Annotation of XNU/osfmk/kern/machine.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: /*
                     53:  *     File:   kern/machine.c
                     54:  *     Author: Avadis Tevanian, Jr.
                     55:  *     Date:   1987
                     56:  *
                     57:  *     Support for machine independent machine abstraction.
                     58:  */
                     59: 
                     60: #include <cpus.h>
                     61: #include <mach_host.h>
                     62: 
                     63: #include <string.h>
                     64: #include <mach/boolean.h>
                     65: #include <mach/kern_return.h>
                     66: #include <mach/mach_types.h>
                     67: #include <mach/machine.h>
                     68: #include <mach/host_info.h>
                     69: #include <mach/host_reboot.h>
                     70: #include <kern/counters.h>
                     71: #include <kern/cpu_data.h>
                     72: #include <kern/ipc_host.h>
                     73: #include <kern/host.h>
                     74: #include <kern/lock.h>
                     75: #include <kern/machine.h>
                     76: #include <kern/processor.h>
                     77: #include <kern/queue.h>
                     78: #include <kern/sched.h>
                     79: #include <kern/task.h>
                     80: #include <kern/thread.h>
                     81: #include <kern/thread_swap.h>
                     82: #include <kern/misc_protos.h>
                     83: 
                     84: #include <mach/mach_host_server.h>
                     85: 
                     86: 
                     87: /*
                     88:  *     Exported variables:
                     89:  */
                     90: 
                     91: struct machine_info    machine_info;
                     92: struct machine_slot    machine_slot[NCPUS];
                     93: 
                     94: queue_head_t   action_queue;   /* assign/shutdown queue */
                     95: decl_simple_lock_data(,action_lock)
                     96: 
                     97: static thread_call_t           processor_action_call;
                     98: 
                     99: /* Forwards */
                    100: processor_set_t        processor_request_action(
                    101:                                        processor_t                     processor,
                    102:                                        processor_set_t         new_pset);
                    103: 
                    104: void           processor_doaction(
                    105:                                processor_t             processor);
                    106: 
                    107: void           processor_doshutdown(
                    108:                                processor_t             processor);
                    109: 
                    110: int                    thread_stop_freeze(
                    111:                                thread_t                        thread,
                    112:                                processor_set_t         pset); 
                    113: 
                    114: /*
                    115:  *     cpu_up:
                    116:  *
                    117:  *     Flag specified cpu as up and running.  Called when a processor comes
                    118:  *     online.
                    119:  */
                    120: void
                    121: cpu_up(
                    122:        int             cpu)
                    123: {
                    124:        processor_t                             processor;
                    125:        struct machine_slot             *ms;
                    126:        spl_t                                   s;
                    127: 
                    128:        processor = cpu_to_processor(cpu);
                    129:        /*
                    130:         * Can't risk blocking with no current thread established.
                    131:         * Just twiddle our thumbs; we've got nothing better to do
                    132:         * yet, anyway.
                    133:         */
                    134:        while (!pset_lock_try(&default_pset))
                    135:                continue;
                    136: 
                    137:        s = splsched();
                    138:        processor_lock(processor);
                    139: #if    NCPUS > 1
                    140:        init_ast_check(processor);
                    141: #endif /* NCPUS > 1 */
                    142:        ms = &machine_slot[cpu];
                    143:        ms->running = TRUE;
                    144:        machine_info.avail_cpus++;
                    145:        pset_add_processor(&default_pset, processor);
                    146:        processor->state = PROCESSOR_RUNNING;
                    147:        processor_unlock(processor);
                    148:        splx(s);
                    149:        pset_unlock(&default_pset);
                    150: }
                    151: 
                    152: /*
                    153:  *     cpu_down:
                    154:  *
                    155:  *     Flag specified cpu as down.  Called when a processor is about to
                    156:  *     go offline.
                    157:  */
                    158: 
                    159: void
                    160: cpu_down(
                    161:        int             cpu)
                    162: {
                    163:        processor_t                             processor;
                    164:        struct machine_slot             *ms;
                    165:        spl_t                                   s;
                    166: 
                    167:        processor = cpu_to_processor(cpu);
                    168: 
                    169:        s = splsched();
                    170:        processor_lock(processor);
                    171:        ms = &machine_slot[cpu];
                    172:        ms->running = FALSE;
                    173:        machine_info.avail_cpus--;
                    174:        /*
                    175:         *      processor has already been removed from pset.
                    176:         */
                    177:        processor->processor_set_next = PROCESSOR_SET_NULL;
                    178:        processor->state = PROCESSOR_OFF_LINE;
                    179:        processor_unlock(processor);
                    180:        splx(s);
                    181: }
                    182: 
                    183: kern_return_t
                    184: host_reboot(
                    185:        host_t                  host,
                    186:        int                             options)
                    187: {
                    188:        if (host == HOST_NULL)
                    189:                return (KERN_INVALID_HOST);
                    190: 
                    191:        if (options & HOST_REBOOT_DEBUGGER) {
                    192:                Debugger("Debugger");
                    193:        }
                    194:        else
                    195:                halt_all_cpus(!(options & HOST_REBOOT_HALT));
                    196: 
                    197:        return (KERN_SUCCESS);
                    198: }
                    199: 
                    200: #if    NCPUS > 1
                    201: /*
                    202:  *     processor_request_action - common internals of processor_assign
                    203:  *             and processor_shutdown.  If new_pset is null, this is
                    204:  *             a shutdown, else it's an assign and caller must donate
                    205:  *             a reference.  For assign operations, it returns 
                    206:  *             an old pset that must be deallocated if it's not NULL.  For
                    207:  *             shutdown operations, it always returns PROCESSOR_SET_NULL.
                    208:  */
                    209: processor_set_t
                    210: processor_request_action(
                    211:        processor_t                     processor,
                    212:        processor_set_t         new_pset)
                    213: {
                    214:     register processor_set_t pset, old_next_pset;
                    215: 
                    216:     /*
                    217:      * Processor must be in a processor set.  Must lock its idle lock to
                    218:      * get at processor state.
                    219:      */
                    220:     pset = processor->processor_set;
                    221:     simple_lock(&pset->idle_lock);
                    222: 
                    223:     /*
                    224:      * If the processor is dispatching, let it finish - it will set its
                    225:      * state to running very soon.
                    226:      */
                    227:     while (*(volatile int *)&processor->state == PROCESSOR_DISPATCHING)
                    228:        continue;
                    229: 
                    230:     /*
                    231:      * Now lock the action queue and do the dirty work.
                    232:      */
                    233:     simple_lock(&action_lock);
                    234: 
                    235:     switch (processor->state) {
                    236: 
                    237:        case PROCESSOR_IDLE:
                    238:            /*
                    239:             *  Remove from idle queue.
                    240:             */
                    241:            queue_remove(&pset->idle_queue,
                    242:                                                        processor, processor_t, processor_queue);
                    243:            pset->idle_count--;
                    244: 
                    245:            /* fall through ... */
                    246:        case PROCESSOR_RUNNING:
                    247:            /*
                    248:             *  Put it on the action queue.
                    249:             */
                    250:            queue_enter(&action_queue,
                    251:                                                        processor, processor_t,processor_queue);
                    252: 
                    253:            /* fall through ... */
                    254:        case PROCESSOR_ASSIGN:
                    255:            /*
                    256:             * And ask the action_thread to do the work.
                    257:             */
                    258: 
                    259:            if (new_pset == PROCESSOR_SET_NULL) {
                    260:                        processor->state = PROCESSOR_SHUTDOWN;
                    261:                        old_next_pset = PROCESSOR_SET_NULL;
                    262:            }
                    263:            else {
                    264:                        processor->state = PROCESSOR_ASSIGN;
                    265:                old_next_pset = processor->processor_set_next;
                    266:                processor->processor_set_next = new_pset;
                    267:            }
                    268:            break;
                    269: 
                    270:        default:
                    271:            printf("state: %d\n", processor->state);
                    272:            panic("processor_request_action: bad state");
                    273:     }
                    274: 
                    275:     simple_unlock(&action_lock);
                    276:     simple_unlock(&pset->idle_lock);
                    277: 
                    278:        thread_call_enter(processor_action_call);
                    279: 
                    280:     return (old_next_pset);
                    281: }
                    282: 
                    283: #if    MACH_HOST
                    284: /*
                    285:  *     processor_assign() changes the processor set that a processor is
                    286:  *     assigned to.  Any previous assignment in progress is overriden.
                    287:  *     Synchronizes with assignment completion if wait is TRUE.
                    288:  */
                    289: kern_return_t
                    290: processor_assign(
                    291:        processor_t                     processor,
                    292:        processor_set_t         new_pset,
                    293:        boolean_t                       wait)
                    294: {
                    295:     register processor_set_t   old_next_pset;
                    296:     spl_t                                              s;
                    297: 
                    298:     /*
                    299:      * Check for null arguments.
                    300:      *  XXX Can't assign master processor.
                    301:      */
                    302:     if (       processor == PROCESSOR_NULL                             ||
                    303:                                new_pset == PROCESSOR_SET_NULL          ||
                    304:                                processor == master_processor)
                    305:            return (KERN_FAILURE);
                    306: 
                    307:     /*
                    308:      * Get pset reference to donate to processor_request_action.
                    309:      */
                    310:     pset_reference(new_pset);
                    311: 
                    312:     s = splsched();
                    313:     processor_lock(processor);
                    314:     if (       processor->state == PROCESSOR_OFF_LINE                  ||
                    315:                                processor->state == PROCESSOR_SHUTDOWN) {
                    316:            /*
                    317:             *  Already shutdown or being shutdown -- Can't reassign.
                    318:             */
                    319:            processor_unlock(processor);
                    320:            splx(s);
                    321:            pset_deallocate(new_pset);
                    322: 
                    323:            return (KERN_FAILURE);
                    324:     }
                    325: 
                    326:     old_next_pset = processor_request_action(processor, new_pset);
                    327: 
                    328: 
                    329:     /*
                    330:      * Synchronization with completion.
                    331:      */
                    332:        while ( wait && (processor->state == PROCESSOR_ASSIGN                    ||
                    333:                                                processor->state == PROCESSOR_SHUTDOWN)) {
                    334:                assert_wait((event_t)processor, THREAD_ABORTSAFE);
                    335:                processor_unlock(processor);
                    336:                splx(s);
                    337: 
                    338:                thread_block((void (*)(void)) 0);
                    339: 
                    340:                s = splsched();
                    341:                processor_lock(processor);
                    342:        }
                    343: 
                    344:     processor_unlock(processor);
                    345:     splx(s);
                    346:     
                    347:     if (old_next_pset != PROCESSOR_SET_NULL)
                    348:        pset_deallocate(old_next_pset);
                    349: 
                    350:     return (KERN_SUCCESS);
                    351: }
                    352: 
                    353: #else  /* MACH_HOST */
                    354: 
                    355: kern_return_t
                    356: processor_assign(
                    357:        processor_t                     processor,
                    358:        processor_set_t         new_pset,
                    359:        boolean_t                       wait)
                    360: {
                    361: #ifdef lint
                    362:        processor++; new_pset++; wait++;
                    363: #endif /* lint */
                    364:        return (KERN_FAILURE);
                    365: }
                    366: 
                    367: #endif /* MACH_HOST */
                    368: 
                    369: /*
                    370:  *     processor_shutdown() queues a processor up for shutdown.
                    371:  *     Any assignment in progress is overriden.  It does not synchronize
                    372:  *     with the shutdown (can be called from interrupt level).
                    373:  */
                    374: kern_return_t
                    375: processor_shutdown(
                    376:        processor_t             processor)
                    377: {
                    378:     spl_t                      s;
                    379: 
                    380:     s = splsched();
                    381:     processor_lock(processor);
                    382:     if (       processor->state == PROCESSOR_OFF_LINE                  ||
                    383:                                processor->state == PROCESSOR_SHUTDOWN) {
                    384:            /*
                    385:             *  Already shutdown or being shutdown -- nothing to do.
                    386:             */
                    387:            processor_unlock(processor);
                    388:            splx(s);
                    389: 
                    390:            return (KERN_SUCCESS);
                    391:     }
                    392: 
                    393:     (void) processor_request_action(processor, PROCESSOR_SET_NULL);
                    394:     processor_unlock(processor);
                    395:     splx(s);
                    396: 
                    397:     return (KERN_SUCCESS);
                    398: }
                    399: 
                    400: /*
                    401:  *     processor_action() shuts down processors or changes their assignment.
                    402:  */
                    403: 
                    404: static thread_call_data_t      processor_action_call_data;
                    405: 
                    406: void
                    407: processor_action(void)
                    408: {
                    409:        register processor_t    processor;
                    410:        spl_t                                   s;
                    411: 
                    412:        s = splsched();
                    413:        simple_lock(&action_lock);
                    414: 
                    415:        if (processor_action_call == NULL) {
                    416:                thread_call_setup(&processor_action_call_data,
                    417:                                                                        processor_action, NULL);
                    418:                processor_action_call = &processor_action_call_data;
                    419:        }
                    420: 
                    421:        while (!queue_empty(&action_queue)) {
                    422:                processor = (processor_t) queue_first(&action_queue);
                    423:                queue_remove(&action_queue, processor, processor_t, processor_queue);
                    424:                simple_unlock(&action_lock);
                    425:                splx(s);
                    426: 
                    427:                processor_doaction(processor);
                    428: 
                    429:                s = splsched();
                    430:                simple_lock(&action_lock);
                    431:        }
                    432: 
                    433:        simple_unlock(&action_lock);
                    434:        splx(s);
                    435: }
                    436: 
                    437: /*
                    438:  * thread_stop_freeze
                    439:  *     Block the thread in the kernel and freeze the processor set.
                    440:  * return value:
                    441:  *     TRUE - the thread has blocked interruptibly, is stopped, and
                    442:  *             the processor set assignment is frozen
                    443:  *     FALSE - the thread is no longer in the processor set, so it
                    444:  *             isn't stopped, and the processor set assignment
                    445:  *             is released.
                    446:  */
                    447: int
                    448: thread_stop_freeze(
                    449:        thread_t                        thread,
                    450:        processor_set_t         pset)
                    451: {
                    452: #if 0  /* HACK ALERT!!!! (TEST/DEBUG) */
                    453:        thread_act_t            thr_act;
                    454:        spl_t                           s;
                    455: 
                    456:        /*
                    457:         * hold it, and wait for it to stop.
                    458:         */
                    459:        thr_act = thread_lock_act(thread);
                    460:        thread_hold(thr_act);
                    461:        act_unlock_thread(thr_act);
                    462: 
                    463:        thread_stop(thread);
                    464: 
                    465:        s = splsched();
                    466:        wake_lock(thread);
                    467:         while( thread->state & (TH_RUN|TH_UNINT) ) {
                    468:                 thread->wake_active = TRUE;
                    469:                 assert_wait((event_t)&thread->wake_active, THREAD_UNINT);
                    470:                 wake_unlock(thread);
                    471:                 splx(s);
                    472:                 thread_block( (void (*)(void)) 0 );
                    473:                 (void) splsched();
                    474:                 wake_lock(thread);
                    475:         }
                    476: 
                    477:        /*
                    478:         * Now, the thread has blocked uninterruptibly; freeze the 
                    479:         * assignment and make sure it's still part of the processor set.
                    480:         */
                    481:        wake_unlock(thread);
                    482:        thread_freeze(thread);
                    483:        thread_lock(thread);
                    484: 
                    485:        /*
                    486:         * if the processor set has changed, release the freeze and
                    487:         * then unstop it.
                    488:         */
                    489:        if( thread->processor_set != pset ) {
                    490:                thread_unlock(thread);
                    491:                splx(s);
                    492:                thread_unfreeze(thread);
                    493:                thread_unstop(thread);
                    494:                return FALSE;
                    495:        }
                    496:        thread_unlock(thread);
                    497:        splx(s);
                    498: #endif                 /* HACK ALERT!!!! */
                    499: 
                    500:        return TRUE;
                    501: }
                    502: 
                    503: /*
                    504:  *     processor_doaction actually does the shutdown.  The trick here
                    505:  *     is to schedule ourselves onto a cpu and then save our
                    506:  *     context back into the runqs before taking out the cpu.
                    507:  */
                    508: 
                    509: void
                    510: processor_doaction(
                    511:        processor_t                                     processor)
                    512: {
                    513:        thread_t                                        this_thread;
                    514:        spl_t                                           s;
                    515:        register processor_set_t        pset;
                    516: #if    MACH_HOST
                    517:        register processor_set_t        new_pset;
                    518:        register thread_t                       thread;
                    519:        register thread_t                       prev_thread = THREAD_NULL;
                    520:        thread_act_t                            thr_act;
                    521:        boolean_t                                       have_pset_ref = FALSE;
                    522: #endif /* MACH_HOST */
                    523: 
                    524:        /*
                    525:         *      Get onto the processor to shutdown
                    526:         */
                    527:        this_thread = current_thread();
                    528:        thread_bind(this_thread, processor);
                    529:        thread_block((void (*)(void)) 0);
                    530: 
                    531:        pset = processor->processor_set;
                    532: #if    MACH_HOST
                    533:        /*
                    534:         *      If this is the last processor in the processor_set,
                    535:         *      stop all the threads first.
                    536:         */
                    537:        pset_lock(pset);
                    538:        if (pset->processor_count == 1) {
                    539:                thread = (thread_t) queue_first(&pset->threads);
                    540:                prev_thread = THREAD_NULL;
                    541:                pset->ref_count++;
                    542:                have_pset_ref = TRUE;
                    543:                pset->empty = TRUE;
                    544: 
                    545:                /*
                    546:                 * loop through freezing the processor set assignment
                    547:                 * and reference counting the threads;
                    548:                 */
                    549:                while (!queue_end(&pset->threads, (queue_entry_t) thread)) {
                    550:                    thread_reference(thread);
                    551:                    pset_unlock(pset);
                    552: 
                    553:                    /*
                    554:                     * Freeze the thread on the processor set.
                    555:                     * If it's moved, just release the reference.
                    556:                     * Get the next thread in the processor set list
                    557:                     * from the last one which was frozen.
                    558:                     */
                    559:                    if (thread_stop_freeze(thread, pset))
                    560:                        prev_thread = thread;
                    561:                    else
                    562:                                thread_deallocate(thread);
                    563: 
                    564:                    pset_lock(pset);
                    565:                    if (prev_thread != THREAD_NULL) 
                    566:                        thread = (thread_t)queue_next(&prev_thread->pset_threads);
                    567:                    else
                    568:                                thread = (thread_t) queue_first(&pset->threads);
                    569:                }
                    570: 
                    571:                /*
                    572:                 * Remove the processor from the set so that when the threads
                    573:                 * are unstopped below the ones blocked in the kernel don't
                    574:                 * start running again.
                    575:                 */
                    576:                s = splsched();
                    577:                processor_lock(processor);
                    578:                pset_remove_processor(pset, processor);
                    579: 
                    580:                /*
                    581:                 * Prevent race with another processor being added to the set
                    582:                 * See code after Restart_pset:
                    583:                 *   while(new_pset->empty && new_pset->processor_count > 0)
                    584:                 *
                    585:                 * ... it tests for the condition where a new processor is
                    586:                 * added to the set while the last one is still being removed.
                    587:                 */
                    588:                pset->processor_count++;        /* block new processors being added */
                    589:                assert(pset->processor_count == 1);
                    590: 
                    591:                /*
                    592:                 * Release the thread assignment locks, unstop the threads and
                    593:                 * release the thread references which were taken above.
                    594:                 */
                    595:                thread = (thread_t) queue_first(&pset->threads);
                    596:                while(!queue_empty(&pset->threads) && (thread != THREAD_NULL)) {
                    597:                    prev_thread = thread;
                    598:                    if (queue_end(&pset->threads, (queue_entry_t) thread))
                    599:                                thread = THREAD_NULL;
                    600:                    else
                    601:                        thread = (thread_t) queue_next(&prev_thread->pset_threads);
                    602: 
                    603:                    pset_unlock(pset);
                    604:                    thread_unfreeze(prev_thread);
                    605:                    thread_unstop(prev_thread);
                    606:                    thread_deallocate(prev_thread);
                    607:                    pset_lock(pset);
                    608:                }
                    609:                /*
                    610:                 * allow a processor to be added to the empty pset
                    611:                 */
                    612:                pset->processor_count--;
                    613:        }
                    614:        else { 
                    615:                /* not last processor in set */
                    616: #endif /* MACH_HOST */
                    617:                /*
                    618:                 * At this point, it is ok to rm the processor from the pset.
                    619:                 */
                    620:                s = splsched();
                    621:                processor_lock(processor);
                    622:                pset_remove_processor(pset, processor);
                    623: #if    MACH_HOST
                    624:        }
                    625:        pset_unlock(pset);
                    626: 
                    627:        /*
                    628:         *      Copy the next pset pointer into a local variable and clear
                    629:         *      it because we are taking over its reference.
                    630:         */
                    631:        new_pset = processor->processor_set_next;
                    632:        processor->processor_set_next = PROCESSOR_SET_NULL;
                    633: 
                    634:        if (processor->state == PROCESSOR_ASSIGN) {
                    635: 
                    636: Restart_pset:
                    637:            /*
                    638:             *  Nasty problem: we want to lock the target pset, but
                    639:             *  we have to enable interrupts to do that which requires
                    640:             *  dropping the processor lock.  While the processor
                    641:             *  is unlocked, it could be reassigned or shutdown.
                    642:             */
                    643:            processor_unlock(processor);
                    644:            splx(s);
                    645: 
                    646:            /*
                    647:             *  Lock target pset and handle remove last / assign first race.
                    648:             *  Only happens if there is more than one action thread.
                    649:             */
                    650:            pset_lock(new_pset);
                    651:            while (new_pset->empty && new_pset->processor_count > 0) {
                    652:                        pset_unlock(new_pset);
                    653:                        while (         *(volatile boolean_t *)&new_pset->empty         &&
                    654:                                                        *(volatile int *)&new_pset->processor_count > 0)
                    655:                                continue;
                    656:                        pset_lock(new_pset);
                    657:            }
                    658: 
                    659:            /*
                    660:             *  Finally relock the processor and see if something changed.
                    661:             *  The only possibilities are assignment to a different pset
                    662:             *  and shutdown.
                    663:             */
                    664:            s = splsched();
                    665:            processor_lock(processor);
                    666: 
                    667:            if (processor->state == PROCESSOR_SHUTDOWN) {
                    668:                        pset_unlock(new_pset);
                    669:                        goto shutdown;                  /* will release pset reference */
                    670:            }
                    671: 
                    672:            if (processor->processor_set_next != PROCESSOR_SET_NULL) {
                    673:                        /*
                    674:                         *      Processor was reassigned.  Drop the reference
                    675:                         *      we have on the wrong new_pset, and get the
                    676:                         *      right one.  Involves lots of lock juggling.
                    677:                         */
                    678:                        processor_unlock(processor);
                    679:                        splx(s);
                    680:                        pset_unlock(new_pset);
                    681:                        pset_deallocate(new_pset);
                    682: 
                    683:                        s = splsched();
                    684:                processor_lock(processor);
                    685:                        new_pset = processor->processor_set_next;
                    686:                        processor->processor_set_next = PROCESSOR_SET_NULL;
                    687:                        goto Restart_pset;
                    688:            }
                    689: 
                    690:            /*
                    691:             *  If the pset has been deactivated since the operation
                    692:             *  was requested, redirect to the default pset.
                    693:             */
                    694:            if (!new_pset->active) {
                    695:                        pset_unlock(new_pset);
                    696:                        pset_deallocate(new_pset);
                    697:                        new_pset = &default_pset;
                    698:                        apset_lock(new_pset);
                    699:                        new_pset->ref_count++;
                    700:            }
                    701: 
                    702:            /*
                    703:             *  Do assignment, then wakeup anyone waiting for it.
                    704:             *  Finally context switch to have it take effect.
                    705:             */
                    706:            pset_add_processor(new_pset, processor);
                    707:            if (new_pset->empty) {
                    708:                        /*
                    709:                         *      Set all the threads loose
                    710:                         */
                    711:                        thread = (thread_t) queue_first(&new_pset->threads);
                    712:                        while (!queue_end(&new_pset->threads,(queue_entry_t)thread)) {
                    713:                                thr_act = thread_lock_act(thread);
                    714:                                thread_release(thread->top_act);
                    715:                                act_unlock_thread(thr_act);
                    716:                                thread = (thread_t) queue_next(&thread->pset_threads);
                    717:                        }
                    718: 
                    719:                        new_pset->empty = FALSE;
                    720:            }
                    721:            processor->processor_set_next = PROCESSOR_SET_NULL;
                    722:            processor->state = PROCESSOR_RUNNING;
                    723:            thread_wakeup((event_t)processor);
                    724:            processor_unlock(processor);
                    725:            splx(s);
                    726:            pset_unlock(new_pset);
                    727: 
                    728:            /*
                    729:             *  Clean up dangling references, and release our binding.
                    730:             */
                    731:            pset_deallocate(new_pset);
                    732:            if (have_pset_ref)
                    733:                        pset_deallocate(pset);
                    734: 
                    735:            if (prev_thread != THREAD_NULL)
                    736:                        thread_deallocate(prev_thread);
                    737: 
                    738:            thread_bind(this_thread, PROCESSOR_NULL);
                    739: 
                    740:            thread_block((void (*)(void)) 0);
                    741:            return;
                    742:        }
                    743: 
                    744: shutdown:
                    745: #endif /* MACH_HOST */
                    746:        
                    747:        /*
                    748:         *      Do shutdown, make sure we live when processor dies.
                    749:         */
                    750:        if (processor->state != PROCESSOR_SHUTDOWN) {
                    751:                printf("state: %d\n", processor->state);
                    752:                panic("action_thread -- bad processor state");
                    753:        }
                    754:        processor_unlock(processor);
                    755:        /*
                    756:         *      Clean up dangling references, and release our binding.
                    757:         */
                    758: #if    MACH_HOST
                    759:        if (new_pset != PROCESSOR_SET_NULL)
                    760:                pset_deallocate(new_pset);
                    761:        if (have_pset_ref)
                    762:                pset_deallocate(pset);
                    763:        if (prev_thread != THREAD_NULL)
                    764:                thread_deallocate(prev_thread);
                    765: #endif /* MACH_HOST */
                    766: 
                    767:        thread_bind(this_thread, PROCESSOR_NULL);
                    768:        switch_to_shutdown_context(this_thread, processor_doshutdown, processor);
                    769:        splx(s);
                    770: }
                    771: 
                    772: /*
                    773:  *     Actually do the processor shutdown.  This is called at splsched,
                    774:  *     running on the processor's shutdown stack.
                    775:  */
                    776: 
                    777: void
                    778: processor_doshutdown(
                    779:        processor_t             processor)
                    780: {
                    781:        register int    cpu = processor->slot_num;
                    782: 
                    783:        timer_switch(&kernel_timer[cpu]);
                    784: 
                    785:        /*
                    786:         *      OK, now exit this cpu.
                    787:         */
                    788:        PMAP_DEACTIVATE_KERNEL(cpu);
                    789:        cpu_data[cpu].active_thread = THREAD_NULL;
                    790:        active_kloaded[cpu] = THR_ACT_NULL;
                    791:        cpu_down(cpu);
                    792:        thread_wakeup((event_t)processor);
                    793:        halt_cpu();
                    794:        panic("zombie processor");
                    795: 
                    796:        /*
                    797:         *      The action thread returns to life after the call to
                    798:         *      switch_to_shutdown_context above, on some other cpu.
                    799:         */
                    800: 
                    801:        /*NOTREACHED*/
                    802: }
                    803: #else  /* NCPUS > 1 */
                    804: 
                    805: kern_return_t
                    806: processor_assign(
                    807:        processor_t                     processor,
                    808:        processor_set_t         new_pset,
                    809:        boolean_t                       wait)
                    810: {
                    811: #ifdef lint
                    812:        processor++; new_pset++; wait++;
                    813: #endif /* lint */
                    814:        return (KERN_FAILURE);
                    815: }
                    816: 
                    817: #endif /* NCPUS > 1 */
                    818: 
                    819: kern_return_t
                    820: host_get_boot_info(
                    821:         host_t              priv_host,
                    822:         kernel_boot_info_t  boot_info)
                    823: {
                    824:        char *src = "";
                    825:        extern char *machine_boot_info(
                    826:                                kernel_boot_info_t      boot_info,
                    827:                                vm_size_t                       buf_len);
                    828: 
                    829:        if (priv_host == HOST_NULL)
                    830:                return (KERN_INVALID_HOST);
                    831: 
                    832:        /*
                    833:         * Copy first operator string terminated by '\0' followed by
                    834:         *      standardized strings generated from boot string.
                    835:         */
                    836:        src = machine_boot_info(boot_info, KERNEL_BOOT_INFO_MAX);
                    837:        if (src != boot_info)
                    838:                (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
                    839: 
                    840:        return (KERN_SUCCESS);
                    841: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.