Annotation of XNU/osfmk/kern/sched_prim.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_FREE_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:   sched_prim.c
        !            54:  *     Author: Avadis Tevanian, Jr.
        !            55:  *     Date:   1986
        !            56:  *
        !            57:  *     Scheduling primitives
        !            58:  *
        !            59:  */
        !            60: 
        !            61: #include <debug.h>
        !            62: #include <cpus.h>
        !            63: #include <mach_kdb.h>
        !            64: #include <simple_clock.h>
        !            65: #include <mach_host.h>
        !            66: #include <power_save.h>
        !            67: #include <task_swapper.h>
        !            68: 
        !            69: #include <ddb/db_output.h>
        !            70: #include <mach/machine.h>
        !            71: #include <machine/machine_routines.h>
        !            72: #include <machine/sched_param.h>
        !            73: #include <kern/ast.h>
        !            74: #include <kern/clock.h>
        !            75: #include <kern/counters.h>
        !            76: #include <kern/cpu_number.h>
        !            77: #include <kern/cpu_data.h>
        !            78: #include <kern/etap_macros.h>
        !            79: #include <kern/lock.h>
        !            80: #include <kern/macro_help.h>
        !            81: #include <kern/machine.h>
        !            82: #include <kern/misc_protos.h>
        !            83: #include <kern/processor.h>
        !            84: #include <kern/queue.h>
        !            85: #include <kern/sched.h>
        !            86: #include <kern/sched_prim.h>
        !            87: #include <kern/syscall_subr.h>
        !            88: #include <kern/task.h>
        !            89: #include <kern/thread.h>
        !            90: #include <kern/thread_swap.h>
        !            91: #include <vm/pmap.h>
        !            92: #include <vm/vm_kern.h>
        !            93: #include <vm/vm_map.h>
        !            94: #include <mach/policy.h>
        !            95: #include <mach/sync_policy.h>
        !            96: #include <kern/sf.h>
        !            97: #include <kern/mk_sp.h>        /*** ??? fix so this can be removed ***/
        !            98: #include <sys/kdebug.h>
        !            99: 
        !           100: #if    TASK_SWAPPER
        !           101: #include <kern/task_swap.h>
        !           102: extern int     task_swap_on;
        !           103: #endif /* TASK_SWAPPER */
        !           104: 
        !           105: extern int     hz;
        !           106: 
        !           107: #define                DEFAULT_PREEMPTION_RATE         100     /* (1/s) */
        !           108: int                    default_preemption_rate = DEFAULT_PREEMPTION_RATE;
        !           109: int                    min_quantum;
        !           110: 
        !           111: unsigned       sched_tick;
        !           112: 
        !           113: #if    SIMPLE_CLOCK
        !           114: int                    sched_usec;
        !           115: #endif /* SIMPLE_CLOCK */
        !           116: 
        !           117: /* Forwards */
        !           118: void        thread_continue(thread_t);
        !           119: 
        !           120: void           wait_queues_init(void);
        !           121: 
        !           122: void           set_pri(
        !           123:                                thread_t                thread,
        !           124:                                int                             pri,
        !           125:                                int                             resched);
        !           126: 
        !           127: thread_t       choose_pset_thread(
        !           128:                                processor_t                     myprocessor,
        !           129:                                processor_set_t         pset);
        !           130: 
        !           131: thread_t       choose_thread(
        !           132:                                processor_t             myprocessor);
        !           133: 
        !           134: int                    run_queue_enqueue(
        !           135:                                run_queue_t             runq,
        !           136:                                thread_t                thread,
        !           137:                                boolean_t               tail);
        !           138: 
        !           139: void           idle_thread_continue(void);
        !           140: void           do_thread_scan(void);
        !           141: 
        !           142: static
        !           143: void           clear_wait_internal(
        !           144:                                thread_t                thread,
        !           145:                                int                             result);
        !           146: 
        !           147: 
        !           148: void           dump_run_queues(run_queue_t);
        !           149: void           dump_run_queue_struct( run_queue_t );
        !           150: void           dump_processor( processor_t );
        !           151: void           dump_processor_set( processor_set_t );
        !           152: 
        !           153: #if    DEBUG
        !           154: void           checkrq(
        !           155:                                run_queue_t             rq,
        !           156:                                char                    *msg);
        !           157: 
        !           158: void           thread_check(
        !           159:                                thread_t                thread,
        !           160:                                run_queue_t             runq);
        !           161: #endif /*DEBUG*/
        !           162: 
        !           163: boolean_t      thread_runnable(
        !           164:                                thread_t                thread);
        !           165: 
        !           166: /*
        !           167:  *     State machine
        !           168:  *
        !           169:  * states are combinations of:
        !           170:  *  R  running
        !           171:  *  W  waiting (or on wait queue)
        !           172:  *  N  non-interruptible
        !           173:  *  O  swapped out
        !           174:  *  I  being swapped in
        !           175:  *
        !           176:  * init        action 
        !           177:  *     assert_wait thread_block    clear_wait          swapout swapin
        !           178:  *
        !           179:  * R   RW, RWN     R;   setrun     -                   -
        !           180:  * RN  RWN         RN;  setrun     -                   -
        !           181:  *
        !           182:  * RW              W               R                   -
        !           183:  * RWN             WN              RN                  -
        !           184:  *
        !           185:  * W                               R;   setrun         WO
        !           186:  * WN                              RN;  setrun         -
        !           187:  *
        !           188:  * RO                              -                   -       R
        !           189:  *
        !           190:  */
        !           191: 
        !           192: /*
        !           193:  *     Waiting protocols and implementation:
        !           194:  *
        !           195:  *     Each thread may be waiting for exactly one event; this event
        !           196:  *     is set using assert_wait().  That thread may be awakened either
        !           197:  *     by performing a thread_wakeup_prim() on its event,
        !           198:  *     or by directly waking that thread up with clear_wait().
        !           199:  *
        !           200:  *     The implementation of wait events uses a hash table.  Each
        !           201:  *     bucket is queue of threads having the same hash function
        !           202:  *     value; the chain for the queue (linked list) is the run queue
        !           203:  *     field.  [It is not possible to be waiting and runnable at the
        !           204:  *     same time.]
        !           205:  *
        !           206:  *     Locks on both the thread and on the hash buckets govern the
        !           207:  *     wait event field and the queue chain field.  Because wakeup
        !           208:  *     operations only have the event as an argument, the event hash
        !           209:  *     bucket must be locked before any thread.
        !           210:  *
        !           211:  *     Scheduling operations may also occur at interrupt level; therefore,
        !           212:  *     interrupts below splsched() must be prevented when holding
        !           213:  *     thread or hash bucket locks.
        !           214:  *
        !           215:  *     The wait event hash table declarations are as follows:
        !           216:  */
        !           217: 
        !           218: #define NUMQUEUES      59
        !           219: 
        !           220: struct wait_queue wait_queues[NUMQUEUES];
        !           221: 
        !           222: #define wait_hash(event) \
        !           223:        ((((int)(event) < 0)? ~(int)(event): (int)(event)) % NUMQUEUES)
        !           224: 
        !           225: void
        !           226: sched_init(void)
        !           227: {
        !           228:        /*
        !           229:         *      Calculate the minimum quantum
        !           230:         *      in ticks.
        !           231:         */
        !           232:        if (default_preemption_rate < 1)
        !           233:                default_preemption_rate = DEFAULT_PREEMPTION_RATE;
        !           234:        min_quantum = hz / default_preemption_rate;
        !           235:        /*
        !           236:         *      Round up result (4/5) to an
        !           237:         *      integral number of ticks.
        !           238:         */
        !           239:        if (((hz * 10) / default_preemption_rate) - (min_quantum * 10) >= 5)
        !           240:                min_quantum++;
        !           241:        if (min_quantum < 1)
        !           242:                min_quantum = 1;
        !           243:        printf("minimum scheduling quantum is %d ms\n", (1000 / hz) * min_quantum);
        !           244: 
        !           245:        wait_queues_init();
        !           246:        pset_sys_bootstrap();           /* initialize processer mgmt. */
        !           247:        queue_init(&action_queue);
        !           248:        simple_lock_init(&action_lock, ETAP_THREAD_ACTION);
        !           249:        sched_tick = 0;
        !           250: #if    SIMPLE_CLOCK
        !           251:        sched_usec = 0;
        !           252: #endif /* SIMPLE_CLOCK */
        !           253:        ast_init();
        !           254:        /*** ??? is this the right place?***/
        !           255:        sf_init();
        !           256: }
        !           257: 
        !           258: void
        !           259: wait_queues_init(void)
        !           260: {
        !           261:        register int    i;
        !           262: 
        !           263:        for (i = 0; i < NUMQUEUES; i++) {
        !           264:                wait_queue_init(&wait_queues[i], SYNC_POLICY_FIFO);
        !           265:        }
        !           266: }
        !           267: 
        !           268: /*
        !           269:  *     Thread timeout routine, called when timer expires.
        !           270:  */
        !           271: void
        !           272: thread_timer_expire(
        !           273:        thread_t                thread)
        !           274: {
        !           275:        spl_t                   s;
        !           276: 
        !           277:        s = splsched();
        !           278:        thread_lock(thread);
        !           279:        if (    thread->wait_timer_is_set                                                       &&
        !           280:                        !thread_call_is_delayed(&thread->wait_timer, NULL)              ) {
        !           281:                thread->wait_timer_is_set = FALSE;
        !           282:                if (thread->active)
        !           283:                        clear_wait_internal(thread, THREAD_TIMED_OUT);
        !           284:        }
        !           285:        thread_unlock(thread);
        !           286:        splx(s);
        !           287: 
        !           288:        thread_deallocate(thread);
        !           289: }
        !           290: 
        !           291: /*
        !           292:  *     thread_set_timer:
        !           293:  *
        !           294:  *     Set a timer for the current thread, if the thread
        !           295:  *     is ready to wait.  Must be called between assert_wait()
        !           296:  *     and thread_block().
        !           297:  */
        !           298: void
        !           299: thread_set_timer(
        !           300:        natural_t               interval,
        !           301:        natural_t               scale_factor)
        !           302: {
        !           303:        thread_t                thread = current_thread();
        !           304:        AbsoluteTime    deadline;
        !           305:        spl_t                   s;
        !           306: 
        !           307:        s = splsched();
        !           308:        thread_lock(thread);
        !           309:        if ((thread->state & TH_WAIT) != 0) {
        !           310:                clock_interval_to_deadline(interval, scale_factor, &deadline);
        !           311:                thread_call_enter_delayed(&thread->wait_timer, deadline);
        !           312:                assert(!thread->wait_timer_is_set);
        !           313:                thread->ref_count++;
        !           314:                thread->wait_timer_is_set = TRUE;
        !           315:        }
        !           316:        thread_unlock(thread);
        !           317:        splx(s);
        !           318: }
        !           319: 
        !           320: void
        !           321: thread_set_timer_deadline(
        !           322:        AbsoluteTime    deadline)
        !           323: {
        !           324:        thread_t                thread = current_thread();
        !           325:        spl_t                   s;
        !           326: 
        !           327:        s = splsched();
        !           328:        thread_lock(thread);
        !           329:        if ((thread->state & TH_WAIT) != 0) {
        !           330:                thread_call_enter_delayed(&thread->wait_timer, deadline);
        !           331:                assert(!thread->wait_timer_is_set);
        !           332:                thread->ref_count++;
        !           333:                thread->wait_timer_is_set = TRUE;
        !           334:        }
        !           335:        thread_unlock(thread);
        !           336:        splx(s);
        !           337: }
        !           338: 
        !           339: void
        !           340: thread_cancel_timer(void)
        !           341: {
        !           342:        thread_t                thread = current_thread();
        !           343:        boolean_t               release = FALSE;
        !           344:        spl_t                   s;
        !           345: 
        !           346:        s = splsched();
        !           347:        thread_lock(thread);
        !           348:        if (thread->wait_timer_is_set) {
        !           349:                if (thread_call_cancel(&thread->wait_timer))
        !           350:                        release = TRUE;
        !           351:                thread->wait_timer_is_set = FALSE;
        !           352:        }
        !           353:        thread_unlock(thread);
        !           354:        splx(s);
        !           355: 
        !           356:        if (release)
        !           357:                thread_deallocate(thread);
        !           358: }
        !           359: 
        !           360: /*
        !           361:  *     thread_depress_timeout:
        !           362:  *
        !           363:  *     Timeout routine for priority depression.
        !           364:  */
        !           365: void
        !           366: thread_depress_timeout(
        !           367:        thread_t                thread)
        !           368: {
        !           369:     sched_policy_t     *policy;
        !           370:     spl_t                      s;
        !           371: 
        !           372:     s = splsched();
        !           373:     thread_lock(thread);
        !           374:     policy = policy_id_to_sched_policy(thread->policy);
        !           375:     thread_unlock(thread);
        !           376:     splx(s);
        !           377: 
        !           378:        if (policy != SCHED_POLICY_NULL)
        !           379:                policy->sp_ops.sp_thread_depress_timeout(policy, thread);
        !           380: 
        !           381:        thread_deallocate(thread);
        !           382: }
        !           383: 
        !           384: /*
        !           385:  * Set up thread timeout element when thread is created.
        !           386:  */
        !           387: void
        !           388: thread_timer_setup(
        !           389:         thread_t               thread)
        !           390: {
        !           391:        thread_call_setup(&thread->wait_timer, thread_timer_expire, thread);
        !           392:        thread->wait_timer_is_set = FALSE;
        !           393:        thread_call_setup(&thread->depress_timer, thread_depress_timeout, thread);
        !           394: }
        !           395: 
        !           396: /*
        !           397:  *     Routine:        thread_go_locked
        !           398:  *     Purpose:
        !           399:  *             Start a thread running.
        !           400:  *     Conditions:
        !           401:  *             thread lock held, IPC locks may be held.
        !           402:  *             thread must have been pulled from wait queue under same lock hold.
        !           403:  */
        !           404: void
        !           405: thread_go_locked(
        !           406:        thread_t                thread,
        !           407:        int                             result)
        !           408: {
        !           409:        int                             state;
        !           410:        sched_policy_t  *policy;
        !           411:        sf_return_t             sfr;
        !           412: 
        !           413:        assert(thread->at_safe_point == FALSE);
        !           414:        assert(thread->wait_event == NO_EVENT);
        !           415:        assert(thread->wait_queue == WAIT_QUEUE_NULL);
        !           416: 
        !           417:        if (thread->state & TH_WAIT) {
        !           418: 
        !           419:                thread->state &= ~TH_WAIT;
        !           420:                if (!(thread->state & TH_RUN)) {
        !           421:                        thread->state |= TH_RUN;
        !           422: #if    THREAD_SWAPPER
        !           423:                        if (thread->state & TH_SWAPPED_OUT)
        !           424:                                thread_swapin(thread->top_act, FALSE);
        !           425:                        else 
        !           426: #endif /* THREAD_SWAPPER */
        !           427:                        {
        !           428:                                policy = &sched_policy[thread->policy];
        !           429:                                sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
        !           430:                                assert(sfr == SF_SUCCESS);
        !           431:                        }
        !           432:                }
        !           433:                thread->wait_result = result;
        !           434:        }
        !           435: 
        !           436:                                        
        !           437:        /*
        !           438:         * The next few lines are a major hack. Hopefully this will get us
        !           439:         * around all of the scheduling framework hooha. We can't call
        !           440:         * sp_thread_unblock yet because we could still be finishing up the
        !           441:         * durn two stage block on another processor and thread_setrun
        !           442:         * could be called by s_t_u and we'll really be messed up then.
        !           443:         */             
        !           444:        /* Don't mess with this if we are still swapped out */
        !           445:        if (!(thread->state & TH_SWAPPED_OUT))
        !           446:                ((mk_sp_info_t)thread->sp_info)->th_state = MK_SP_RUNNABLE;
        !           447:                        
        !           448: }
        !           449: 
        !           450: void
        !           451: thread_mark_wait_locked(
        !           452:        thread_t                thread,
        !           453:        int                 interruptible)
        !           454: {
        !           455: 
        !           456:        assert(thread == current_thread());
        !           457: 
        !           458:        thread->wait_result = -1; /* JMM - Needed for non-assert kernel */
        !           459:        thread->state |= (interruptible) ? TH_WAIT : (TH_WAIT | TH_UNINT);
        !           460:        thread->at_safe_point = (interruptible == THREAD_ABORTSAFE);
        !           461:        thread->sleep_stamp = sched_tick;
        !           462: }
        !           463: 
        !           464: 
        !           465: 
        !           466: /*
        !           467:  *     Routine:        assert_wait_timeout
        !           468:  *     Purpose:
        !           469:  *             Assert that the thread intends to block,
        !           470:  *             waiting for a timeout (no user known event).
        !           471:  */
        !           472: unsigned int assert_wait_timeout_event;
        !           473: 
        !           474: void
        !           475: assert_wait_timeout(
        !           476:         mach_msg_timeout_t             msecs,
        !           477:        int                             interruptible)
        !           478: {
        !           479:        spl_t           s;
        !           480: 
        !           481:        assert_wait((event_t)&assert_wait_timeout_event, interruptible);
        !           482:        thread_set_timer(msecs, 1000*NSEC_PER_USEC);
        !           483: }
        !           484: 
        !           485: /*
        !           486:  * Check to see if an assert wait is possible, without actually doing one.
        !           487:  * This is used by debug code in locks and elsewhere to verify that it is
        !           488:  * always OK to block when trying to take a blocking lock (since waiting
        !           489:  * for the actual assert_wait to catch the case may make it hard to detect
        !           490:  * this case.
        !           491:  */
        !           492: boolean_t
        !           493: assert_wait_possible(void)
        !           494: {
        !           495:        thread_t thread = current_thread();
        !           496: 
        !           497:        return (thread == NULL || wait_queue_assert_possible(thread));
        !           498: }
        !           499: 
        !           500: /*
        !           501:  *     assert_wait:
        !           502:  *
        !           503:  *     Assert that the current thread is about to go to
        !           504:  *     sleep until the specified event occurs.
        !           505:  */
        !           506: void
        !           507: assert_wait(
        !           508:        event_t                         event,
        !           509:        int                             interruptible)
        !           510: {
        !           511:        register wait_queue_t   wq;
        !           512:        register int            index;
        !           513: 
        !           514:        assert(event != NO_EVENT);
        !           515:        assert(assert_wait_possible());
        !           516: 
        !           517:        index = wait_hash(event);
        !           518:        wq = &wait_queues[index];
        !           519:        wait_queue_assert_wait(wq,
        !           520:                               event,
        !           521:                               interruptible);
        !           522: }
        !           523: 
        !           524:   
        !           525: /*
        !           526:  * thread_[un]stop(thread)
        !           527:  *     Once a thread has blocked interruptibly (via assert_wait) prevent 
        !           528:  *     it from running until thread_unstop.
        !           529:  *
        !           530:  *     If someone else has already stopped the thread, wait for the
        !           531:  *     stop to be cleared, and then stop it again.
        !           532:  *
        !           533:  *     Return FALSE if interrupted.
        !           534:  *
        !           535:  * NOTE: thread_hold/thread_suspend should be called on the activation
        !           536:  *     before calling thread_stop.  TH_SUSP is only recognized when
        !           537:  *     a thread blocks and only prevents clear_wait/thread_wakeup
        !           538:  *     from restarting an interruptible wait.  The wake_active flag is
        !           539:  *     used to indicate that someone is waiting on the thread.
        !           540:  */
        !           541: boolean_t
        !           542: thread_stop(
        !           543:        thread_t                        thread)
        !           544: {
        !           545:        spl_t                           s;
        !           546: 
        !           547:        s = splsched();
        !           548:        wake_lock(thread);
        !           549: 
        !           550:        while (thread->state & TH_SUSP) {
        !           551:                thread->wake_active = TRUE;
        !           552:                assert_wait((event_t)&thread->wake_active, THREAD_ABORTSAFE);
        !           553:                wake_unlock(thread);
        !           554:                splx(s);
        !           555: 
        !           556:                thread_block((void (*)(void)) 0);
        !           557:                if (current_thread()->wait_result != THREAD_AWAKENED)
        !           558:                        return (FALSE);
        !           559: 
        !           560:                s = splsched();
        !           561:                wake_lock(thread);
        !           562:        }
        !           563:        thread_lock(thread);
        !           564:        thread->state |= TH_SUSP;
        !           565:        thread_unlock(thread);
        !           566: 
        !           567:        wake_unlock(thread);
        !           568:        splx(s);
        !           569: 
        !           570:        return (TRUE);
        !           571: }
        !           572: 
        !           573: /*
        !           574:  *     Clear TH_SUSP and if the thread has been stopped and is now runnable,
        !           575:  *     put it back on the run queue.
        !           576:  */
        !           577: void
        !           578: thread_unstop(
        !           579:        thread_t                        thread)
        !           580: {
        !           581:        sched_policy_t          *policy;
        !           582:        sf_return_t                     sfr;
        !           583:        spl_t                           s;
        !           584: 
        !           585:        s = splsched();
        !           586:        wake_lock(thread);
        !           587:        thread_lock(thread);
        !           588: 
        !           589:        if ((thread->state & (TH_RUN|TH_WAIT|TH_SUSP/*|TH_UNINT*/)) == TH_SUSP) {
        !           590:                thread->state = (thread->state & ~TH_SUSP) | TH_RUN;
        !           591: #if    THREAD_SWAPPER
        !           592:                if (thread->state & TH_SWAPPED_OUT)
        !           593:                        thread_swapin(thread->top_act, FALSE);
        !           594:                else
        !           595: #endif /* THREAD_SWAPPER */
        !           596:                        {
        !           597:                                policy = &sched_policy[thread->policy];
        !           598:                                sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
        !           599:                                assert(sfr == SF_SUCCESS);
        !           600:                        }
        !           601:        }
        !           602:        else
        !           603:        if (thread->state & TH_SUSP) {
        !           604:                thread->state &= ~TH_SUSP;
        !           605: 
        !           606:                if (thread->wake_active) {
        !           607:                        thread->wake_active = FALSE;
        !           608:                        thread_unlock(thread);
        !           609:                        wake_unlock(thread);
        !           610:                        splx(s);
        !           611:                        thread_wakeup((event_t)&thread->wake_active);
        !           612: 
        !           613:                        return;
        !           614:                }
        !           615:        }
        !           616: 
        !           617:        thread_unlock(thread);
        !           618:        wake_unlock(thread);
        !           619:        splx(s);
        !           620: }
        !           621: 
        !           622: /*
        !           623:  * Wait for the thread's RUN bit to clear
        !           624:  */
        !           625: boolean_t
        !           626: thread_wait(
        !           627:        thread_t                thread)
        !           628: {
        !           629:        spl_t                   s;
        !           630: 
        !           631:        s = splsched();
        !           632:        wake_lock(thread);
        !           633: 
        !           634:        while (thread->state & (TH_RUN/*|TH_UNINT*/)) {
        !           635:                if (thread->last_processor != PROCESSOR_NULL)
        !           636:                        cause_ast_check(thread->last_processor);
        !           637: 
        !           638:                thread->wake_active = TRUE;
        !           639:                assert_wait((event_t)&thread->wake_active, THREAD_ABORTSAFE);
        !           640:                wake_unlock(thread);
        !           641:                splx(s);
        !           642: 
        !           643:                thread_block((void (*)(void))0);
        !           644:                if (current_thread()->wait_result != THREAD_AWAKENED)
        !           645:                        return (FALSE);
        !           646: 
        !           647:                s = splsched();
        !           648:                wake_lock(thread);
        !           649:        }
        !           650: 
        !           651:        wake_unlock(thread);
        !           652:        splx(s);
        !           653: 
        !           654:        return (TRUE);
        !           655: }
        !           656: 
        !           657: 
        !           658: /*
        !           659:  * thread_stop_wait(thread)
        !           660:  *     Stop the thread then wait for it to block interruptibly
        !           661:  */
        !           662: boolean_t
        !           663: thread_stop_wait(
        !           664:        thread_t                thread)
        !           665: {
        !           666:        if (thread_stop(thread)) {
        !           667:                if (thread_wait(thread))
        !           668:                        return (TRUE);
        !           669: 
        !           670:                thread_unstop(thread);
        !           671:        }
        !           672: 
        !           673:        return (FALSE);
        !           674: }
        !           675: 
        !           676: 
        !           677: static
        !           678: void
        !           679: clear_wait_internal(
        !           680:        thread_t                        thread,
        !           681:        int                                     result)
        !           682: {
        !           683:        register int                    index;
        !           684:        register queue_t                q;
        !           685:        register event_t                event;
        !           686:        register simple_lock_t  lock;
        !           687:        sched_policy_t                  *policy;
        !           688:        sf_return_t                             sfr;
        !           689: 
        !           690:        /*
        !           691:         * If the thread isn't in a wait queue, just set it running.  Otherwise,
        !           692:         * try to remove it from the queue and, if successful, then set it
        !           693:         * running.
        !           694:         */
        !           695:        if (wait_queue_assert_possible(thread) ||
        !           696:            (wait_queue_remove(thread) == KERN_SUCCESS)) {
        !           697:                thread_go_locked(thread, result);
        !           698:        }
        !           699: }
        !           700: 
        !           701: /*
        !           702:  *     clear_wait:
        !           703:  *
        !           704:  *     Clear the wait condition for the specified thread.  Start the thread
        !           705:  *     executing if that is appropriate.
        !           706:  *
        !           707:  *     parameters:
        !           708:  *       thread                thread to awaken
        !           709:  *       result                Wakeup result the thread should see
        !           710:  *       interruptible Don't wake up the thread if it isn't interruptible.
        !           711:  */
        !           712: void
        !           713: clear_wait(
        !           714:        thread_t                        thread,
        !           715:        int                                     result,
        !           716:        boolean_t                       interruptible)
        !           717: {
        !           718:        spl_t                           s;
        !           719: 
        !           720:        s = splsched();
        !           721:        thread_lock(thread);
        !           722:        if (!interruptible || !(thread->state & TH_UNINT))
        !           723:                        clear_wait_internal(thread, result);
        !           724:        thread_unlock(thread);
        !           725:        splx(s);
        !           726: }
        !           727: 
        !           728: 
        !           729: /*
        !           730:  *     thread_wakeup_prim:
        !           731:  *
        !           732:  *     Common routine for thread_wakeup, thread_wakeup_with_result,
        !           733:  *     and thread_wakeup_one.
        !           734:  *
        !           735:  */
        !           736: void
        !           737: thread_wakeup_prim(
        !           738:        event_t                 event,
        !           739:        boolean_t               one_thread,
        !           740:        int                     result)
        !           741: {
        !           742:        register wait_queue_t   wq;
        !           743:        register int                    index;
        !           744: 
        !           745:        index = wait_hash(event);
        !           746:        wq = &wait_queues[index];
        !           747:        if (one_thread)
        !           748:            wait_queue_wakeup_one(wq, event, result);
        !           749:        else
        !           750:            wait_queue_wakeup_all(wq, event, result);
        !           751: }
        !           752: 
        !           753: /*
        !           754:  *     thread_bind:
        !           755:  *
        !           756:  *     Force a thread to execute on the specified processor.
        !           757:  *     If the thread is currently executing, it may wait until its
        !           758:  *     time slice is up before switching onto the specified processor.
        !           759:  *
        !           760:  *     A processor of PROCESSOR_NULL causes the thread to be unbound.
        !           761:  *     xxx - DO NOT export this to users.
        !           762:  */
        !           763: void
        !           764: thread_bind(
        !           765:        register thread_t       thread,
        !           766:        processor_t                     processor)
        !           767: {
        !           768:        spl_t           s;
        !           769: 
        !           770:        s = splsched();
        !           771:        thread_lock(thread);
        !           772:        thread_bind_locked(thread, processor);
        !           773:        thread_unlock(thread);
        !           774:        splx(s);
        !           775: }
        !           776: 
        !           777: /*
        !           778:  *     Select a thread for this processor (the current processor) to run.
        !           779:  *     May select the current thread.
        !           780:  *     Assumes splsched.
        !           781:  */
        !           782: thread_t
        !           783: thread_select(
        !           784:        register processor_t    myprocessor)
        !           785: {
        !           786:        register thread_t               thread;
        !           787:        processor_set_t                 pset;
        !           788:        register run_queue_t    runq = &myprocessor->runq;
        !           789:        boolean_t                               other_runnable;
        !           790:        sched_policy_t                  *policy;
        !           791:        sf_return_t                             sfr;
        !           792: 
        !           793:        /*
        !           794:         *      Check for other non-idle runnable threads.
        !           795:         */
        !           796:        myprocessor->first_quantum = TRUE;
        !           797:        pset = myprocessor->processor_set;
        !           798:        thread = current_thread();
        !           799: 
        !           800: #if 0 /* CHECKME! */
        !           801:        thread->unconsumed_quantum = myprocessor->quantum;
        !           802: #endif
        !           803: 
        !           804:        simple_lock(&runq->lock);
        !           805:        simple_lock(&pset->runq.lock);
        !           806: 
        !           807:        other_runnable = runq->count > 0 || pset->runq.count > 0;
        !           808: 
        !           809:        if (    (!other_runnable                                                        ||
        !           810:                         (runq->highq < thread->sched_pri                       &&
        !           811:                          pset->runq.highq < thread->sched_pri))                &&
        !           812: #if    MACH_HOST
        !           813:                        thread->processor_set == pset                                   &&
        !           814: #endif /* MACH_HOST */
        !           815:                        (thread->bound_processor == PROCESSOR_NULL      ||
        !           816:                         thread->bound_processor == myprocessor)                &&
        !           817:                        thread->state == TH_RUN                                                 &&
        !           818:                        thread->pending_policy == POLICY_NULL                           ) {
        !           819: 
        !           820:                /* I am the highest priority runnable thread: */
        !           821:                simple_unlock(&pset->runq.lock);
        !           822:                simple_unlock(&runq->lock);
        !           823: 
        !           824:                /* Update the thread's meta-priority */
        !           825:                policy = &sched_policy[thread->policy];
        !           826:                /*** ??? maybe use a macro ***/
        !           827:                sfr = policy->sp_ops.sp_thread_update_mpri(policy, thread);
        !           828:                assert(sfr == SF_SUCCESS);
        !           829:        }
        !           830:        else if (other_runnable) {
        !           831:                simple_unlock(&pset->runq.lock);
        !           832:                simple_unlock(&runq->lock);
        !           833:                thread = choose_thread(myprocessor);
        !           834:        }
        !           835:        else {
        !           836:                simple_unlock(&runq->lock);
        !           837: 
        !           838:                /*
        !           839:                 *      Nothing non-idle runnable, including myself.
        !           840:                 *      Return if this
        !           841:                 *      thread is still runnable on this processor.
        !           842:                 *      Check for priority update if required.
        !           843:                 */
        !           844:                /* get an idle thread to run */
        !           845:                thread = choose_pset_thread(myprocessor, pset);
        !           846:        }
        !           847: 
        !           848:        if (thread->policy & (POLICY_RR|POLICY_FIFO))
        !           849: #if 1 /* CHECKME! */
        !           850:                myprocessor->quantum = pset->set_quantum;
        !           851: #else
        !           852:                myprocessor->quantum = thread->unconsumed_quantum;
        !           853: #endif
        !           854:        else
        !           855:                myprocessor->quantum = thread->bound_processor?
        !           856:                                                                        min_quantum : pset->set_quantum;
        !           857: 
        !           858:        return (thread);
        !           859: }
        !           860: 
        !           861: 
        !           862: /*
        !           863:  *     Stop running the current thread and start running the new thread.
        !           864:  *     If continuation is non-zero, and the current thread is blocked,
        !           865:  *     then it will resume by executing continuation on a new stack.
        !           866:  *     Returns TRUE if the hand-off succeeds.
        !           867:  *     The reason parameter == AST_QUANTUM if the thread blocked
        !           868:  *     because its quantum expired.
        !           869:  *     Assumes splsched.
        !           870:  */
        !           871: 
        !           872: 
        !           873: static thread_t
        !           874: __current_thread(void)
        !           875: {
        !           876:   return (current_thread());
        !           877: }
        !           878: 
        !           879: 
        !           880: boolean_t
        !           881: thread_invoke(
        !           882:        register thread_t       old_thread,
        !           883:        register thread_t       new_thread,
        !           884:        int                                     reason,
        !           885:        void                (*continuation)(void))
        !           886: {
        !           887:        sched_policy_t          *policy;
        !           888:        sf_return_t                     sfr;
        !           889:        thread_t                        old_thread_hold;
        !           890:        void                (*lcont)(void);
        !           891: 
        !           892:        /*
        !           893:         *      Mark thread interruptible.
        !           894:         */
        !           895:        thread_lock(new_thread);
        !           896:        new_thread->state &= ~TH_UNINT;
        !           897: 
        !           898:        assert(thread_runnable(new_thread));
        !           899: 
        !           900:        /*
        !           901:         *      Check for invoking the same thread.
        !           902:         */
        !           903:        if (old_thread == new_thread) {
        !           904:                counter(++c_thread_invoke_same);
        !           905:                thread_unlock(new_thread);
        !           906:         if (continuation != (void (*)()) 0) {
        !           907:                  if (old_thread->funnel_state & TH_FN_REFUNNEL) {
        !           908:                        kern_return_t save_wait_result;
        !           909:                        old_thread->funnel_state = 0;
        !           910:                        save_wait_result = old_thread->wait_result;
        !           911:                        mutex_lock(&funnel_lock);
        !           912:                        old_thread->funnel_state = TH_FN_OWNED;
        !           913:                        old_thread->wait_result = save_wait_result;
        !           914:                  }
        !           915:                  (void) spllo();
        !           916:                  call_continuation(continuation);
        !           917:           /*NOTREACHED*/
        !           918:         }
        !           919:         return TRUE;
        !           920:        }
        !           921: 
        !           922:        if ((old_thread->stack_privilege != current_stack()) &&
        !           923:                (continuation != (void (*)()) 0))
        !           924:        {
        !           925:          switch (new_thread->state & TH_STACK_STATE) {
        !           926:          case TH_STACK_HANDOFF:
        !           927:                new_thread->state &= ~(TH_STACK_HANDOFF|TH_UNINT);
        !           928:                thread_unlock(new_thread);
        !           929: 
        !           930:                mp_disable_preemption();
        !           931:                new_thread->last_processor = current_processor();
        !           932:                mp_enable_preemption();
        !           933: 
        !           934:        /*
        !           935:         *      Set up ast context of new thread and switch to its timer.
        !           936:         */
        !           937:        mp_disable_preemption();
        !           938:        ast_context(new_thread->top_act, cpu_number());
        !           939:        mp_enable_preemption();
        !           940:        timer_switch(&new_thread->system_timer);
        !           941: 
        !           942:        old_thread->continuation = continuation;
        !           943:        stack_handoff(old_thread, new_thread);
        !           944:        act_machine_sv_free(old_thread->top_act);
        !           945: 
        !           946:        thread_lock(old_thread);
        !           947: 
        !           948:        /* 
        !           949:         *  inline thread_dispatch but don't free stack
        !           950:      */
        !           951: 
        !           952:           switch (old_thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) {
        !           953:                sched_policy_t *policy;
        !           954:                sf_return_t sfr;
        !           955:  
        !           956:            case TH_RUN                     | TH_UNINT:
        !           957:            case TH_RUN:
        !           958:                /*
        !           959:                 *      No reason to stop.  Put back on a run queue.
        !           960:                 */
        !           961:                old_thread->state |= TH_STACK_HANDOFF;
        !           962: 
        !           963:                /* Get pointer to scheduling policy "object" */
        !           964:                policy = &sched_policy[old_thread->policy];
        !           965: 
        !           966:                /* Leave enqueueing thread up to scheduling policy */
        !           967:                sfr = policy->sp_ops.sp_thread_dispatch(policy,
        !           968:                                                              old_thread);
        !           969:                assert(sfr == SF_SUCCESS);
        !           970: 
        !           971:                break;
        !           972: 
        !           973:            case TH_RUN | TH_WAIT           | TH_UNINT:
        !           974:            case TH_RUN | TH_WAIT:
        !           975:                old_thread->sleep_stamp = sched_tick;
        !           976: 
        !           977:                /* fallthrough */
        !           978:            case          TH_WAIT:                      /* this happens! */
        !           979: 
        !           980:                /*
        !           981:                 *      Waiting
        !           982:                 */
        !           983:                old_thread->state |= TH_STACK_HANDOFF;
        !           984:                old_thread->state &= ~TH_RUN;
        !           985:                if (old_thread->state & TH_TERMINATE)
        !           986:                        thread_reaper_enqueue(old_thread);
        !           987: 
        !           988:                if (old_thread->wake_active) {
        !           989:                    old_thread->wake_active = FALSE;
        !           990:                    thread_unlock(old_thread);
        !           991:                    thread_wakeup((event_t)&old_thread->wake_active);
        !           992:                    goto after_old_thread;
        !           993:                }
        !           994:                break;
        !           995: 
        !           996:            case TH_RUN | TH_IDLE:
        !           997:                /*
        !           998:                 *      Drop idle thread -- it is already in
        !           999:                 *      idle_thread_array.
        !          1000:                 */
        !          1001:                  old_thread->state |= TH_STACK_HANDOFF;
        !          1002: 
        !          1003:                break;
        !          1004: 
        !          1005:            default:
        !          1006:                panic("State 0x%x \n",old_thread->state);
        !          1007:        }
        !          1008:           
        !          1009:           thread_unlock(old_thread);
        !          1010:          after_old_thread:
        !          1011:           /*
        !          1012:         * call_continuation calls the continuation after
        !          1013:                  resetting the current stack pointer to recover
        !          1014:           stack space.  without this we could stack overflow
        !          1015:           */
        !          1016:        disable_preemption();
        !          1017: 
        !          1018:        thread_lock(old_thread);
        !          1019: 
        !          1020:        /* Get pointer to scheduling policy "object" */
        !          1021:        policy = &sched_policy[old_thread->policy];
        !          1022: 
        !          1023:        /* Indicate to sched policy that old thread has stopped execution */
        !          1024:        /*** ??? maybe use a macro -- rkc, 1/4/96 ***/
        !          1025:        sfr = policy->sp_ops.sp_thread_done(policy,
        !          1026:                                                  old_thread);
        !          1027:        assert(sfr == SF_SUCCESS);
        !          1028: 
        !          1029:        /* Process any pending scheduling policy change */
        !          1030:        if (old_thread->pending_policy != POLICY_NULL) {
        !          1031:                sched_policy_t *policy;
        !          1032:                sf_return_t sfr;
        !          1033:            if (old_thread->policy != old_thread->pending_policy) {
        !          1034:                /* Detach thread from current scheduling policy */
        !          1035:                sfr = policy->sp_ops.sp_thread_detach(
        !          1036:                                                            policy,
        !          1037:                                                            old_thread);
        !          1038:                assert(sfr == SF_SUCCESS);
        !          1039: 
        !          1040:                /* Attach to the pending policy */
        !          1041:                policy = &sched_policy[old_thread->pending_policy];
        !          1042:                sfr = policy->sp_ops.sp_thread_attach(
        !          1043:                                                            policy,
        !          1044:                                                            old_thread);
        !          1045: 
        !          1046:                /* Save result for issuer of policy change */
        !          1047:                old_thread->change_sfr = (kern_return_t)sfr;
        !          1048: 
        !          1049:                /* If successful so far, set up sched attributes */
        !          1050:                if (sfr == SF_SUCCESS) {
        !          1051:                    sfr = policy->sp_ops.sp_thread_set(
        !          1052:                                               policy,
        !          1053:                                               old_thread,
        !          1054:                                               old_thread->pending_sched_attr);
        !          1055: 
        !          1056:                    /* Save result for issuer of policy change */
        !          1057:                    old_thread->change_sfr = (kern_return_t)sfr;
        !          1058:                }
        !          1059:            }
        !          1060: 
        !          1061:            /* Indicate change has been done */
        !          1062:            old_thread->pending_policy = POLICY_NULL;
        !          1063:        }
        !          1064:        thread_unlock(old_thread);
        !          1065:        thread_lock(new_thread);
        !          1066: 
        !          1067:        assert(thread_runnable(new_thread));
        !          1068: 
        !          1069:        /* Get pointer to scheduling policy "object" */
        !          1070:        policy = &sched_policy[new_thread->policy];
        !          1071: 
        !          1072:        /* Indicate to sched policy that new thread has started execution */
        !          1073:        /*** ??? maybe use a macro ***/
        !          1074:        sfr = policy->sp_ops.sp_thread_begin(policy, new_thread);
        !          1075:        assert(sfr == SF_SUCCESS);
        !          1076:        thread_unlock(new_thread);
        !          1077:        enable_preemption();
        !          1078: 
        !          1079:           counter_always(c_thread_invoke_hits++);
        !          1080:           (void) spllo();
        !          1081:           lcont = new_thread->continuation;
        !          1082:           assert(lcont);
        !          1083:           if (new_thread->funnel_state & TH_FN_REFUNNEL) {
        !          1084:                 kern_return_t save_wait_result;
        !          1085:                 new_thread->funnel_state = 0;
        !          1086:                 save_wait_result = new_thread->wait_result;
        !          1087:                 mutex_lock(&funnel_lock);
        !          1088:                 new_thread->funnel_state = TH_FN_OWNED;
        !          1089:                 new_thread->wait_result = save_wait_result;
        !          1090:           }
        !          1091:           assert(lcont);
        !          1092:           call_continuation(lcont);
        !          1093:           /*NOTREACHED*/
        !          1094:           return TRUE;
        !          1095: 
        !          1096:          case TH_STACK_COMING_IN:
        !          1097:                /*
        !          1098:                 * waiting for a stack
        !          1099:                 */
        !          1100:                thread_swapin(new_thread);
        !          1101:                thread_unlock(new_thread);
        !          1102:                counter_always(c_thread_invoke_misses++);
        !          1103:                return FALSE;
        !          1104: 
        !          1105:       case 0:
        !          1106:         /*
        !          1107:          * already has a stack - can't handoff
        !          1108:          */
        !          1109: 
        !          1110:         break;
        !          1111:       }
        !          1112:        }
        !          1113:        else 
        !          1114:          {
        !          1115:                /*
        !          1116:                 * check that the new thread has a stack
        !          1117:                 */
        !          1118:                if (new_thread->state & TH_STACK_HANDOFF) {
        !          1119:                  /* has no stack. if not already waiting for one try to get one */
        !          1120:                if ((new_thread->state & TH_STACK_COMING_IN) ||
        !          1121:                        /* not already waiting. nonblocking try to get one */
        !          1122:                        !stack_alloc_try(new_thread, thread_continue))
        !          1123:                  {
        !          1124:                        /* couldn't get one. schedule new thread to get a stack and
        !          1125:                           return failure so we can try another thread. */
        !          1126:                        thread_swapin(new_thread);
        !          1127:                        thread_unlock(new_thread);
        !          1128:                        counter_always(c_thread_invoke_misses++);
        !          1129:             return FALSE;
        !          1130:           }
        !          1131:                }
        !          1132:                /* new thread now has a stack. it has been setup to resume in
        !          1133:                   thread_continue so it can dispatch the old thread, deal with
        !          1134:                   funnelling and then go to it's true continuation point */
        !          1135:          }
        !          1136: 
        !          1137:      new_thread->state &= ~(TH_STACK_HANDOFF | TH_UNINT);
        !          1138: 
        !          1139:        /*
        !          1140:         *      Thread is now interruptible.
        !          1141:         */
        !          1142:        mp_disable_preemption();
        !          1143:        new_thread->last_processor = current_processor();
        !          1144:        mp_enable_preemption();
        !          1145: 
        !          1146:        thread_unlock(new_thread);
        !          1147: 
        !          1148:        /*
        !          1149:         *      Set up ast context of new thread and switch to its timer.
        !          1150:         */
        !          1151:        mp_disable_preemption();
        !          1152:        ast_context(new_thread->top_act, cpu_number());
        !          1153:        mp_enable_preemption();
        !          1154:        timer_switch(&new_thread->system_timer);
        !          1155: 
        !          1156:        /*
        !          1157:         *      switch_context is machine-dependent.  It does the
        !          1158:         *      machine-dependent components of a context-switch, like
        !          1159:         *      changing address spaces.  It updates active_threads.
        !          1160:         */
        !          1161:        old_thread->reason = reason;
        !          1162:        counter_always(c_thread_invoke_csw++);
        !          1163:        current_task()->csw++;
        !          1164: 
        !          1165:        /*
        !          1166:         * N.B. On return from the call to switch_context, 'old_thread'
        !          1167:         * points at the thread that yielded to us.  Unfortunately, at
        !          1168:         * this point, there are no simple_locks held, so if we are preempted
        !          1169:         * before the call to thread_dispatch blocks preemption, it is
        !          1170:         * possible for 'old_thread' to terminate, leaving us with a
        !          1171:         * stale thread pointer.
        !          1172:         */
        !          1173:        assert(thread_runnable(new_thread));
        !          1174:        assert(old_thread->runq == RUN_QUEUE_NULL);
        !          1175: 
        !          1176:        disable_preemption();
        !          1177: 
        !          1178:        thread_lock(old_thread);
        !          1179: 
        !          1180:        /* Indicate to sched policy that old thread has stopped execution */
        !          1181:        policy = &sched_policy[old_thread->policy];
        !          1182:        /*** ??? maybe use a macro -- ***/
        !          1183:        sfr = policy->sp_ops.sp_thread_done(policy, old_thread);
        !          1184:        assert(sfr == SF_SUCCESS);
        !          1185: 
        !          1186:        /* Process any pending scheduling policy change */
        !          1187:        if (old_thread->pending_policy != POLICY_NULL) {
        !          1188:            if (old_thread->policy != old_thread->pending_policy) {
        !          1189:                        /* Detach thread from current scheduling policy */
        !          1190:                        sfr = policy->sp_ops.sp_thread_detach(policy, old_thread);
        !          1191:                        assert(sfr == SF_SUCCESS);
        !          1192: 
        !          1193:                        /* Attach to the pending policy */
        !          1194:                        policy = &sched_policy[old_thread->pending_policy];
        !          1195:                        sfr = policy->sp_ops.sp_thread_attach(policy, old_thread);
        !          1196: 
        !          1197:                        /* Save result for issuer of policy change */
        !          1198:                        old_thread->change_sfr = (kern_return_t)sfr;
        !          1199: 
        !          1200:                        /* If successful so far, set up sched attributes */
        !          1201:                        if (sfr == SF_SUCCESS) {
        !          1202:                                sfr = policy->sp_ops.sp_thread_set(policy, old_thread,
        !          1203:                                                                                        old_thread->pending_sched_attr);
        !          1204: 
        !          1205:                                /* Save result for issuer of policy change */
        !          1206:                                old_thread->change_sfr = (kern_return_t)sfr;
        !          1207:                        }
        !          1208:            }
        !          1209: 
        !          1210:            /* Indicate change has been done */
        !          1211:            old_thread->pending_policy = POLICY_NULL;
        !          1212:        }
        !          1213: 
        !          1214:        thread_unlock(old_thread);
        !          1215:        old_thread_hold = old_thread;
        !          1216: 
        !          1217: /*     SWITCH CONTEXT HERE */
        !          1218: 
        !          1219:        old_thread = switch_context(old_thread, continuation, new_thread);
        !          1220: 
        !          1221:        /* Now on new thread's stack.  Set a local variable to refer to it. */
        !          1222:        new_thread = __current_thread();
        !          1223:        assert(old_thread != new_thread);
        !          1224: 
        !          1225:        assert(thread_runnable(new_thread));
        !          1226: 
        !          1227:        thread_lock(new_thread);
        !          1228:        assert(thread_runnable(new_thread));
        !          1229:        /* Indicate to sched policy that new thread has started execution */
        !          1230:        policy = &sched_policy[new_thread->policy];
        !          1231:        /*** ??? maybe use a macro -- rkc, 1/4/96 ***/
        !          1232:        sfr = policy->sp_ops.sp_thread_begin(policy, new_thread);
        !          1233:        assert(sfr == SF_SUCCESS);
        !          1234:        thread_unlock(new_thread);
        !          1235: 
        !          1236:        /*
        !          1237:         *      We're back.  Now old_thread is the thread that resumed
        !          1238:         *      us, and we have to dispatch it.
        !          1239:         */
        !          1240:        /* CHECKME! */
        !          1241: //     Code from OSF in Grenoble deleted the following fields. They were
        !          1242: //     used in HPPA and 386 code, but not in the PPC for other than
        !          1243: //     just setting and resetting. They didn't delete these lines from
        !          1244: //     the MACH_RT builds, though, causing compile errors.  I'm going
        !          1245: //     to make a wild guess and assume we can just delete these.
        !          1246: #if 0
        !          1247:        if (old_thread->preempt == TH_NOT_PREEMPTABLE) {
        !          1248:            /*
        !          1249:             * Mark that we have been really preempted
        !          1250:             */
        !          1251:            old_thread->preempt = TH_PREEMPTED;
        !          1252:        }
        !          1253: #endif
        !          1254:        thread_dispatch(old_thread);
        !          1255:        enable_preemption();
        !          1256:        return TRUE;
        !          1257: }
        !          1258: 
        !          1259: /*
        !          1260:  *     thread_continue:
        !          1261:  *
        !          1262:  *     Called when the launching a new thread, at splsched();
        !          1263:  */
        !          1264: void
        !          1265: thread_continue(
        !          1266:        register thread_t old_thread)
        !          1267: {
        !          1268:        register thread_t self;
        !          1269:        register void (*continuation)();
        !          1270:     sched_policy_t          *policy;
        !          1271:     sf_return_t             sfr;
        !          1272: 
        !          1273:        self = current_thread();
        !          1274:        continuation = self->continuation;
        !          1275: 
        !          1276:        /*
        !          1277:         *      We must dispatch the old thread and then
        !          1278:         *      call the current thread's continuation.
        !          1279:         *      There might not be an old thread, if we are
        !          1280:         *      the first thread to run on this processor.
        !          1281:         */
        !          1282:        if (old_thread != THREAD_NULL) {
        !          1283:                thread_dispatch(old_thread);
        !          1284:         thread_lock(self);
        !          1285: 
        !          1286:         /* Get pointer to scheduling policy "object" */
        !          1287:         policy = &sched_policy[self->policy];
        !          1288: 
        !          1289:        /* Indicate to sched policy that new thread has started execution */
        !          1290:        /*** ??? maybe use a macro -- rkc, 1/4/96 ***/
        !          1291:        sfr = policy->sp_ops.sp_thread_begin(policy,self);
        !          1292:        assert(sfr == SF_SUCCESS);
        !          1293:        thread_unlock(self);
        !          1294:        }
        !          1295: 
        !          1296:        /*
        !          1297:         * N.B. - the following is necessary, since thread_invoke()
        !          1298:         * inhibits preemption on entry and reenables before it
        !          1299:         * returns.  Unfortunately, the first time a newly-created
        !          1300:         * thread executes, it magically appears here, and never
        !          1301:         * executes the enable_preemption() call in thread_invoke().
        !          1302:         */
        !          1303:        enable_preemption();
        !          1304:        if (self->funnel_state & TH_FN_REFUNNEL) {
        !          1305:          kern_return_t save_wait_result;
        !          1306:          self->funnel_state = 0;
        !          1307:          save_wait_result = self->wait_result;
        !          1308:          mutex_lock(&funnel_lock);
        !          1309:          self->wait_result = save_wait_result;
        !          1310:          self->funnel_state = TH_FN_OWNED;
        !          1311:        }
        !          1312:        spllo();
        !          1313: 
        !          1314:        assert(continuation);
        !          1315:        (*continuation)();
        !          1316:        /*NOTREACHED*/
        !          1317: }
        !          1318: 
        !          1319: #if    MACH_LDEBUG || MACH_KDB
        !          1320: 
        !          1321: #define THREAD_LOG_SIZE                300
        !          1322: 
        !          1323: struct t64 {
        !          1324:        unsigned long h;
        !          1325:        unsigned long l;
        !          1326: };
        !          1327: 
        !          1328: struct {
        !          1329:        struct t64      stamp;
        !          1330:        thread_t        thread;
        !          1331:        long            info1;
        !          1332:        long            info2;
        !          1333:        long            info3;
        !          1334:        char            * action;
        !          1335: } thread_log[THREAD_LOG_SIZE];
        !          1336: 
        !          1337: int            thread_log_index;
        !          1338: 
        !          1339: void           check_thread_time(long n);
        !          1340: 
        !          1341: 
        !          1342: int    check_thread_time_crash;
        !          1343: 
        !          1344: #if 0
        !          1345: void
        !          1346: check_thread_time(long us)
        !          1347: {
        !          1348:        struct t64      temp;
        !          1349: 
        !          1350:        if (!check_thread_time_crash)
        !          1351:                return;
        !          1352: 
        !          1353:        temp = thread_log[0].stamp;
        !          1354:        cyctm05_diff (&thread_log[1].stamp, &thread_log[0].stamp, &temp);
        !          1355: 
        !          1356:        if (temp.l >= us && thread_log[1].info != 0x49) /* HACK!!! */
        !          1357:                panic ("check_thread_time");
        !          1358: }
        !          1359: #endif
        !          1360: 
        !          1361: void
        !          1362: log_thread_action(char * action, long info1, long info2, long info3)
        !          1363: {
        !          1364:        int     i;
        !          1365:        spl_t   x;
        !          1366:        static  unsigned int tstamp;
        !          1367: 
        !          1368:        x = splhigh();
        !          1369: 
        !          1370:        for (i = THREAD_LOG_SIZE-1; i > 0; i--) {
        !          1371:                thread_log[i] = thread_log[i-1];
        !          1372:        }
        !          1373: 
        !          1374:        thread_log[0].stamp.h = 0;
        !          1375:        thread_log[0].stamp.l = tstamp++;
        !          1376:        thread_log[0].thread = current_thread();
        !          1377:        thread_log[0].info1 = info1;
        !          1378:        thread_log[0].info2 = info2;
        !          1379:        thread_log[0].info3 = info3;
        !          1380:        thread_log[0].action = action;
        !          1381: /*     strcpy (&thread_log[0].action[0], action);*/
        !          1382: 
        !          1383:        splx(x);
        !          1384: }
        !          1385: #endif /* MACH_LDEBUG || MACH_KDB */
        !          1386: 
        !          1387: #if    MACH_KDB
        !          1388: #include <ddb/db_output.h>
        !          1389: void           db_show_thread_log(void);
        !          1390: 
        !          1391: void
        !          1392: db_show_thread_log(void)
        !          1393: {
        !          1394:        int     i;
        !          1395: 
        !          1396:        db_printf ("%s %s %s %s %s %s\n", " Thread ", "  Info1 ", "  Info2 ",
        !          1397:                        "  Info3 ", "    Timestamp    ", "Action");
        !          1398: 
        !          1399:        for (i = 0; i < THREAD_LOG_SIZE; i++) {
        !          1400:                db_printf ("%08x %08x %08x %08x %08x/%08x %s\n",
        !          1401:                        thread_log[i].thread,
        !          1402:                        thread_log[i].info1,
        !          1403:                        thread_log[i].info2,
        !          1404:                        thread_log[i].info3,
        !          1405:                        thread_log[i].stamp.h,
        !          1406:                        thread_log[i].stamp.l,
        !          1407:                        thread_log[i].action);
        !          1408:        }
        !          1409: }
        !          1410: #endif /* MACH_KDB */
        !          1411: 
        !          1412: /*
        !          1413:  *     thread_block_reason:
        !          1414:  *
        !          1415:  *     Block the current thread.  If the thread is runnable
        !          1416:  *     then someone must have woken it up between its request
        !          1417:  *     to sleep and now.  In this case, it goes back on a
        !          1418:  *     run queue.
        !          1419:  *
        !          1420:  *     If a continuation is specified, then thread_block will
        !          1421:  *     attempt to discard the thread's kernel stack.  When the
        !          1422:  *     thread resumes, it will execute the continuation function
        !          1423:  *     on a new kernel stack.
        !          1424:  */
        !          1425: counter(mach_counter_t  c_thread_block_calls = 0;)
        !          1426:  
        !          1427: int
        !          1428: thread_block_reason(
        !          1429:        void            (*continuation)(void),
        !          1430:        int                     reason)
        !          1431: {
        !          1432:        register thread_t               thread = current_thread();
        !          1433:        register processor_t    myprocessor;
        !          1434:        register thread_t               new_thread;
        !          1435:        register int                    aborted;
        !          1436:        spl_t                                   s;
        !          1437: 
        !          1438:        counter(++c_thread_block_calls);
        !          1439: 
        !          1440:        check_simple_locks();
        !          1441: 
        !          1442:        if (thread->funnel_state & TH_FN_OWNED) {
        !          1443:          thread->funnel_state = TH_FN_REFUNNEL;
        !          1444:          mutex_unlock(&funnel_lock);
        !          1445:        }
        !          1446: 
        !          1447:        machine_clock_assist();
        !          1448: 
        !          1449:        s = splsched();
        !          1450:        mp_disable_preemption();
        !          1451:        myprocessor = current_processor();
        !          1452: 
        !          1453:        thread_lock(thread);
        !          1454:        aborted = (thread->state & TH_ABORT);
        !          1455:        if (aborted)
        !          1456:                clear_wait_internal(thread, THREAD_INTERRUPTED);
        !          1457: 
        !          1458:        /* Unconditionally remove either | both */
        !          1459:        ast_off(AST_QUANTUM|AST_BLOCK|AST_URGENT);
        !          1460: 
        !          1461:        mp_enable_preemption();
        !          1462: 
        !          1463:        new_thread = thread_select(myprocessor);
        !          1464:        assert(new_thread);
        !          1465:        assert(thread_runnable(new_thread));
        !          1466:        thread_unlock(thread);
        !          1467:        while (!thread_invoke(thread, new_thread, reason, continuation)) {
        !          1468:                thread_lock(thread);
        !          1469:                new_thread = thread_select(myprocessor);
        !          1470:                assert(new_thread);
        !          1471:                assert(thread_runnable(new_thread));
        !          1472:                thread_unlock(thread);
        !          1473:        }
        !          1474: 
        !          1475:        splx(s);
        !          1476: 
        !          1477:        if (thread->funnel_state & TH_FN_REFUNNEL) {
        !          1478:                kern_return_t   save_wait_result;
        !          1479: 
        !          1480:                save_wait_result = thread->wait_result;
        !          1481:                thread->funnel_state = 0;
        !          1482:                mutex_lock(&funnel_lock);
        !          1483:                thread->funnel_state = TH_FN_OWNED;
        !          1484:                thread->wait_result = save_wait_result;
        !          1485:        }
        !          1486: 
        !          1487:        return thread->wait_result;
        !          1488: }
        !          1489: 
        !          1490: /*
        !          1491:  *     thread_block:
        !          1492:  *
        !          1493:  *     Now calls thread_block_reason() which forwards the
        !          1494:  *     the reason parameter to thread_invoke() so it can
        !          1495:  *     do the right thing if the thread's quantum expired.
        !          1496:  */
        !          1497: int
        !          1498: thread_block(
        !          1499:        void            (*continuation)(void))
        !          1500: {
        !          1501:        return thread_block_reason(continuation, 0);
        !          1502: }
        !          1503: 
        !          1504: /*
        !          1505:  *     thread_run:
        !          1506:  *
        !          1507:  *     Switch directly from the current thread to a specified
        !          1508:  *     thread.  Both the current and new threads must be
        !          1509:  *     runnable.
        !          1510:  */
        !          1511: void
        !          1512: thread_run(
        !          1513:        void                            (*continuation)(void),
        !          1514:        register thread_t       new_thread)
        !          1515: {
        !          1516:        register thread_t       thread = current_thread();
        !          1517:        spl_t                           s;
        !          1518: 
        !          1519:        s = splsched();
        !          1520:        while (!thread_invoke(thread, new_thread, 0, continuation)) {
        !          1521:                register processor_t myprocessor = current_processor();
        !          1522:                thread_lock(thread);
        !          1523:                new_thread = thread_select(myprocessor);
        !          1524:                thread_unlock(thread);
        !          1525:        }
        !          1526:        splx(s);
        !          1527: }
        !          1528: 
        !          1529: /*
        !          1530:  *     Dispatches a running thread that is not on a runq.
        !          1531:  *     Called at splsched.
        !          1532:  */
        !          1533: void
        !          1534: thread_dispatch(
        !          1535:        register thread_t       thread)
        !          1536: {
        !          1537:        sched_policy_t          *policy;
        !          1538:        sf_return_t                     sfr;
        !          1539: 
        !          1540:        /*
        !          1541:         *      If we are discarding the thread's stack, we must do it
        !          1542:         *      before the thread has a chance to run.
        !          1543:         */
        !          1544:        wake_lock(thread);
        !          1545:        thread_lock(thread);
        !          1546: 
        !          1547:     if (thread->continuation != (void (*)())0) {
        !          1548:       assert((thread->state & TH_STACK_STATE) == 0);
        !          1549:       thread->state |= TH_STACK_HANDOFF;
        !          1550: 
        !          1551:       stack_free(thread);
        !          1552:       if (thread->top_act) {
        !          1553:         act_machine_sv_free(thread->top_act);
        !          1554:         }
        !          1555:       }
        !          1556: 
        !          1557:        switch (thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) {
        !          1558: 
        !          1559:        case TH_RUN                              | TH_UNINT:
        !          1560:        case TH_RUN:
        !          1561:                /*
        !          1562:                 *      No reason to stop.  Put back on a run queue.
        !          1563:                 */
        !          1564:                /* Leave enqueueing thread up to scheduling policy */
        !          1565:                policy = &sched_policy[thread->policy];
        !          1566:                /*** ??? maybe use a macro ***/
        !          1567:                sfr = policy->sp_ops.sp_thread_dispatch(policy, thread);
        !          1568:                assert(sfr == SF_SUCCESS);
        !          1569:                break;
        !          1570: 
        !          1571:        case TH_RUN | TH_WAIT   | TH_UNINT:
        !          1572:        case TH_RUN | TH_WAIT:
        !          1573:                thread->sleep_stamp = sched_tick;
        !          1574:                /* fallthrough */
        !          1575:        case              TH_WAIT:                      /* this happens! */
        !          1576:        
        !          1577:                /*
        !          1578:                 *      Waiting
        !          1579:                 */
        !          1580:                thread->state &= ~TH_RUN;
        !          1581:                if (thread->state & TH_TERMINATE)
        !          1582:                        thread_reaper_enqueue(thread);
        !          1583: 
        !          1584:                if (thread->wake_active) {
        !          1585:                    thread->wake_active = FALSE;
        !          1586:                    thread_unlock(thread);
        !          1587:                    wake_unlock(thread);
        !          1588:                    thread_wakeup((event_t)&thread->wake_active);
        !          1589:                    return;
        !          1590:                }
        !          1591:                break;
        !          1592: 
        !          1593:        case TH_RUN                                             | TH_IDLE:
        !          1594:                /*
        !          1595:                 *      Drop idle thread -- it is already in
        !          1596:                 *      idle_thread_array.
        !          1597:                 */
        !          1598:                break;
        !          1599: 
        !          1600:        default:
        !          1601:                panic("State 0x%x \n",thread->state);
        !          1602:        }
        !          1603:        thread_unlock(thread);
        !          1604:        wake_unlock(thread);
        !          1605: }
        !          1606: 
        !          1607: /*
        !          1608:  * Enqueue thread on run_queue.
        !          1609:  */
        !          1610: int
        !          1611: run_queue_enqueue(
        !          1612:        register run_queue_t    rq,
        !          1613:        register thread_t               thread,
        !          1614:        boolean_t                               tail)
        !          1615: {
        !          1616:        register int                    whichq;
        !          1617:        int                                             oldrqcount;
        !          1618:        
        !          1619:        whichq = thread->sched_pri;
        !          1620:        if (whichq > MAXPRI || whichq < MINPRI) {
        !          1621:                panic("run_queue_enqueue: bad pri (%d)\n", whichq);
        !          1622:        }
        !          1623: 
        !          1624:        simple_lock(&rq->lock); /* lock the run queue */
        !          1625:        assert(thread->runq == RUN_QUEUE_NULL);
        !          1626:        if (tail)
        !          1627:                enqueue_tail(&rq->runq[whichq], (queue_entry_t)thread);
        !          1628:        else
        !          1629:                enqueue_head(&rq->runq[whichq], (queue_entry_t)thread);
        !          1630: 
        !          1631:        setbit(MAXPRI - whichq, rq->bitmap);
        !          1632:        if (whichq > rq->highq) {
        !          1633:                rq->highq = whichq;
        !          1634:        }
        !          1635:        oldrqcount = rq->count++;
        !          1636:        if (whichq == DEPRESSPRI)
        !          1637:            rq->depress_count++;
        !          1638:        thread->runq = rq;
        !          1639:        thread->whichq = whichq;
        !          1640: #if    DEBUG
        !          1641:        thread_check(thread, rq);
        !          1642: #endif /* DEBUG */
        !          1643:        simple_unlock(&rq->lock);
        !          1644: 
        !          1645:        return (oldrqcount);
        !          1646: }
        !          1647: 
        !          1648: /*
        !          1649:  *     thread_setrun:
        !          1650:  *
        !          1651:  *     Make thread runnable; dispatch directly onto an idle processor
        !          1652:  *     if possible.  Else put on appropriate run queue (processor
        !          1653:  *     if bound, else processor set.  Caller must have lock on thread.
        !          1654:  *     This is always called at splsched.
        !          1655:  *     The tail parameter, if TRUE || TAIL_Q, indicates that the 
        !          1656:  *     thread should be placed at the tail of the runq. If 
        !          1657:  *     FALSE || HEAD_Q the thread will be placed at the head of the 
        !          1658:  *      appropriate runq.
        !          1659:  */
        !          1660: void
        !          1661: thread_setrun(
        !          1662:        register thread_t                       new_thread,
        !          1663:        boolean_t                                       may_preempt,
        !          1664:        boolean_t                                       tail)
        !          1665: {
        !          1666:        register processor_t            processor;
        !          1667:        register run_queue_t            runq;
        !          1668:        register processor_set_t        pset;
        !          1669:        thread_t                                        thread;
        !          1670:        ast_t                                           ast_flags = AST_BLOCK;
        !          1671: 
        !          1672:        mp_disable_preemption();
        !          1673: 
        !          1674:        assert(!(new_thread->state & TH_SWAPPED_OUT));
        !          1675:        assert(thread_runnable(new_thread));
        !          1676:        
        !          1677:        /*
        !          1678:         *      Update priority if needed.
        !          1679:         */
        !          1680:        /*** ??? fix me ***/
        !          1681:        if (new_thread->policy & (POLICY_TIMESHARE|POLICY_RR|POLICY_FIFO)) {
        !          1682:                mk_sp_info_t                    sp_info = new_thread->sp_info;
        !          1683: 
        !          1684:                assert(sp_info != SP_INFO_NULL);
        !          1685:                if (sp_info->sched_stamp != sched_tick)
        !          1686:                        update_priority(new_thread);
        !          1687: 
        !          1688: #if 0 /* TEMPORARILY DISABLE PREEMPTION */
        !          1689:                if (    (new_thread->policy & (POLICY_FIFO|POLICY_RR))          &&
        !          1690:                                sp_info->priority > BASEPRI_SYSTEM                                              )
        !          1691:                        ast_flags |= AST_URGENT;
        !          1692: #endif /* TEMPORARILY DISABLE PREEMPTION */
        !          1693:        }
        !          1694:        
        !          1695:        assert(new_thread->runq == RUN_QUEUE_NULL);
        !          1696: 
        !          1697:        /*** ??? fix me ***/
        !          1698:        assert(new_thread->sp_info != SP_INFO_NULL);
        !          1699: 
        !          1700:        /*
        !          1701:         *      Try to dispatch the thread directly onto an idle processor.
        !          1702:         */
        !          1703:        if ((processor = new_thread->bound_processor) == PROCESSOR_NULL) {
        !          1704:            /*
        !          1705:             *  Not bound, any processor in the processor set is ok.
        !          1706:             */
        !          1707:            pset = new_thread->processor_set;
        !          1708:            if (pset->idle_count > 0) {
        !          1709:                        simple_lock(&pset->idle_lock);
        !          1710:                        if (pset->idle_count > 0) {
        !          1711:                                processor = (processor_t) queue_first(&pset->idle_queue);
        !          1712:                                queue_remove(&(pset->idle_queue), processor, processor_t,
        !          1713:                                        processor_queue);
        !          1714:                                pset->idle_count--;
        !          1715:                                processor->next_thread = new_thread;
        !          1716:                                processor->state = PROCESSOR_DISPATCHING;
        !          1717:                                simple_unlock(&pset->idle_lock);
        !          1718: 
        !          1719:                                mp_enable_preemption();
        !          1720:                                return;
        !          1721:                        }
        !          1722:                        simple_unlock(&pset->idle_lock);
        !          1723:            }
        !          1724:        
        !          1725: 
        !          1726:            /*
        !          1727:             * Preempt check
        !          1728:             */
        !          1729:            runq = &pset->runq;
        !          1730:                thread = current_thread();
        !          1731:            processor = current_processor();
        !          1732:            if (        may_preempt                                                                     &&
        !          1733: #if    MACH_HOST
        !          1734:                                pset == processor->processor_set                        &&
        !          1735: #endif /* MACH_HOST */
        !          1736:                                thread->sched_pri < new_thread->sched_pri                       ) {
        !          1737:                        simple_lock(&processor->lock);
        !          1738:                        pset = processor->processor_set;
        !          1739:                        simple_lock(&pset->idle_lock);
        !          1740: 
        !          1741:                    /*
        !          1742:                     * XXX if we have a non-empty local runq or are
        !          1743:                     * XXX running a bound thread, ought to check for
        !          1744:                     * XXX another cpu running lower-pri thread to preempt.
        !          1745:                     *
        !          1746:                     *  Turn off first_quantum to allow csw.
        !          1747:                     */
        !          1748:                        if (processor->state == PROCESSOR_DISPATCHING) {
        !          1749:                                thread = processor->next_thread;
        !          1750:                                processor->next_thread = new_thread;
        !          1751:                                simple_unlock(&pset->idle_lock);
        !          1752:                                simple_unlock(&processor->lock);
        !          1753:                                new_thread = thread;
        !          1754:                        }
        !          1755:                        else {
        !          1756:                                simple_unlock(&pset->idle_lock);
        !          1757:                                simple_unlock(&processor->lock);
        !          1758:                                processor->first_quantum = FALSE;
        !          1759:                                ast_on(ast_flags);
        !          1760:                        }
        !          1761:            }
        !          1762: 
        !          1763:                /*
        !          1764:                 * Put us on the end of the runq, if we are not preempting
        !          1765:                 * or the guy we are preempting.
        !          1766:                 */
        !          1767:                run_queue_enqueue(runq, new_thread, tail);
        !          1768:        }
        !          1769:        else {
        !          1770:            /*
        !          1771:             *  Bound, can only run on bound processor.  Have to lock
        !          1772:             *  processor here because it may not be the current one.
        !          1773:             */
        !          1774:            if (processor->state == PROCESSOR_IDLE) {
        !          1775:                        simple_lock(&processor->lock);
        !          1776:                        pset = processor->processor_set;
        !          1777:                        simple_lock(&pset->idle_lock);
        !          1778:                        if (processor->state == PROCESSOR_IDLE) {
        !          1779:                                queue_remove(&pset->idle_queue, processor,
        !          1780:                                processor_t, processor_queue);
        !          1781:                                pset->idle_count--;
        !          1782:                                processor->next_thread = new_thread;
        !          1783:                                processor->state = PROCESSOR_DISPATCHING;
        !          1784:                                simple_unlock(&pset->idle_lock);
        !          1785:                                simple_unlock(&processor->lock);
        !          1786: 
        !          1787:                                mp_enable_preemption();
        !          1788:                                return;
        !          1789:                        }
        !          1790:                        simple_unlock(&pset->idle_lock);
        !          1791:                        simple_unlock(&processor->lock);
        !          1792:                }
        !          1793:          
        !          1794:            /*
        !          1795:             * Cause ast on processor if processor is on line, and the
        !          1796:             * currently executing thread is not bound to that processor
        !          1797:             * (bound threads have implicit priority over non-bound threads).
        !          1798:             * We also avoid sending the AST to the idle thread (if it got
        !          1799:             * scheduled in the window between the 'if' above and here),
        !          1800:             * since the idle_thread is bound.
        !          1801:             */
        !          1802:            runq = &processor->runq;
        !          1803:                thread = current_thread();
        !          1804:            if (processor == current_processor()) {
        !          1805:                        if (    thread->bound_processor == PROCESSOR_NULL               ||
        !          1806:                                                thread->sched_pri > new_thread->sched_pri               ) {
        !          1807:                                if (processor->state == PROCESSOR_DISPATCHING) {
        !          1808:                                        thread = processor->next_thread;
        !          1809:                                        processor->next_thread = new_thread;
        !          1810:                                        new_thread = thread;
        !          1811:                                } 
        !          1812:                                else {
        !          1813:                                        processor->first_quantum = FALSE;
        !          1814:                                        ast_on(ast_flags);
        !          1815:                                }
        !          1816:                        }
        !          1817: 
        !          1818:                        run_queue_enqueue(runq, new_thread, tail);
        !          1819:            }
        !          1820:                else {
        !          1821:                        thread = cpu_data[processor->slot_num].active_thread;
        !          1822:                        if (    run_queue_enqueue(runq, new_thread, tail) == 0  &&
        !          1823:                                        processor->state != PROCESSOR_OFF_LINE                  &&
        !          1824:                                        thread && thread->bound_processor != processor          )
        !          1825:                                cause_ast_check(processor);
        !          1826:            }
        !          1827:        }
        !          1828: 
        !          1829:        mp_enable_preemption();
        !          1830: }
        !          1831: 
        !          1832: /*
        !          1833:  *     set_pri:
        !          1834:  *
        !          1835:  *     Set the priority of the specified thread to the specified
        !          1836:  *     priority.  This may cause the thread to change queues.
        !          1837:  *
        !          1838:  *     The thread *must* be locked by the caller.
        !          1839:  */
        !          1840: void
        !          1841: set_pri(
        !          1842:        thread_t                        thread,
        !          1843:        int                                     pri,
        !          1844:        boolean_t                       resched)
        !          1845: {
        !          1846:        register struct run_queue       *rq;
        !          1847: 
        !          1848:        rq = rem_runq(thread);
        !          1849:        assert(thread->runq == RUN_QUEUE_NULL);
        !          1850:        thread->sched_pri = pri;
        !          1851:        if (rq != RUN_QUEUE_NULL) {
        !          1852:            if (resched)
        !          1853:                        thread_setrun(thread, TRUE, TAIL_Q);
        !          1854:            else
        !          1855:                        run_queue_enqueue(rq, thread, TAIL_Q);
        !          1856:        }
        !          1857: }
        !          1858: 
        !          1859: /*
        !          1860:  *     rem_runq:
        !          1861:  *
        !          1862:  *     Remove a thread from its run queue.
        !          1863:  *     The run queue that the process was on is returned
        !          1864:  *     (or RUN_QUEUE_NULL if not on a run queue).  Thread *must* be locked
        !          1865:  *     before calling this routine.  Unusual locking protocol on runq
        !          1866:  *     field in thread structure makes this code interesting; see thread.h.
        !          1867:  */
        !          1868: run_queue_t
        !          1869: rem_runq(
        !          1870:        thread_t                        thread)
        !          1871: {
        !          1872:        register struct run_queue       *rq;
        !          1873: 
        !          1874:        rq = thread->runq;
        !          1875:        /*
        !          1876:         *      If rq is RUN_QUEUE_NULL, the thread will stay out of the
        !          1877:         *      run_queues because the caller locked the thread.  Otherwise
        !          1878:         *      the thread is on a runq, but could leave.
        !          1879:         */
        !          1880:        if (rq != RUN_QUEUE_NULL) {
        !          1881: #if DEBUG
        !          1882:                thread_t        t;
        !          1883:                int             whichq;
        !          1884: #endif
        !          1885:                simple_lock(&rq->lock);
        !          1886:                if (rq == thread->runq) {
        !          1887:                        /*
        !          1888:                         *      Thread is in a runq and we have a lock on
        !          1889:                         *      that runq.
        !          1890:                         */
        !          1891: #if    DEBUG
        !          1892:                        thread_check(thread, rq);
        !          1893: #endif /* DEBUG */
        !          1894:                        remqueue(&rq->runq[0], (queue_entry_t)thread);
        !          1895:                        rq->count--;
        !          1896: 
        !          1897:                        if (thread->whichq == DEPRESSPRI)
        !          1898:                            rq->depress_count--;
        !          1899: 
        !          1900:                        if (queue_empty(rq->runq + thread->sched_pri)) {
        !          1901:                                /* update run queue status */
        !          1902:                                clrbit(MAXPRI - thread->sched_pri, rq->bitmap);
        !          1903:                                rq->highq = MAXPRI - ffsbit(rq->bitmap);
        !          1904:                        }
        !          1905:                        thread->runq = RUN_QUEUE_NULL;
        !          1906:                        simple_unlock(&rq->lock);
        !          1907:                }
        !          1908:                else {
        !          1909:                        /*
        !          1910:                         *      The thread left the runq before we could
        !          1911:                         *      lock the runq.  It is not on a runq now, and
        !          1912:                         *      can't move again because this routine's
        !          1913:                         *      caller locked the thread.
        !          1914:                         */
        !          1915:                        assert(thread->runq == RUN_QUEUE_NULL);
        !          1916:                        simple_unlock(&rq->lock);
        !          1917:                        rq = RUN_QUEUE_NULL;
        !          1918:                }
        !          1919:        }
        !          1920: 
        !          1921:        return (rq);
        !          1922: }
        !          1923: 
        !          1924: 
        !          1925: /*
        !          1926:  *     choose_thread:
        !          1927:  *
        !          1928:  *     Choose a thread to execute.  The thread chosen is removed
        !          1929:  *     from its run queue.  Note that this requires only that the runq
        !          1930:  *     lock be held.
        !          1931:  *
        !          1932:  *     Strategy:
        !          1933:  *             Check processor runq first; if anything found, run it.
        !          1934:  *             Else check pset runq; if nothing found, return idle thread.
        !          1935:  *
        !          1936:  *     Second line of strategy is implemented by choose_pset_thread.
        !          1937:  *     This is only called on processor startup and when thread_block
        !          1938:  *     thinks there's something in the processor runq.
        !          1939:  */
        !          1940: thread_t
        !          1941: choose_thread(
        !          1942:        processor_t             myprocessor)
        !          1943: {
        !          1944:        thread_t                                thread;
        !          1945:        register queue_t                q;
        !          1946:        register run_queue_t    runq;
        !          1947:        processor_set_t                 pset;
        !          1948: 
        !          1949:        runq = &myprocessor->runq;
        !          1950:        pset = myprocessor->processor_set;
        !          1951: 
        !          1952:        simple_lock(&runq->lock);
        !          1953:        if (runq->count > 0 && runq->highq >= pset->runq.highq) {
        !          1954:                q = runq->runq + runq->highq;
        !          1955: #if    MACH_ASSERT
        !          1956:                if (!queue_empty(q)) {
        !          1957: #endif /*MACH_ASSERT*/
        !          1958:                        thread = (thread_t)q->next;
        !          1959:                        ((queue_entry_t)thread)->next->prev = q;
        !          1960:                        q->next = ((queue_entry_t)thread)->next;
        !          1961:                        thread->runq = RUN_QUEUE_NULL;
        !          1962:                        runq->count--;
        !          1963:                        if (thread->whichq == DEPRESSPRI)
        !          1964:                            runq->depress_count--;
        !          1965:                        if (queue_empty(q)) {
        !          1966:                                clrbit(MAXPRI - runq->highq, runq->bitmap);
        !          1967:                                runq->highq = MAXPRI - ffsbit(runq->bitmap);
        !          1968:                        }
        !          1969:                        simple_unlock(&runq->lock);
        !          1970:                        return (thread);
        !          1971: #if    MACH_ASSERT
        !          1972:                }
        !          1973:                panic("choose_thread");
        !          1974: #endif /*MACH_ASSERT*/
        !          1975:                /*NOTREACHED*/
        !          1976:        }
        !          1977: 
        !          1978:        simple_unlock(&runq->lock);
        !          1979:        simple_lock(&pset->runq.lock);
        !          1980:        return (choose_pset_thread(myprocessor, pset));
        !          1981: }
        !          1982: 
        !          1983: 
        !          1984: /*
        !          1985:  *     choose_pset_thread:  choose a thread from processor_set runq or
        !          1986:  *             set processor idle and choose its idle thread.
        !          1987:  *
        !          1988:  *     Caller must be at splsched and have a lock on the runq.  This
        !          1989:  *     lock is released by this routine.  myprocessor is always the current
        !          1990:  *     processor, and pset must be its processor set.
        !          1991:  *     This routine chooses and removes a thread from the runq if there
        !          1992:  *     is one (and returns it), else it sets the processor idle and
        !          1993:  *     returns its idle thread.
        !          1994:  */
        !          1995: thread_t
        !          1996: choose_pset_thread(
        !          1997:        register processor_t    myprocessor,
        !          1998:        processor_set_t                 pset)
        !          1999: {
        !          2000:        register run_queue_t    runq;
        !          2001:        register thread_t               thread;
        !          2002:        register queue_t                q;
        !          2003: 
        !          2004:        runq = &pset->runq;
        !          2005:        if (runq->count > 0) {
        !          2006:                q = runq->runq + runq->highq;
        !          2007: #if    MACH_ASSERT
        !          2008:                if (!queue_empty(q)) {
        !          2009: #endif /*MACH_ASSERT*/
        !          2010:                        thread = (thread_t)q->next;
        !          2011:                        ((queue_entry_t)thread)->next->prev = q;
        !          2012:                        q->next = ((queue_entry_t)thread)->next;
        !          2013:                        thread->runq = RUN_QUEUE_NULL;
        !          2014:                        runq->count--;
        !          2015:                        if (thread->whichq == DEPRESSPRI)
        !          2016:                            runq->depress_count--;
        !          2017:                        if (queue_empty(q)) {
        !          2018:                                clrbit(MAXPRI - runq->highq, runq->bitmap);
        !          2019:                                runq->highq = MAXPRI - ffsbit(runq->bitmap);
        !          2020:                        }
        !          2021:                        simple_unlock(&runq->lock);
        !          2022:                        return (thread);
        !          2023: #if    MACH_ASSERT
        !          2024:                }
        !          2025:                panic("choose_pset_thread");
        !          2026: #endif /*MACH_ASSERT*/
        !          2027:                /*NOTREACHED*/
        !          2028:        }
        !          2029:        simple_unlock(&runq->lock);
        !          2030: 
        !          2031:        /*
        !          2032:         *      Nothing is runnable, so set this processor idle if it
        !          2033:         *      was running.  If it was in an assignment or shutdown,
        !          2034:         *      leave it alone.  Return its idle thread.
        !          2035:         */
        !          2036:        simple_lock(&pset->idle_lock);
        !          2037:        if (myprocessor->state == PROCESSOR_RUNNING) {
        !          2038:            myprocessor->state = PROCESSOR_IDLE;
        !          2039:            /*
        !          2040:             *  XXX Until it goes away, put master on end of queue, others
        !          2041:             *  XXX on front so master gets used last.
        !          2042:             */
        !          2043:            if (myprocessor == master_processor)
        !          2044:                        queue_enter(&(pset->idle_queue), myprocessor,
        !          2045:                                                                        processor_t, processor_queue);
        !          2046:            else
        !          2047:                        queue_enter_first(&(pset->idle_queue), myprocessor,
        !          2048:                                                                                processor_t, processor_queue);
        !          2049: 
        !          2050:            pset->idle_count++;
        !          2051:        }
        !          2052:        simple_unlock(&pset->idle_lock);
        !          2053: 
        !          2054:        return (myprocessor->idle_thread);
        !          2055: }
        !          2056: 
        !          2057: /*
        !          2058:  *     no_dispatch_count counts number of times processors go non-idle
        !          2059:  *     without being dispatched.  This should be very rare.
        !          2060:  */
        !          2061: int    no_dispatch_count = 0;
        !          2062: 
        !          2063: /*
        !          2064:  *     This is the idle thread, which just looks for other threads
        !          2065:  *     to execute.
        !          2066:  */
        !          2067: void
        !          2068: idle_thread_continue(void)
        !          2069: {
        !          2070:        register processor_t            myprocessor;
        !          2071:        register volatile thread_t      *threadp;
        !          2072:        register volatile int           *gcount;
        !          2073:        register volatile int           *lcount;
        !          2074:        register thread_t                       new_thread;
        !          2075:        register int                            state;
        !          2076:        register processor_set_t        pset;
        !          2077:        int                                                     mycpu;
        !          2078:        spl_t                                           s;
        !          2079: 
        !          2080:        mycpu = cpu_number();
        !          2081:        myprocessor = current_processor();
        !          2082:        threadp = (volatile thread_t *) &myprocessor->next_thread;
        !          2083:        lcount = (volatile int *) &myprocessor->runq.count;
        !          2084: 
        !          2085:        for (;;) {
        !          2086: #ifdef MARK_CPU_IDLE
        !          2087:                MARK_CPU_IDLE(mycpu);
        !          2088: #endif /* MARK_CPU_IDLE */
        !          2089: 
        !          2090: #if     MACH_HOST
        !          2091:                gcount = (volatile int *)&myprocessor->processor_set->runq.count;
        !          2092: #else   /* MACH_HOST */
        !          2093:                gcount = (volatile int *)&default_pset.runq.count;
        !          2094: #endif  /* MACH_HOST */
        !          2095: 
        !          2096: /*
        !          2097:  *     This cpu will be dispatched (by thread_setrun) by setting next_thread
        !          2098:  *     to the value of the thread to run next.  Also check runq counts.
        !          2099:  */
        !          2100:                s = splsched();
        !          2101:                while ((*threadp == (volatile thread_t)THREAD_NULL) && (*gcount == 0) && (*lcount == 0)) {
        !          2102: 
        !          2103:                        /* check for ASTs while we wait */
        !          2104: 
        !          2105:                        if (need_ast[mycpu] &~ (AST_SCHEDULING|AST_BSD|AST_BSD_INIT)) {
        !          2106:                                /* don't allow scheduling ASTs */
        !          2107:                                need_ast[mycpu] &= ~(AST_SCHEDULING|AST_BSD|AST_BSD_INIT);
        !          2108:                                splx(s);
        !          2109:                                ast_taken(FALSE, AST_ALL, s);
        !          2110:                                /* back at spllo */
        !          2111:                        }
        !          2112:                        else
        !          2113:                                splx(s);
        !          2114: 
        !          2115:                        machine_clock_assist();
        !          2116: 
        !          2117:                        /*
        !          2118:                         * machine_idle is a machine dependent function,
        !          2119:                         * to conserve power.
        !          2120:                         */
        !          2121: #if    POWER_SAVE
        !          2122:                        machine_idle(mycpu);
        !          2123: #endif /* POWER_SAVE */
        !          2124:                        s = splsched();
        !          2125:                }
        !          2126: 
        !          2127: #ifdef MARK_CPU_ACTIVE
        !          2128:                splx(s);
        !          2129:                MARK_CPU_ACTIVE(mycpu);
        !          2130:                s = splsched();
        !          2131: #endif /* MARK_CPU_ACTIVE */
        !          2132: 
        !          2133:                /*
        !          2134:                 *      This is not a switch statement to avoid the
        !          2135:                 *      bounds checking code in the common case.
        !          2136:                 */
        !          2137:                pset = myprocessor->processor_set;
        !          2138:                simple_lock(&pset->idle_lock);
        !          2139: retry:
        !          2140:                state = myprocessor->state;
        !          2141:                if (state == PROCESSOR_DISPATCHING) {
        !          2142:                        /*
        !          2143:                         *      Commmon case -- cpu dispatched.
        !          2144:                         */
        !          2145:                        new_thread = *threadp;
        !          2146:                        *threadp = (volatile thread_t) THREAD_NULL;
        !          2147:                        myprocessor->state = PROCESSOR_RUNNING;
        !          2148: 
        !          2149:                        simple_unlock(&pset->idle_lock);
        !          2150:                        thread_lock(new_thread);
        !          2151:                
        !          2152:                        /*
        !          2153:                         *      set up quantum for new thread.
        !          2154:                         */
        !          2155:                        if (new_thread->policy == POLICY_TIMESHARE) {
        !          2156:                                /*
        !          2157:                                 *  Just use set quantum.  No point in
        !          2158:                                 *  checking for shorter local runq quantum;
        !          2159:                                 *  csw_needed will handle correctly.
        !          2160:                                 */
        !          2161: #if    MACH_HOST
        !          2162:                                myprocessor->quantum = new_thread->processor_set->set_quantum;
        !          2163: #else  /* MACH_HOST */
        !          2164:                                myprocessor->quantum = default_pset.set_quantum;
        !          2165: #endif /* MACH_HOST */
        !          2166:                        }
        !          2167:                        else
        !          2168:                        if (new_thread->policy & (POLICY_RR|POLICY_FIFO)) {
        !          2169:                                mk_sp_info_t    sp_info = (mk_sp_info_t)new_thread->sp_info;
        !          2170: 
        !          2171:                                assert(sp_info != SP_INFO_NULL);
        !          2172:                                myprocessor->quantum = sp_info->unconsumed_quantum;
        !          2173:                        }
        !          2174: 
        !          2175:                        thread_unlock(new_thread);
        !          2176: 
        !          2177:                        myprocessor->first_quantum = TRUE;
        !          2178:                        counter(c_idle_thread_handoff++);
        !          2179:                        thread_run((void(*)(void))0, new_thread);
        !          2180:                }
        !          2181:                else
        !          2182:                if (state == PROCESSOR_IDLE) {
        !          2183: 
        !          2184:                        if (myprocessor->state != PROCESSOR_IDLE) {
        !          2185:                                /*
        !          2186:                                 *      Something happened, try again.
        !          2187:                                 */
        !          2188:                                goto retry;
        !          2189:                        }
        !          2190:                        /*
        !          2191:                         *      Processor was not dispatched (Rare).
        !          2192:                         *      Set it running again.
        !          2193:                         */
        !          2194:                        no_dispatch_count++;
        !          2195:                        pset->idle_count--;
        !          2196:                        queue_remove(&pset->idle_queue, myprocessor,
        !          2197:                                                                        processor_t, processor_queue);
        !          2198:                        myprocessor->state = PROCESSOR_RUNNING;
        !          2199:                        simple_unlock(&pset->idle_lock);
        !          2200:                        counter(c_idle_thread_block++);
        !          2201:                        thread_block((void(*)(void))0);
        !          2202:                }
        !          2203:                else
        !          2204:                if (    state == PROCESSOR_ASSIGN               ||
        !          2205:                                state == PROCESSOR_SHUTDOWN                     ) {
        !          2206:                        /*
        !          2207:                         *      Changing processor sets, or going off-line.
        !          2208:                         *      Release next_thread if there is one.  Actual
        !          2209:                         *      thread to run in on a runq.
        !          2210:                         */
        !          2211:                        if ((new_thread = (thread_t)*threadp)!= THREAD_NULL) {
        !          2212:                                *threadp = (volatile thread_t) THREAD_NULL;
        !          2213:                                thread_setrun(new_thread, FALSE, TAIL_Q);
        !          2214:                        }
        !          2215: 
        !          2216:                        counter(c_idle_thread_block++);
        !          2217:                        thread_block((void(*)(void))0);
        !          2218:                }
        !          2219:                else {
        !          2220:                        simple_unlock(&pset->idle_lock);
        !          2221:                        printf("Bad processor state %d (Cpu %d)\n",
        !          2222:                                                                                cpu_state(mycpu), mycpu);
        !          2223:                        panic("idle_thread");
        !          2224: 
        !          2225:                }
        !          2226:                splx(s);
        !          2227:        }
        !          2228: }
        !          2229: 
        !          2230: void
        !          2231: idle_thread(void)
        !          2232: {
        !          2233:        thread_t                self = current_thread();
        !          2234:        mk_sp_info_t    sp_info;
        !          2235:        spl_t                   s;
        !          2236: 
        !          2237:        stack_privilege(self);
        !          2238:        thread_swappable(current_act(), FALSE);
        !          2239: 
        !          2240:        s = splsched();
        !          2241:        thread_lock(self);
        !          2242: 
        !          2243:        /*
        !          2244:         *      Set the idle flag to indicate that this is an idle thread,
        !          2245:         *      enter ourselves in the idle array, and thread_block() to get
        !          2246:         *      out of the run queues (and set the processor idle when we
        !          2247:         *      run next time).
        !          2248:         */
        !          2249:        self->state |= TH_IDLE;
        !          2250:        current_processor()->idle_thread = self;
        !          2251: 
        !          2252:        /*** ??? fix me ***/
        !          2253:        assert(self->policy == POLICY_FIFO);
        !          2254:        sp_info = (mk_sp_info_t)self->sp_info;
        !          2255:        assert(sp_info != SP_INFO_NULL);
        !          2256:        sp_info->priority = IDLEPRI;
        !          2257:        self->sched_pri = sp_info->priority;
        !          2258: 
        !          2259:        thread_unlock(self);
        !          2260:        splx(s);
        !          2261: 
        !          2262:        counter(c_idle_thread_block++);
        !          2263:        thread_block((void(*)(void))0);
        !          2264:        idle_thread_continue();
        !          2265:        /*NOTREACHED*/
        !          2266: 
        !          2267:        panic("idle_thread_continue!");
        !          2268: }
        !          2269: 
        !          2270: static thread_call_t           sched_tick_timer;
        !          2271: static thread_call_data_t      sched_tick_timer_data;
        !          2272: static AbsoluteTime                    sched_tick_interval, sched_tick_deadline;
        !          2273: 
        !          2274: /*
        !          2275:  *     recompute_priorities:
        !          2276:  *
        !          2277:  *     Update the priorities of all threads periodically.
        !          2278:  */
        !          2279: void
        !          2280: _recompute_priorities(void)
        !          2281: {
        !          2282:        AbsoluteTime            abstime;
        !          2283: #if    SIMPLE_CLOCK
        !          2284:        int                                     new_usec;
        !          2285: #endif /* SIMPLE_CLOCK */
        !          2286: 
        !          2287:        clock_get_uptime(&abstime);
        !          2288: 
        !          2289:        sched_tick++;           /* age usage one more time */
        !          2290: #if    SIMPLE_CLOCK
        !          2291:        /*
        !          2292:         *      Compensate for clock drift.  sched_usec is an
        !          2293:         *      exponential average of the number of microseconds in
        !          2294:         *      a second.  It decays in the same fashion as cpu_usage.
        !          2295:         */
        !          2296:        new_usec = sched_usec_elapsed();
        !          2297:        sched_usec = (5*sched_usec + 3*new_usec)/8;
        !          2298: #endif /* SIMPLE_CLOCK */
        !          2299: 
        !          2300:     /*
        !          2301:         *  Compute the scheduler load factors.
        !          2302:         */
        !          2303:        compute_mach_factor();
        !          2304: 
        !          2305:        /*
        !          2306:         *  Scan the run queues for runnable threads that need to
        !          2307:         *  have their priorities recalculated.
        !          2308:         */
        !          2309:        do_thread_scan();
        !          2310: 
        !          2311:        clock_deadline_for_periodic_event(sched_tick_interval, abstime,
        !          2312:                                                                                          &sched_tick_deadline);
        !          2313:        thread_call_enter_delayed(sched_tick_timer, sched_tick_deadline);
        !          2314: }
        !          2315: 
        !          2316: void
        !          2317: recompute_priorities(void)
        !          2318: {
        !          2319:        thread_call_setup(&sched_tick_timer_data, _recompute_priorities, NULL);
        !          2320:        clock_interval_to_absolutetime_interval(1, NSEC_PER_SEC,
        !          2321:                                                                                                &sched_tick_interval);
        !          2322:        clock_get_uptime(&sched_tick_deadline);
        !          2323:        sched_tick_timer = &sched_tick_timer_data;
        !          2324: 
        !          2325:        _recompute_priorities();
        !          2326: }
        !          2327: 
        !          2328: #define        MAX_STUCK_THREADS       128
        !          2329: 
        !          2330: /*
        !          2331:  *     do_thread_scan: scan for stuck threads.  A thread is stuck if
        !          2332:  *     it is runnable but its priority is so low that it has not
        !          2333:  *     run for several seconds.  Its priority should be higher, but
        !          2334:  *     won't be until it runs and calls update_priority.  The scanner
        !          2335:  *     finds these threads and does the updates.
        !          2336:  *
        !          2337:  *     Scanner runs in two passes.  Pass one squirrels likely
        !          2338:  *     thread ids away in an array  (takes out references for them).
        !          2339:  *     Pass two does the priority updates.  This is necessary because
        !          2340:  *     the run queue lock is required for the candidate scan, but
        !          2341:  *     cannot be held during updates [set_pri will deadlock].
        !          2342:  *
        !          2343:  *     Array length should be enough so that restart isn't necessary,
        !          2344:  *     but restart logic is included.  Does not scan processor runqs.
        !          2345:  *
        !          2346:  */
        !          2347: thread_t               stuck_threads[MAX_STUCK_THREADS];
        !          2348: int                            stuck_count = 0;
        !          2349: 
        !          2350: /*
        !          2351:  *     do_runq_scan is the guts of pass 1.  It scans a runq for
        !          2352:  *     stuck threads.  A boolean is returned indicating whether
        !          2353:  *     a retry is needed.
        !          2354:  */
        !          2355: boolean_t
        !          2356: do_runq_scan(
        !          2357:        run_queue_t                             runq,
        !          2358:        int                                             *mask)
        !          2359: {
        !          2360:        register queue_t                q;
        !          2361:        register thread_t               thread;
        !          2362:        register int                    count;
        !          2363:        int                                             qindex;
        !          2364:        spl_t                                   s;
        !          2365:        boolean_t                               result = FALSE;
        !          2366: 
        !          2367:        s = splsched();
        !          2368:        simple_lock(&runq->lock);
        !          2369:        if ((count = runq->count) > 0) {
        !          2370:            q = runq->runq + runq->highq;
        !          2371:            qindex = runq->highq;
        !          2372:                while (count > 0) {
        !          2373:                        boolean_t               qvalid = testbit(qindex, mask);
        !          2374: 
        !          2375:                        queue_iterate(q, thread, thread_t, links) {
        !          2376:                                if (    qvalid                                                                  &&
        !          2377:                                                !(thread->state & (TH_WAIT|TH_SUSP))    &&
        !          2378:                                                thread->policy == POLICY_TIMESHARE                              ) {
        !          2379:                                        mk_sp_info_t                    sp_info = thread->sp_info;
        !          2380: 
        !          2381:                                        assert(sp_info != SP_INFO_NULL);
        !          2382:                                        /*** ??? fix me ***/
        !          2383:                                        if (sp_info->sched_stamp != sched_tick) {
        !          2384:                                                /*
        !          2385:                                                 *      Stuck, save its id for later.
        !          2386:                                                 */
        !          2387:                                                if (stuck_count == MAX_STUCK_THREADS) {
        !          2388:                                                        /*
        !          2389:                                                         *      !@#$% No more room.
        !          2390:                                                         */
        !          2391:                                                        simple_unlock(&runq->lock);
        !          2392:                                                        splx(s);
        !          2393: 
        !          2394:                                                        return (TRUE);
        !          2395:                                                }
        !          2396: 
        !          2397:                                                /*
        !          2398:                                                 * Inline version of thread_reference
        !          2399:                                                 * XXX - lock ordering problem here:
        !          2400:                                                 * thread locks should be taken before runq
        !          2401:                                                 * locks: just try and get the thread's locks
        !          2402:                                                 * and ignore this thread if we fail, we might
        !          2403:                                                 * have better luck next time.
        !          2404:                                                 */
        !          2405:                                                if (simple_lock_try(&thread->lock)) {
        !          2406:                                                        thread->ref_count++;
        !          2407:                                                        thread_unlock(thread);
        !          2408:                                                        stuck_threads[stuck_count++] = thread;
        !          2409:                                                }
        !          2410:                                                else
        !          2411:                                                        result = TRUE;
        !          2412:                                        }
        !          2413:                                }
        !          2414: 
        !          2415:                                count--;
        !          2416:                        }
        !          2417: 
        !          2418:                        q--;
        !          2419:                        qindex--;
        !          2420:                }
        !          2421:        }
        !          2422:        simple_unlock(&runq->lock);
        !          2423:        splx(s);
        !          2424: 
        !          2425:        return (result);
        !          2426: }
        !          2427: 
        !          2428: boolean_t      thread_scan_enabled = TRUE;
        !          2429: 
        !          2430: void
        !          2431: do_thread_scan(void)
        !          2432: {
        !          2433:        register boolean_t                      restart_needed = FALSE;
        !          2434:        register thread_t                       thread;
        !          2435: #if    MACH_HOST
        !          2436:        register processor_set_t        pset;
        !          2437: #endif /* MACH_HOST */
        !          2438:        int                                                     *mask;
        !          2439:        spl_t                                           s;
        !          2440: 
        !          2441:        if (!thread_scan_enabled)
        !          2442:                return;
        !          2443: 
        !          2444:        mask = sched_policy[POLICY_TIMESHARE].priority_mask.bitmap;
        !          2445: 
        !          2446:        do {
        !          2447: #if    MACH_HOST
        !          2448:            mutex_lock(&all_psets_lock);
        !          2449:            queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
        !          2450:                        if (restart_needed = do_runq_scan(&pset->runq, mask))
        !          2451:                                break;
        !          2452:            }
        !          2453:            mutex_unlock(&all_psets_lock);
        !          2454: #else  /* MACH_HOST */
        !          2455:            restart_needed = do_runq_scan(&default_pset.runq, mask);
        !          2456: #endif /* MACH_HOST */
        !          2457:            if (!restart_needed)
        !          2458:                restart_needed = do_runq_scan(&master_processor->runq, mask);
        !          2459: 
        !          2460:            /*
        !          2461:             *  Ok, we now have a collection of candidates -- fix them.
        !          2462:             */
        !          2463:            while (stuck_count > 0) {
        !          2464:                        thread = stuck_threads[--stuck_count];
        !          2465:                        stuck_threads[stuck_count] = THREAD_NULL;
        !          2466:                        s = splsched();
        !          2467:                        thread_lock(thread);
        !          2468:                        /*** ??? fix me ***/
        !          2469:                        if (thread->policy == POLICY_TIMESHARE) {
        !          2470:                                mk_sp_info_t            sp_info = thread->sp_info;
        !          2471: 
        !          2472:                                assert(thread->sp_info != SP_INFO_NULL);
        !          2473:                                if (    !(thread->state & (TH_WAIT|TH_SUSP))    &&
        !          2474:                                                /*** ??? fix me ***/
        !          2475:                                                sp_info->sched_stamp != sched_tick                      )
        !          2476:                                        update_priority(thread);
        !          2477:                        }
        !          2478:                        thread_unlock(thread);
        !          2479:                        splx(s);
        !          2480:                        thread_deallocate(thread);
        !          2481:            }
        !          2482:                
        !          2483:        } while (restart_needed);
        !          2484: }
        !          2485:                
        !          2486: /*
        !          2487:  *     Just in case someone doesn't use the macro
        !          2488:  */
        !          2489: #undef thread_wakeup
        !          2490: void
        !          2491: thread_wakeup(
        !          2492:        event_t         x);
        !          2493: 
        !          2494: void
        !          2495: thread_wakeup(
        !          2496:        event_t         x)
        !          2497: {
        !          2498:        thread_wakeup_with_result(x, THREAD_AWAKENED);
        !          2499: }
        !          2500: 
        !          2501: boolean_t
        !          2502: thread_runnable(
        !          2503:        thread_t                thread)
        !          2504: {
        !          2505:        sched_policy_t  *policy;
        !          2506: 
        !          2507:        /* Ask sched policy if thread is runnable */
        !          2508:        policy = policy_id_to_sched_policy(thread->policy);
        !          2509: 
        !          2510:        return ((policy != SCHED_POLICY_NULL)?
        !          2511:                                policy->sp_ops.sp_thread_runnable(policy, thread) : FALSE);
        !          2512: }
        !          2513: 
        !          2514: void
        !          2515: dump_processor_set(
        !          2516:        processor_set_t ps)
        !          2517: {
        !          2518:     printf("processor_set: %08x\n",ps);
        !          2519:     printf("idle_queue: %08x %08x, idle_count:      0x%x\n",
        !          2520:        ps->idle_queue.next,ps->idle_queue.prev,ps->idle_count);
        !          2521:     printf("processors: %08x %08x, processor_count: 0x%x, empty: %x\n",
        !          2522:        ps->processors.next,ps->processors.prev,ps->processor_count);
        !          2523:     printf("tasks:      %08x %08x, task_count:      0x%x\n",
        !          2524:        ps->tasks.next,ps->tasks.prev,ps->task_count);
        !          2525:     printf("threads:    %08x %08x, thread_count:    0x%x\n",
        !          2526:        ps->threads.next,ps->threads.prev,ps->thread_count);
        !          2527:     printf("ref_count: 0x%x, all_psets: %08x %08x, active: %x\n",
        !          2528:        ps->ref_count, ps->all_psets.next,ps->all_psets.prev,ps->active);
        !          2529:     printf("pset_self: %08x, pset_name_self: %08x\n",ps->pset_self, ps->pset_name_self);
        !          2530:     printf("max_priority: 0x%x, policies: 0x%x, set_quantum: 0x%x\n",
        !          2531:        ps->max_priority, ps->policies, ps->set_quantum);
        !          2532: }
        !          2533: 
        !          2534: #define processor_state(s) (((s)>PROCESSOR_SHUTDOWN)?"*unknown*":states[s])
        !          2535: 
        !          2536: void
        !          2537: dump_processor(
        !          2538:        processor_t     p)
        !          2539: {
        !          2540:     char *states[]={"OFF_LINE","RUNNING","IDLE","DISPATCHING",
        !          2541:                   "ASSIGN","SHUTDOWN"};
        !          2542: 
        !          2543:     printf("processor: %08x\n",p);
        !          2544:     printf("processor_queue: %08x %08x\n",
        !          2545:        p->processor_queue.next,p->processor_queue.prev);
        !          2546:     printf("state: %8s, next_thread: %08x, idle_thread: %08x\n",
        !          2547:        processor_state(p->state), p->next_thread, p->idle_thread);
        !          2548:     printf("quantum: %u, first_quantum: %x, last_quantum: %u\n",
        !          2549:        p->quantum, p->first_quantum, p->last_quantum);
        !          2550:     printf("processor_set: %08x, processor_set_next: %08x\n",
        !          2551:        p->processor_set, p->processor_set_next);
        !          2552:     printf("processors: %08x %08x\n", p->processors.next,p->processors.prev);
        !          2553:     printf("processor_self: %08x, slot_num: 0x%x\n", p->processor_self, p->slot_num);
        !          2554: }
        !          2555: 
        !          2556: void
        !          2557: dump_run_queue_struct(
        !          2558:        run_queue_t     rq)
        !          2559: {
        !          2560:     char dump_buf[80];
        !          2561:     int i;
        !          2562: 
        !          2563:     for( i=0; i < NRQS; ) {
        !          2564:         int j;
        !          2565: 
        !          2566:        printf("%6s",(i==0)?"runq:":"");
        !          2567:        for( j=0; (j<8) && (i < NRQS); j++,i++ ) {
        !          2568:            if( rq->runq[i].next == &rq->runq[i] )
        !          2569:                printf( " --------");
        !          2570:            else
        !          2571:                printf(" %08x",rq->runq[i].next);
        !          2572:        }
        !          2573:        printf("\n");
        !          2574:     }
        !          2575:     for( i=0; i < NRQBM; ) {
        !          2576:         register unsigned int mask;
        !          2577:        char *d=dump_buf;
        !          2578: 
        !          2579:        mask = ~0;
        !          2580:        mask ^= (mask>>1);
        !          2581: 
        !          2582:        do {
        !          2583:            *d++ = ((rq->bitmap[i]&mask)?'r':'e');
        !          2584:            mask >>=1;
        !          2585:        } while( mask );
        !          2586:        *d = '\0';
        !          2587:        printf("%8s%s\n",((i==0)?"bitmap:":""),dump_buf);
        !          2588:        i++;
        !          2589:     }  
        !          2590:     printf("highq: 0x%x, count: %u\n", rq->highq, rq->count);
        !          2591: }
        !          2592:  
        !          2593: void
        !          2594: dump_run_queues(
        !          2595:        run_queue_t     runq)
        !          2596: {
        !          2597:        register queue_t        q1;
        !          2598:        register int            i;
        !          2599:        register queue_entry_t  e;
        !          2600: 
        !          2601:        q1 = runq->runq;
        !          2602:        for (i = 0; i < NRQS; i++) {
        !          2603:            if (q1->next != q1) {
        !          2604:                int t_cnt;
        !          2605: 
        !          2606:                printf("[%u]",i);
        !          2607:                for (t_cnt=0, e = q1->next; e != q1; e = e->next) {
        !          2608:                    printf("\t0x%08x",e);
        !          2609:                    if( (t_cnt = ++t_cnt%4) == 0 )
        !          2610:                        printf("\n");
        !          2611:                }
        !          2612:                if( t_cnt )
        !          2613:                        printf("\n");
        !          2614:            }
        !          2615:            /* else
        !          2616:                printf("[%u]\t<empty>\n",i);
        !          2617:             */
        !          2618:            q1++;
        !          2619:        }
        !          2620: }
        !          2621: 
        !          2622: #if    DEBUG
        !          2623: 
        !          2624: void
        !          2625: checkrq(
        !          2626:        run_queue_t     rq,
        !          2627:        char            *msg)
        !          2628: {
        !          2629:        register queue_t        q1;
        !          2630:        register int            i, j;
        !          2631:        register queue_entry_t  e;
        !          2632:        register int            highq;
        !          2633: 
        !          2634:        highq = NRQS;
        !          2635:        j = 0;
        !          2636:        q1 = rq->runq;
        !          2637:        for (i = MAXPRI; i >= 0; i--) {
        !          2638:            if (q1->next == q1) {
        !          2639:                if (q1->prev != q1) {
        !          2640:                    panic("checkrq: empty at %s", msg);
        !          2641:                }
        !          2642:            }
        !          2643:            else {
        !          2644:                if (highq == -1)
        !          2645:                    highq = i;
        !          2646:                
        !          2647:                for (e = q1->next; e != q1; e = e->next) {
        !          2648:                    j++;
        !          2649:                    if (e->next->prev != e)
        !          2650:                        panic("checkrq-2 at %s", msg);
        !          2651:                    if (e->prev->next != e)
        !          2652:                        panic("checkrq-3 at %s", msg);
        !          2653:                }
        !          2654:            }
        !          2655:            q1++;
        !          2656:        }
        !          2657:        if (j != rq->count)
        !          2658:            panic("checkrq: count wrong at %s", msg);
        !          2659:        if (rq->count != 0 && highq > rq->highq)
        !          2660:            panic("checkrq: highq wrong at %s", msg);
        !          2661: }
        !          2662: 
        !          2663: void
        !          2664: thread_check(
        !          2665:        register thread_t       th,
        !          2666:        register run_queue_t    rq)
        !          2667: {
        !          2668:        register unsigned int   whichq;
        !          2669: 
        !          2670:        whichq = th->sched_pri;
        !          2671:        if (whichq < MINPRI) {
        !          2672:                printf("thread_check: priority too high\n");
        !          2673:                whichq = MINPRI;
        !          2674:        }
        !          2675:        if ((th->links.next == &rq->runq[whichq]) &&
        !          2676:                (rq->runq[whichq].prev != (queue_entry_t)th))
        !          2677:                        panic("thread_check");
        !          2678: }
        !          2679: 
        !          2680: #endif /* DEBUG */
        !          2681: 
        !          2682: #if    MACH_KDB
        !          2683: #include <ddb/db_output.h>
        !          2684: #define        printf          kdbprintf
        !          2685: extern int             db_indent;
        !          2686: void                   db_sched(void);
        !          2687: 
        !          2688: void
        !          2689: db_sched(void)
        !          2690: {
        !          2691:        iprintf("Scheduling Statistics:\n");
        !          2692:        db_indent += 2;
        !          2693:        iprintf("Thread invocations:  csw %d same %d\n",
        !          2694:                c_thread_invoke_csw, c_thread_invoke_same);
        !          2695: #if    MACH_COUNTERS
        !          2696:        iprintf("Thread block:  calls %d\n",
        !          2697:                c_thread_block_calls);
        !          2698:        iprintf("Idle thread:\n\thandoff %d block %d no_dispatch %d\n",
        !          2699:                c_idle_thread_handoff,
        !          2700:                c_idle_thread_block, no_dispatch_count);
        !          2701:        iprintf("Sched thread blocks:  %d\n", c_sched_thread_block);
        !          2702: #endif /* MACH_COUNTERS */
        !          2703:        db_indent -= 2;
        !          2704: }
        !          2705: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

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