Annotation of OSKit-Mach/kern/machine.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
                      4:  * Copyright (c) 1993,1994 The University of Utah and
                      5:  * the Computer Systems Laboratory (CSL).
                      6:  * All rights reserved.
                      7:  *
                      8:  * Permission to use, copy, modify and distribute this software and its
                      9:  * documentation is hereby granted, provided that both the copyright
                     10:  * notice and this permission notice appear in all copies of the
                     11:  * software, derivative works or modified versions, and any portions
                     12:  * thereof, and that both notices appear in supporting documentation.
                     13:  *
                     14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
                     15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
                     16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
                     17:  * THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  [email protected]
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29: /*
                     30:  *     File:   kern/machine.c
                     31:  *     Author: Avadis Tevanian, Jr.
                     32:  *     Date:   1987
                     33:  *
                     34:  *     Support for machine independent machine abstraction.
                     35:  */
                     36: 
                     37: #include <norma_ether.h>
                     38: #include <cpus.h>
                     39: #include <mach_host.h>
                     40: 
                     41: #include <mach/boolean.h>
                     42: #include <mach/kern_return.h>
                     43: #include <mach/mach_types.h>
                     44: #include <mach/machine.h>
                     45: #include <mach/host_info.h>
                     46: #include <kern/counters.h>
                     47: #include <kern/ipc_host.h>
                     48: #include <kern/host.h>
                     49: #include <kern/lock.h>
                     50: #include <kern/processor.h>
                     51: #include <kern/queue.h>
                     52: #include <kern/sched.h>
                     53: #include <kern/task.h>
                     54: #include <kern/thread.h>
                     55: #include <machine/machspl.h>   /* for splsched */
                     56: #include <sys/reboot.h>
                     57: 
                     58: #include <oskit/gdb.h>
                     59: 
                     60: 
                     61: /*
                     62:  *     Exported variables:
                     63:  */
                     64: 
                     65: struct machine_info    machine_info;
                     66: struct machine_slot    machine_slot[NCPUS];
                     67: 
                     68: queue_head_t   action_queue;   /* assign/shutdown queue */
                     69: decl_simple_lock_data(,action_lock);
                     70: 
                     71: /*
                     72:  *     xxx_host_info:
                     73:  *
                     74:  *     Return the host_info structure.  This routine is exported to the
                     75:  *     user level.
                     76:  */
                     77: kern_return_t xxx_host_info(task, info)
                     78:        task_t          task;
                     79:        machine_info_t  info;
                     80: {
                     81: #ifdef lint
                     82:        task++;
                     83: #endif /* lint */
                     84:        *info = machine_info;
                     85:        return(KERN_SUCCESS);
                     86: }
                     87: 
                     88: /*
                     89:  *     xxx_slot_info:
                     90:  *
                     91:  *     Return the slot_info structure for the specified slot.  This routine
                     92:  *     is exported to the user level.
                     93:  */
                     94: kern_return_t xxx_slot_info(task, slot, info)
                     95:        task_t          task;
                     96:        int             slot;
                     97:        machine_slot_t  info;
                     98: {
                     99: #ifdef lint
                    100:        task++;
                    101: #endif /* lint */
                    102:        if ((slot < 0) || (slot >= NCPUS))
                    103:                return(KERN_INVALID_ARGUMENT);
                    104:        *info = machine_slot[slot];
                    105:        return(KERN_SUCCESS);
                    106: }
                    107: 
                    108: /*
                    109:  *     xxx_cpu_control:
                    110:  *
                    111:  *     Support for user control of cpus.  The user indicates which cpu
                    112:  *     he is interested in, and whether or not that cpu should be running.
                    113:  */
                    114: kern_return_t xxx_cpu_control(task, cpu, runnable)
                    115:        task_t          task;
                    116:        int             cpu;
                    117:        boolean_t       runnable;
                    118: {
                    119: #ifdef lint
                    120:        task++; cpu++; runnable++;
                    121: #endif /* lint */
                    122:        return(KERN_FAILURE);
                    123: }
                    124: 
                    125: /*
                    126:  *     cpu_up:
                    127:  *
                    128:  *     Flag specified cpu as up and running.  Called when a processor comes
                    129:  *     online.
                    130:  */
                    131: void cpu_up(cpu)
                    132:        int     cpu;
                    133: {
                    134:        register struct machine_slot    *ms;
                    135:        register processor_t    processor;
                    136:        register spl_t s;
                    137: 
                    138:        processor = cpu_to_processor(cpu);
                    139:        pset_lock(&default_pset);
                    140:        s = splsched();
                    141:        processor_lock(processor);
                    142: #if    NCPUS > 1
                    143:        init_ast_check(processor);
                    144: #endif /* NCPUS > 1 */
                    145:        ms = &machine_slot[cpu];
                    146:        ms->running = TRUE;
                    147:        machine_info.avail_cpus++;
                    148:        pset_add_processor(&default_pset, processor);
                    149:        processor->state = PROCESSOR_RUNNING;
                    150:        processor_unlock(processor);
                    151:        splx(s);
                    152:        pset_unlock(&default_pset);
                    153: }
                    154: 
                    155: /*
                    156:  *     cpu_down:
                    157:  *
                    158:  *     Flag specified cpu as down.  Called when a processor is about to
                    159:  *     go offline.
                    160:  */
                    161: void cpu_down(cpu)
                    162:        int     cpu;
                    163: {
                    164:        register struct machine_slot    *ms;
                    165:        register processor_t    processor;
                    166:        register spl_t  s;
                    167: 
                    168:        s = splsched();
                    169:        processor = cpu_to_processor(cpu);
                    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(host, options)
                    185:        host_t  host;
                    186:        int     options;
                    187: {
                    188:        if (host == HOST_NULL)
                    189:                return (KERN_INVALID_HOST);
                    190: 
                    191:        if (options & RB_DEBUGGER) {
                    192:                gdb_breakpoint();
                    193:                panic("host_reboot with RB_DEBUGGER flag");
                    194:        } else {
                    195: #ifdef parisc
                    196: /* XXX this could be made common */
                    197:                halt_all_cpus(options);
                    198: #else
                    199:                halt_all_cpus(!(options & RB_HALT));
                    200: #endif
                    201:        }
                    202:        return (KERN_SUCCESS);
                    203: }
                    204: 
                    205: #if    NCPUS > 1
                    206: /*
                    207:  *     processor_request_action - common internals of processor_assign
                    208:  *             and processor_shutdown.  If new_pset is null, this is
                    209:  *             a shutdown, else it's an assign and caller must donate
                    210:  *             a reference.
                    211:  */
                    212: void
                    213: processor_request_action(processor, new_pset)
                    214: processor_t    processor;
                    215: processor_set_t        new_pset;
                    216: {
                    217:     register processor_set_t pset;
                    218: 
                    219:     /*
                    220:      * Processor must be in a processor set.  Must lock its idle lock to
                    221:      * get at processor state.
                    222:      */
                    223:     pset = processor->processor_set;
                    224:     simple_lock(&pset->idle_lock);
                    225: 
                    226:     /*
                    227:      * If the processor is dispatching, let it finish - it will set its
                    228:      * state to running very soon.
                    229:      */
                    230:     while (*(volatile int *)&processor->state == PROCESSOR_DISPATCHING)
                    231:        continue;
                    232: 
                    233:     /*
                    234:      * Now lock the action queue and do the dirty work.
                    235:      */
                    236:     simple_lock(&action_lock);
                    237: 
                    238:     switch (processor->state) {
                    239:        case PROCESSOR_IDLE:
                    240:            /*
                    241:             *  Remove from idle queue.
                    242:             */
                    243:            queue_remove(&pset->idle_queue, processor,  processor_t,
                    244:                processor_queue);
                    245:            pset->idle_count--;
                    246: 
                    247:            /* fall through ... */
                    248:        case PROCESSOR_RUNNING:
                    249:            /*
                    250:             *  Put it on the action queue.
                    251:             */
                    252:            queue_enter(&action_queue, processor, processor_t,
                    253:                processor_queue);
                    254: 
                    255:            /* fall through ... */
                    256:        case PROCESSOR_ASSIGN:
                    257:            /*
                    258:             * And ask the action_thread to do the work.
                    259:             */
                    260: 
                    261:            if (new_pset == PROCESSOR_SET_NULL) {
                    262:                processor->state = PROCESSOR_SHUTDOWN;
                    263:            }
                    264:            else {
                    265:                assert(processor->state != PROCESSOR_ASSIGN);
                    266:                processor->state = PROCESSOR_ASSIGN;
                    267:                processor->processor_set_next = new_pset;
                    268:            }
                    269:            break;
                    270: 
                    271:        default:
                    272:            printf("state: %d\n", processor->state);
                    273:            panic("processor_request_action: bad state");
                    274:     }
                    275:     simple_unlock(&action_lock);
                    276:     simple_unlock(&pset->idle_lock);
                    277: 
                    278:     thread_wakeup((event_t)&action_queue);
                    279: }
                    280: 
                    281: #if    MACH_HOST
                    282: /*
                    283:  *     processor_assign() changes the processor set that a processor is
                    284:  *     assigned to.  Any previous assignment in progress is overridden.
                    285:  *     Synchronizes with assignment completion if wait is TRUE.
                    286:  */
                    287: kern_return_t
                    288: processor_assign(processor, new_pset, wait)
                    289: processor_t    processor;
                    290: processor_set_t        new_pset;
                    291: boolean_t      wait;
                    292: {
                    293:     spl_t              s;
                    294: 
                    295:     /*
                    296:      * Check for null arguments.
                    297:      *  XXX Can't assign master processor.
                    298:      */
                    299:     if (processor == PROCESSOR_NULL || new_pset == PROCESSOR_SET_NULL ||
                    300:        processor == master_processor) {
                    301:            return(KERN_INVALID_ARGUMENT);
                    302:     }
                    303: 
                    304:     /*
                    305:      * Get pset reference to donate to processor_request_action.
                    306:      */
                    307:     pset_reference(new_pset);
                    308: 
                    309:     /*
                    310:      * Check processor status.
                    311:      * If shutdown or being shutdown, can`t reassign.
                    312:      * If being assigned, wait for assignment to finish.
                    313:      */
                    314: Retry:
                    315:     s = splsched();
                    316:     processor_lock(processor);
                    317:     if(processor->state == PROCESSOR_OFF_LINE ||
                    318:        processor->state == PROCESSOR_SHUTDOWN) {
                    319:            /*
                    320:             *  Already shutdown or being shutdown -- Can't reassign.
                    321:             */
                    322:            processor_unlock(processor);
                    323:            (void) splx(s);
                    324:            pset_deallocate(new_pset);
                    325:            return(KERN_FAILURE);
                    326:     }
                    327: 
                    328:     if (processor->state == PROCESSOR_ASSIGN) {
                    329:        assert_wait((event_t) processor, TRUE);
                    330:        processor_unlock(processor);
                    331:        splx(s);
                    332:        thread_block((void(*)()) 0);
                    333:        goto Retry;
                    334:     }
                    335: 
                    336:     /*
                    337:      * Avoid work if processor is already in this processor set.
                    338:      */
                    339:     if (processor->processor_set == new_pset)  {
                    340:        processor_unlock(processor);
                    341:        (void) splx(s);
                    342:        /* clean up dangling ref */
                    343:        pset_deallocate(new_pset);
                    344:        return(KERN_SUCCESS);
                    345:     }
                    346: 
                    347:     /*
                    348:      * OK to start processor assignment.
                    349:      */
                    350:     processor_request_action(processor, new_pset);
                    351: 
                    352:     /*
                    353:      * Synchronization with completion.
                    354:      */
                    355:     if (wait) {
                    356:        while (processor->state == PROCESSOR_ASSIGN ||
                    357:            processor->state == PROCESSOR_SHUTDOWN) {
                    358:                assert_wait((event_t)processor, TRUE);
                    359:                processor_unlock(processor);
                    360:                splx(s);
                    361:                thread_block((void (*)()) 0);
                    362:                s = splsched();
                    363:                processor_lock(processor);
                    364:        }
                    365:     }
                    366:     processor_unlock(processor);
                    367:     splx(s);
                    368: 
                    369:     return(KERN_SUCCESS);
                    370: }
                    371: 
                    372: #else  /* MACH_HOST */
                    373: 
                    374: kern_return_t
                    375: processor_assign(processor, new_pset, wait)
                    376: processor_t    processor;
                    377: processor_set_t        new_pset;
                    378: boolean_t      wait;
                    379: {
                    380: #ifdef lint
                    381:        processor++; new_pset++; wait++;
                    382: #endif
                    383:        return KERN_FAILURE;
                    384: }
                    385: 
                    386: #endif /* MACH_HOST */
                    387: 
                    388: /*
                    389:  *     processor_shutdown() queues a processor up for shutdown.
                    390:  *     Any assignment in progress is overriden.  It does not synchronize
                    391:  *     with the shutdown (can be called from interrupt level).
                    392:  */
                    393: kern_return_t
                    394: processor_shutdown(processor)
                    395: processor_t    processor;
                    396: {
                    397:     spl_t              s;
                    398: 
                    399:     if (processor == PROCESSOR_NULL)
                    400:        return KERN_INVALID_ARGUMENT;
                    401: 
                    402:     s = splsched();
                    403:     processor_lock(processor);
                    404:     if(processor->state == PROCESSOR_OFF_LINE ||
                    405:        processor->state == PROCESSOR_SHUTDOWN) {
                    406:            /*
                    407:             *  Already shutdown or being shutdown -- nothing to do.
                    408:             */
                    409:            processor_unlock(processor);
                    410:            splx(s);
                    411:            return(KERN_SUCCESS);
                    412:     }
                    413: 
                    414:     processor_request_action(processor, PROCESSOR_SET_NULL);
                    415:     processor_unlock(processor);
                    416:     splx(s);
                    417: 
                    418:     return(KERN_SUCCESS);
                    419: }
                    420: 
                    421: /*
                    422:  *     action_thread() shuts down processors or changes their assignment.
                    423:  */
                    424: void   processor_doaction();   /* forward */
                    425: 
                    426: void action_thread_continue()
                    427: {
                    428:        register processor_t    processor;
                    429:        register spl_t          s;
                    430: 
                    431:        while (TRUE) {
                    432:                s = splsched();
                    433:                simple_lock(&action_lock);
                    434:                while ( !queue_empty(&action_queue)) {
                    435:                        processor = (processor_t) queue_first(&action_queue);
                    436:                        queue_remove(&action_queue, processor, processor_t,
                    437:                                     processor_queue);
                    438:                        simple_unlock(&action_lock);
                    439:                        (void) splx(s);
                    440: 
                    441:                        processor_doaction(processor);
                    442: 
                    443:                        s = splsched();
                    444:                        simple_lock(&action_lock);
                    445:                }
                    446: 
                    447:                assert_wait((event_t) &action_queue, FALSE);
                    448:                simple_unlock(&action_lock);
                    449:                (void) splx(s);
                    450:                counter(c_action_thread_block++);
                    451:                thread_block(action_thread_continue);
                    452:        }
                    453: }
                    454: 
                    455: void action_thread()
                    456: {
                    457:        action_thread_continue();
                    458:        /*NOTREACHED*/
                    459: }
                    460: 
                    461: /*
                    462:  *     processor_doaction actually does the shutdown.  The trick here
                    463:  *     is to schedule ourselves onto a cpu and then save our
                    464:  *     context back into the runqs before taking out the cpu.
                    465:  */
                    466: #ifdef __GNUC__
                    467: __volatile__
                    468: #endif
                    469: void   processor_doshutdown(); /* forward */
                    470: 
                    471: void processor_doaction(processor)
                    472: register processor_t   processor;
                    473: {
                    474:        thread_t                        this_thread;
                    475:        spl_t                           s;
                    476:        register processor_set_t        pset;
                    477: #if    MACH_HOST
                    478:        register processor_set_t        new_pset;
                    479:        register thread_t               thread;
                    480:        register thread_t               prev_thread = THREAD_NULL;
                    481:        boolean_t                       have_pset_ref = FALSE;
                    482: #endif /* MACH_HOST */
                    483: 
                    484:        /*
                    485:         *      Get onto the processor to shutdown
                    486:         */
                    487:        this_thread = current_thread();
                    488:        thread_bind(this_thread, processor);
                    489:        thread_block((void (*)()) 0);
                    490: 
                    491:        pset = processor->processor_set;
                    492: #if    MACH_HOST
                    493:        /*
                    494:         *      If this is the last processor in the processor_set,
                    495:         *      stop all the threads first.
                    496:         */
                    497:        pset_lock(pset);
                    498:        if (pset->processor_count == 1) {
                    499:                /*
                    500:                 *      First suspend all of them.
                    501:                 */
                    502:                queue_iterate(&pset->threads, thread, thread_t, pset_threads) {
                    503:                        thread_hold(thread);
                    504:                }
                    505:                pset->empty = TRUE;
                    506:                /*
                    507:                 *      Now actually stop them.  Need a pset reference.
                    508:                 */
                    509:                pset->ref_count++;
                    510:                have_pset_ref = TRUE;
                    511: 
                    512: Restart_thread:
                    513:                prev_thread = THREAD_NULL;
                    514:                queue_iterate(&pset->threads, thread, thread_t, pset_threads) {
                    515:                        thread_reference(thread);
                    516:                        pset_unlock(pset);
                    517:                        if (prev_thread != THREAD_NULL)
                    518:                                thread_deallocate(prev_thread);
                    519: 
                    520:                        /*
                    521:                         *      Only wait for threads still in the pset.
                    522:                         */
                    523:                        thread_freeze(thread);
                    524:                        if (thread->processor_set != pset) {
                    525:                                /*
                    526:                                 *      It got away - start over.
                    527:                                 */
                    528:                                thread_unfreeze(thread);
                    529:                                thread_deallocate(thread);
                    530:                                pset_lock(pset);
                    531:                                goto Restart_thread;
                    532:                        }
                    533: 
                    534:                        (void) thread_dowait(thread, TRUE);
                    535:                        prev_thread = thread;
                    536:                        pset_lock(pset);
                    537:                        thread_unfreeze(prev_thread);
                    538:                }
                    539:        }
                    540:        pset_unlock(pset);
                    541: 
                    542:        /*
                    543:         *      At this point, it is ok to remove the processor from the pset.
                    544:         *      We can use processor->processor_set_next without locking the
                    545:         *      processor, since it cannot change while processor->state is
                    546:         *      PROCESSOR_ASSIGN or PROCESSOR_SHUTDOWN.
                    547:         */
                    548: 
                    549:        new_pset = processor->processor_set_next;
                    550: 
                    551: Restart_pset:
                    552:        if (new_pset) {
                    553:            /*
                    554:             *  Reassigning processor.
                    555:             */
                    556: 
                    557:            if ((integer_t) pset < (integer_t) new_pset) {
                    558:                pset_lock(pset);
                    559:                pset_lock(new_pset);
                    560:            }
                    561:            else {
                    562:                pset_lock(new_pset);
                    563:                pset_lock(pset);
                    564:            }
                    565:            if (!(new_pset->active)) {
                    566:                pset_unlock(new_pset);
                    567:                pset_unlock(pset);
                    568:                pset_deallocate(new_pset);
                    569:                new_pset = &default_pset;
                    570:                pset_reference(new_pset);
                    571:                goto Restart_pset;
                    572:            }
                    573: 
                    574:            /*
                    575:             *  Handle remove last / assign first race.
                    576:             *  Only happens if there is more than one action thread.
                    577:             */
                    578:            while (new_pset->empty && new_pset->processor_count > 0) {
                    579:                pset_unlock(new_pset);
                    580:                pset_unlock(pset);
                    581:                while (*(volatile boolean_t *)&new_pset->empty &&
                    582:                       *(volatile int *)&new_pset->processor_count > 0)
                    583:                        /* spin */;
                    584:                goto Restart_pset;
                    585:            }
                    586: 
                    587:            /*
                    588:             *  Lock the processor.  new_pset should not have changed.
                    589:             */
                    590:            s = splsched();
                    591:            processor_lock(processor);
                    592:            assert(processor->processor_set_next == new_pset);
                    593: 
                    594:            /*
                    595:             *  Shutdown may have been requested while this assignment
                    596:             *  was in progress.
                    597:             */
                    598:            if (processor->state == PROCESSOR_SHUTDOWN) {
                    599:                processor->processor_set_next = PROCESSOR_SET_NULL;
                    600:                pset_unlock(new_pset);
                    601:                goto shutdown;  /* releases pset reference */
                    602:            }
                    603: 
                    604:            /*
                    605:             *  Do assignment, then wakeup anyone waiting for it.
                    606:             */
                    607:            pset_remove_processor(pset, processor);
                    608:            pset_unlock(pset);
                    609: 
                    610:            pset_add_processor(new_pset, processor);
                    611:            if (new_pset->empty) {
                    612:                /*
                    613:                 *      Set all the threads loose.
                    614:                 *
                    615:                 *      NOTE: this appears to violate the locking
                    616:                 *      order, since the processor lock should
                    617:                 *      be taken AFTER a thread lock.  However,
                    618:                 *      thread_setrun (called by thread_release)
                    619:                 *      only takes the processor lock if the
                    620:                 *      processor is idle.  The processor is
                    621:                 *      not idle here.
                    622:                 */
                    623:                queue_iterate(&new_pset->threads, thread, thread_t,
                    624:                              pset_threads) {
                    625:                    thread_release(thread);
                    626:                }
                    627:                new_pset->empty = FALSE;
                    628:            }
                    629:            processor->processor_set_next = PROCESSOR_SET_NULL;
                    630:            processor->state = PROCESSOR_RUNNING;
                    631:            thread_wakeup((event_t)processor);
                    632:            processor_unlock(processor);
                    633:            splx(s);
                    634:            pset_unlock(new_pset);
                    635: 
                    636:            /*
                    637:             *  Clean up dangling references, and release our binding.
                    638:             */
                    639:            pset_deallocate(new_pset);
                    640:            if (have_pset_ref)
                    641:                pset_deallocate(pset);
                    642:            if (prev_thread != THREAD_NULL)
                    643:                thread_deallocate(prev_thread);
                    644:            thread_bind(this_thread, PROCESSOR_NULL);
                    645: 
                    646:            thread_block((void (*)()) 0);
                    647:            return;
                    648:        }
                    649: 
                    650: #endif /* MACH_HOST */
                    651: 
                    652:        /*
                    653:         *      Do shutdown, make sure we live when processor dies.
                    654:         */
                    655:        if (processor->state != PROCESSOR_SHUTDOWN) {
                    656:                printf("state: %d\n", processor->state);
                    657:                panic("action_thread -- bad processor state");
                    658:        }
                    659: 
                    660:        s = splsched();
                    661:        processor_lock(processor);
                    662: 
                    663:     shutdown:
                    664:        pset_remove_processor(pset, processor);
                    665:        processor_unlock(processor);
                    666:        pset_unlock(pset);
                    667:        splx(s);
                    668: 
                    669:        /*
                    670:         *      Clean up dangling references, and release our binding.
                    671:         */
                    672: #if    MACH_HOST
                    673:        if (new_pset != PROCESSOR_SET_NULL)
                    674:                pset_deallocate(new_pset);
                    675:        if (have_pset_ref)
                    676:                pset_deallocate(pset);
                    677:        if (prev_thread != THREAD_NULL)
                    678:                thread_deallocate(prev_thread);
                    679: #endif /* MACH_HOST */
                    680: 
                    681:        thread_bind(this_thread, PROCESSOR_NULL);
                    682:        switch_to_shutdown_context(this_thread,
                    683:                                   processor_doshutdown,
                    684:                                   processor);
                    685: 
                    686: }
                    687: 
                    688: /*
                    689:  *     Actually do the processor shutdown.  This is called at splsched,
                    690:  *     running on the processor's shutdown stack.
                    691:  */
                    692: 
                    693: #ifdef __GNUC__
                    694: extern __volatile__ void halt_cpu();
                    695: #endif
                    696: 
                    697: #ifdef __GNUC__
                    698: __volatile__
                    699: #endif
                    700: void processor_doshutdown(processor)
                    701: register processor_t   processor;
                    702: {
                    703:        register int            cpu = processor->slot_num;
                    704: 
                    705:        timer_switch(&kernel_timer[cpu]);
                    706: 
                    707:        /*
                    708:         *      Ok, now exit this cpu.
                    709:         */
                    710:        PMAP_DEACTIVATE_KERNEL(cpu);
                    711: #ifndef MIGRATING_THREADS
                    712:        active_threads[cpu] = THREAD_NULL;
                    713: #endif
                    714:        cpu_down(cpu);
                    715:        thread_wakeup((event_t)processor);
                    716:        halt_cpu();
                    717:        /*
                    718:         *      The action thread returns to life after the call to
                    719:         *      switch_to_shutdown_context above, on some other cpu.
                    720:         */
                    721: 
                    722:        /*NOTREACHED*/
                    723: }
                    724: #else  /* NCPUS > 1 */
                    725: 
                    726: kern_return_t
                    727: processor_assign(processor, new_pset, wait)
                    728: processor_t    processor;
                    729: processor_set_t        new_pset;
                    730: boolean_t      wait;
                    731: {
                    732: #ifdef lint
                    733:        processor++; new_pset++; wait++;
                    734: #endif /* lint */
                    735:        return(KERN_FAILURE);
                    736: }
                    737: 
                    738: #endif /* NCPUS > 1 */
                    739: 
                    740: kern_return_t
                    741: host_get_boot_info(priv_host, boot_info)
                    742:         host_t              priv_host;
                    743:         kernel_boot_info_t  boot_info;
                    744: {
                    745:        char *src = "";
                    746: 
                    747:        if (priv_host == HOST_NULL) {
                    748:                return KERN_INVALID_HOST;
                    749:        }
                    750: 
                    751: #if    NORMA_ETHER
                    752: {
                    753:        extern char *norma_ether_boot_info();
                    754:        src = norma_ether_boot_info();
                    755: }
                    756: #endif /* NORMA_ETHER */
                    757: #if    defined(iPSC386) || defined(iPSC860)
                    758: {
                    759:        extern char *ipsc_boot_environ();
                    760:        src = ipsc_boot_environ();
                    761: }
                    762: #endif /* defined(iPSC386) || defined(iPSC860) */
                    763: 
                    764:        (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
                    765:        return KERN_SUCCESS;
                    766: }

unix.superglobalmegacorp.com

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