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

unix.superglobalmegacorp.com

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