Annotation of kernel/kern/machine.c, revision 1.1

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

unix.superglobalmegacorp.com

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