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

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

unix.superglobalmegacorp.com

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