Annotation of OSKit-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: #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.