Annotation of OSKit-Mach/kern/sched_prim.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1993-1987 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  *
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  *
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  *
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  *
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  *
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /*
        !            27:  *     File:   sched_prim.c
        !            28:  *     Author: Avadis Tevanian, Jr.
        !            29:  *     Date:   1986
        !            30:  *
        !            31:  *     Scheduling primitives
        !            32:  *
        !            33:  */
        !            34: 
        !            35: #include <cpus.h>
        !            36: #include <simple_clock.h>
        !            37: #include <mach_fixpri.h>
        !            38: #include <mach_host.h>
        !            39: #include <hw_footprint.h>
        !            40: #include <fast_tas.h>
        !            41: #include <power_save.h>
        !            42: 
        !            43: #include <mach/machine.h>
        !            44: #include <kern/ast.h>
        !            45: #include <kern/counters.h>
        !            46: #include <kern/cpu_number.h>
        !            47: #include <kern/lock.h>
        !            48: #include <kern/macro_help.h>
        !            49: #include <kern/processor.h>
        !            50: #include <kern/queue.h>
        !            51: #include <kern/sched.h>
        !            52: #include <kern/sched_prim.h>
        !            53: #include <kern/syscall_subr.h>
        !            54: #include <kern/thread.h>
        !            55: #include <kern/thread_swap.h>
        !            56: #include <kern/time_out.h>
        !            57: #include <vm/pmap.h>
        !            58: #include <vm/vm_kern.h>
        !            59: #include <vm/vm_map.h>
        !            60: #include <machine/machspl.h>   /* For def'n of splsched() */
        !            61: 
        !            62: #if    MACH_FIXPRI
        !            63: #include <mach/policy.h>
        !            64: #endif /* MACH_FIXPRI */
        !            65: 
        !            66: 
        !            67: extern int hz;
        !            68: 
        !            69: int            min_quantum;    /* defines max context switch rate */
        !            70: 
        !            71: unsigned       sched_tick;
        !            72: 
        !            73: #if    SIMPLE_CLOCK
        !            74: int            sched_usec;
        !            75: #endif /* SIMPLE_CLOCK */
        !            76: 
        !            77: thread_t       sched_thread_id;
        !            78: 
        !            79: void recompute_priorities(void);       /* forward */
        !            80: void update_priority(thread_t);
        !            81: void set_pri(thread_t, int, boolean_t);
        !            82: void do_thread_scan(void);
        !            83: 
        !            84: thread_t       choose_pset_thread();
        !            85: 
        !            86: timer_elt_data_t recompute_priorities_timer;
        !            87: 
        !            88: #if    DEBUG
        !            89: void checkrq(run_queue_t, char *);
        !            90: void thread_check(thread_t, run_queue_t);
        !            91: #endif
        !            92: 
        !            93: /*
        !            94:  *     State machine
        !            95:  *
        !            96:  * states are combinations of:
        !            97:  *  R  running
        !            98:  *  W  waiting (or on wait queue)
        !            99:  *  S  suspended (or will suspend)
        !           100:  *  N  non-interruptible
        !           101:  *
        !           102:  * init        action
        !           103:  *     assert_wait thread_block    clear_wait  suspend resume
        !           104:  *
        !           105:  * R   RW,  RWN    R;   setrun     -           RS      -
        !           106:  * RS  RWS, RWNS   S;  wake_active -           -       R
        !           107:  * RN  RWN         RN;  setrun     -           RNS     -
        !           108:  * RNS RWNS        RNS; setrun     -           -       RN
        !           109:  *
        !           110:  * RW              W               R           RWS     -
        !           111:  * RWN             WN              RN          RWNS    -
        !           112:  * RWS             WS; wake_active RS          -       RW
        !           113:  * RWNS                    WNS             RNS         -       RWN
        !           114:  *
        !           115:  * W                               R;   setrun WS      -
        !           116:  * WN                              RN;  setrun WNS     -
        !           117:  * WNS                             RNS; setrun -       WN
        !           118:  *
        !           119:  * S                               -           -       R
        !           120:  * WS                              S           -       W
        !           121:  *
        !           122:  */
        !           123: 
        !           124: /*
        !           125:  *     Waiting protocols and implementation:
        !           126:  *
        !           127:  *     Each thread may be waiting for exactly one event; this event
        !           128:  *     is set using assert_wait().  That thread may be awakened either
        !           129:  *     by performing a thread_wakeup_prim() on its event,
        !           130:  *     or by directly waking that thread up with clear_wait().
        !           131:  *
        !           132:  *     The implementation of wait events uses a hash table.  Each
        !           133:  *     bucket is queue of threads having the same hash function
        !           134:  *     value; the chain for the queue (linked list) is the run queue
        !           135:  *     field.  [It is not possible to be waiting and runnable at the
        !           136:  *     same time.]
        !           137:  *
        !           138:  *     Locks on both the thread and on the hash buckets govern the
        !           139:  *     wait event field and the queue chain field.  Because wakeup
        !           140:  *     operations only have the event as an argument, the event hash
        !           141:  *     bucket must be locked before any thread.
        !           142:  *
        !           143:  *     Scheduling operations may also occur at interrupt level; therefore,
        !           144:  *     interrupts below splsched() must be prevented when holding
        !           145:  *     thread or hash bucket locks.
        !           146:  *
        !           147:  *     The wait event hash table declarations are as follows:
        !           148:  */
        !           149: 
        !           150: #define NUMQUEUES      59
        !           151: 
        !           152: queue_head_t           wait_queue[NUMQUEUES];
        !           153: decl_simple_lock_data(,        wait_lock[NUMQUEUES])
        !           154: 
        !           155: #include <oskit/types.h>
        !           156: 
        !           157: /* NOTE: we want a small positive integer out of this */
        !           158: static inline int
        !           159: wait_hash(event_t arg)
        !           160: {
        !           161:   oskit_sreg_t event = (oskit_sreg_t)arg;
        !           162:   return ((event < 0 ? ~event : event) % NUMQUEUES);
        !           163: }
        !           164: 
        !           165: void wait_queue_init(void)
        !           166: {
        !           167:        register int i;
        !           168: 
        !           169:        for (i = 0; i < NUMQUEUES; i++) {
        !           170:                queue_init(&wait_queue[i]);
        !           171:                simple_lock_init(&wait_lock[i]);
        !           172:        }
        !           173: }
        !           174: 
        !           175: void sched_init(void)
        !           176: {
        !           177:        recompute_priorities_timer.fcn = (int (*)())recompute_priorities;
        !           178:        recompute_priorities_timer.param = (char *)0;
        !           179: 
        !           180:        min_quantum = hz / 10;          /* context switch 10 times/second */
        !           181:        wait_queue_init();
        !           182:        pset_sys_bootstrap();           /* initialize processer mgmt. */
        !           183:        queue_init(&action_queue);
        !           184:        simple_lock_init(&action_lock);
        !           185:        sched_tick = 0;
        !           186: #if    SIMPLE_CLOCK
        !           187:        sched_usec = 0;
        !           188: #endif /* SIMPLE_CLOCK */
        !           189:        ast_init();
        !           190: }
        !           191: 
        !           192: /*
        !           193:  *     Thread timeout routine, called when timer expires.
        !           194:  *     Called at splsoftclock.
        !           195:  */
        !           196: void thread_timeout(
        !           197:        thread_t thread)
        !           198: {
        !           199:        assert(thread->timer.set == TELT_UNSET);
        !           200: 
        !           201:        clear_wait(thread, THREAD_TIMED_OUT, FALSE);
        !           202: }
        !           203: 
        !           204: /*
        !           205:  *     thread_set_timeout:
        !           206:  *
        !           207:  *     Set a timer for the current thread, if the thread
        !           208:  *     is ready to wait.  Must be called between assert_wait()
        !           209:  *     and thread_block().
        !           210:  */
        !           211: 
        !           212: void thread_set_timeout(
        !           213:        int     t)      /* timeout interval in ticks */
        !           214: {
        !           215:        register thread_t       thread = current_thread();
        !           216:        register spl_t s;
        !           217: 
        !           218:        s = splsched();
        !           219:        thread_lock(thread);
        !           220:        if ((thread->state & TH_WAIT) != 0) {
        !           221:                set_timeout(&thread->timer, t);
        !           222:        }
        !           223:        thread_unlock(thread);
        !           224:        splx(s);
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * Set up thread timeout element when thread is created.
        !           229:  */
        !           230: void thread_timeout_setup(
        !           231:        register thread_t       thread)
        !           232: {
        !           233:        thread->timer.fcn = (int (*)())thread_timeout;
        !           234:        thread->timer.param = (char *)thread;
        !           235:        thread->depress_timer.fcn = (int (*)())thread_depress_timeout;
        !           236:        thread->depress_timer.param = (char *)thread;
        !           237: }
        !           238: 
        !           239: /*
        !           240:  *     assert_wait:
        !           241:  *
        !           242:  *     Assert that the current thread is about to go to
        !           243:  *     sleep until the specified event occurs.
        !           244:  */
        !           245: void assert_wait(
        !           246:        event_t         event,
        !           247:        boolean_t       interruptible)
        !           248: {
        !           249:        register queue_t        q;
        !           250:        register int            index;
        !           251:        register thread_t       thread;
        !           252: #if    MACH_SLOCKS
        !           253:        register simple_lock_t  lock;
        !           254: #endif /* MACH_SLOCKS */
        !           255:        spl_t                   s;
        !           256: 
        !           257:        thread = current_thread();
        !           258:        if (thread->wait_event != 0) {
        !           259:                panic("assert_wait: already asserted event %#x\n",
        !           260:                      thread->wait_event);
        !           261:        }
        !           262:        s = splsched();
        !           263:        if (event != 0) {
        !           264:                index = wait_hash(event);
        !           265:                q = &wait_queue[index];
        !           266: #if    MACH_SLOCKS
        !           267:                lock = &wait_lock[index];
        !           268: #endif /* MACH_SLOCKS */
        !           269:                simple_lock(lock);
        !           270:                thread_lock(thread);
        !           271:                enqueue_tail(q, (queue_entry_t) thread);
        !           272:                thread->wait_event = event;
        !           273:                if (interruptible)
        !           274:                        thread->state |= TH_WAIT;
        !           275:                else
        !           276:                        thread->state |= TH_WAIT | TH_UNINT;
        !           277:                thread_unlock(thread);
        !           278:                simple_unlock(lock);
        !           279:        }
        !           280:        else {
        !           281:                thread_lock(thread);
        !           282:                if (interruptible)
        !           283:                        thread->state |= TH_WAIT;
        !           284:                else
        !           285:                        thread->state |= TH_WAIT | TH_UNINT;
        !           286:                thread_unlock(thread);
        !           287:        }
        !           288:        splx(s);
        !           289: }
        !           290: 
        !           291: /*
        !           292:  *     clear_wait:
        !           293:  *
        !           294:  *     Clear the wait condition for the specified thread.  Start the thread
        !           295:  *     executing if that is appropriate.
        !           296:  *
        !           297:  *     parameters:
        !           298:  *       thread                thread to awaken
        !           299:  *       result                Wakeup result the thread should see
        !           300:  *       interrupt_only        Don't wake up the thread if it isn't
        !           301:  *                             interruptible.
        !           302:  */
        !           303: void clear_wait(
        !           304:        register thread_t       thread,
        !           305:        int                     result,
        !           306:        boolean_t               interrupt_only)
        !           307: {
        !           308:        register int            index;
        !           309:        register queue_t        q;
        !           310: #if    MACH_SLOCKS
        !           311:        register simple_lock_t  lock;
        !           312: #endif /* MACH_SLOCKS */
        !           313:        register event_t        event;
        !           314:        spl_t                   s;
        !           315: 
        !           316:        s = splsched();
        !           317:        thread_lock(thread);
        !           318:        if (interrupt_only && (thread->state & TH_UNINT)) {
        !           319:                /*
        !           320:                 *      can`t interrupt thread
        !           321:                 */
        !           322:                thread_unlock(thread);
        !           323:                splx(s);
        !           324:                return;
        !           325:        }
        !           326: 
        !           327:        event = thread->wait_event;
        !           328:        if (event != 0) {
        !           329:                thread_unlock(thread);
        !           330:                index = wait_hash(event);
        !           331:                q = &wait_queue[index];
        !           332: #if    MACH_SLOCKS
        !           333:                lock = &wait_lock[index];
        !           334: #endif /* MACH_SLOCKS */
        !           335:                simple_lock(lock);
        !           336:                /*
        !           337:                 *      If the thread is still waiting on that event,
        !           338:                 *      then remove it from the list.  If it is waiting
        !           339:                 *      on a different event, or no event at all, then
        !           340:                 *      someone else did our job for us.
        !           341:                 */
        !           342:                thread_lock(thread);
        !           343:                if (thread->wait_event == event) {
        !           344:                        remqueue(q, (queue_entry_t)thread);
        !           345:                        thread->wait_event = 0;
        !           346:                        event = 0;              /* cause to run below */
        !           347:                }
        !           348:                simple_unlock(lock);
        !           349:        }
        !           350:        if (event == 0) {
        !           351:                register int    state = thread->state;
        !           352: 
        !           353:                reset_timeout_check(&thread->timer);
        !           354: 
        !           355:                switch (state & TH_SCHED_STATE) {
        !           356:                    case          TH_WAIT | TH_SUSP | TH_UNINT:
        !           357:                    case          TH_WAIT           | TH_UNINT:
        !           358:                    case          TH_WAIT:
        !           359:                        /*
        !           360:                         *      Sleeping and not suspendable - put
        !           361:                         *      on run queue.
        !           362:                         */
        !           363:                        thread->state = (state &~ TH_WAIT) | TH_RUN;
        !           364:                        thread->wait_result = result;
        !           365:                        thread_setrun(thread, TRUE);
        !           366:                        break;
        !           367: 
        !           368:                    case          TH_WAIT | TH_SUSP:
        !           369:                    case TH_RUN | TH_WAIT:
        !           370:                    case TH_RUN | TH_WAIT | TH_SUSP:
        !           371:                    case TH_RUN | TH_WAIT           | TH_UNINT:
        !           372:                    case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
        !           373:                        /*
        !           374:                         *      Either already running, or suspended.
        !           375:                         */
        !           376:                        thread->state = state &~ TH_WAIT;
        !           377:                        thread->wait_result = result;
        !           378:                        break;
        !           379: 
        !           380:                    default:
        !           381:                        /*
        !           382:                         *      Not waiting.
        !           383:                         */
        !           384:                        break;
        !           385:                }
        !           386:        }
        !           387:        thread_unlock(thread);
        !           388:        splx(s);
        !           389: }
        !           390: 
        !           391: static inline void __attribute__((noreturn))
        !           392: state_panic(thread_t thread, const char *caller)
        !           393: {
        !           394:   panic ("%s: thread %x has unexpected state %x",
        !           395:         caller, thread, thread->state);
        !           396: }
        !           397: 
        !           398: /*
        !           399:  *     thread_wakeup_prim:
        !           400:  *
        !           401:  *     Common routine for thread_wakeup, thread_wakeup_with_result,
        !           402:  *     and thread_wakeup_one.
        !           403:  *
        !           404:  */
        !           405: void thread_wakeup_prim(
        !           406:        event_t         event,
        !           407:        boolean_t       one_thread,
        !           408:        int             result)
        !           409: {
        !           410:        register queue_t        q;
        !           411:        register int            index;
        !           412:        register thread_t       thread, next_th;
        !           413: #if    MACH_SLOCKS
        !           414:        register simple_lock_t  lock;
        !           415: #endif  /* MACH_SLOCKS */
        !           416:        spl_t                   s;
        !           417:        register int            state;
        !           418: 
        !           419:        index = wait_hash(event);
        !           420:        q = &wait_queue[index];
        !           421:        s = splsched();
        !           422: #if    MACH_SLOCKS
        !           423:        lock = &wait_lock[index];
        !           424: #endif /* MACH_SLOCKS */
        !           425:        simple_lock(lock);
        !           426:        thread = (thread_t) queue_first(q);
        !           427:        while (!queue_end(q, (queue_entry_t)thread)) {
        !           428:                next_th = (thread_t) queue_next((queue_t) thread);
        !           429: 
        !           430:                if (thread->wait_event == event) {
        !           431:                        thread_lock(thread);
        !           432:                        remqueue(q, (queue_entry_t) thread);
        !           433:                        thread->wait_event = 0;
        !           434:                        reset_timeout_check(&thread->timer);
        !           435: 
        !           436:                        state = thread->state;
        !           437:                        switch (state & TH_SCHED_STATE) {
        !           438: 
        !           439:                            case          TH_WAIT | TH_SUSP | TH_UNINT:
        !           440:                            case          TH_WAIT           | TH_UNINT:
        !           441:                            case          TH_WAIT:
        !           442:                                /*
        !           443:                                 *      Sleeping and not suspendable - put
        !           444:                                 *      on run queue.
        !           445:                                 */
        !           446:                                thread->state = (state &~ TH_WAIT) | TH_RUN;
        !           447:                                thread->wait_result = result;
        !           448:                                thread_setrun(thread, TRUE);
        !           449:                                break;
        !           450: 
        !           451:                            case          TH_WAIT | TH_SUSP:
        !           452:                            case TH_RUN | TH_WAIT:
        !           453:                            case TH_RUN | TH_WAIT | TH_SUSP:
        !           454:                            case TH_RUN | TH_WAIT           | TH_UNINT:
        !           455:                            case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
        !           456:                                /*
        !           457:                                 *      Either already running, or suspended.
        !           458:                                 */
        !           459:                                thread->state = state &~ TH_WAIT;
        !           460:                                thread->wait_result = result;
        !           461:                                break;
        !           462: 
        !           463:                            default:
        !           464:                                state_panic(thread, "thread_wakeup");
        !           465:                                break;
        !           466:                        }
        !           467:                        thread_unlock(thread);
        !           468:                        if (one_thread)
        !           469:                                break;
        !           470:                }
        !           471:                thread = next_th;
        !           472:        }
        !           473:        simple_unlock(lock);
        !           474:        splx(s);
        !           475: }
        !           476: 
        !           477: /*
        !           478:  *     thread_sleep:
        !           479:  *
        !           480:  *     Cause the current thread to wait until the specified event
        !           481:  *     occurs.  The specified lock is unlocked before releasing
        !           482:  *     the cpu.  (This is a convenient way to sleep without manually
        !           483:  *     calling assert_wait).
        !           484:  */
        !           485: void thread_sleep(
        !           486:        event_t         event,
        !           487:        simple_lock_t   lock,
        !           488:        boolean_t       interruptible)
        !           489: {
        !           490:        assert_wait(event, interruptible);      /* assert event */
        !           491:        simple_unlock(lock);                    /* release the lock */
        !           492:        thread_block((void (*)()) 0);           /* block ourselves */
        !           493: }
        !           494: 
        !           495: /*
        !           496:  *     thread_bind:
        !           497:  *
        !           498:  *     Force a thread to execute on the specified processor.
        !           499:  *     If the thread is currently executing, it may wait until its
        !           500:  *     time slice is up before switching onto the specified processor.
        !           501:  *
        !           502:  *     A processor of PROCESSOR_NULL causes the thread to be unbound.
        !           503:  *     xxx - DO NOT export this to users.
        !           504:  */
        !           505: void thread_bind(
        !           506:        register thread_t       thread,
        !           507:        processor_t             processor)
        !           508: {
        !           509:        spl_t           s;
        !           510: 
        !           511:        s = splsched();
        !           512:        thread_lock(thread);
        !           513:        thread->bound_processor = processor;
        !           514:        thread_unlock(thread);
        !           515:        (void) splx(s);
        !           516: }
        !           517: 
        !           518: /*
        !           519:  *     Select a thread for this processor (the current processor) to run.
        !           520:  *     May select the current thread.
        !           521:  *     Assumes splsched.
        !           522:  */
        !           523: 
        !           524: thread_t thread_select(
        !           525:        register processor_t myprocessor)
        !           526: {
        !           527:        register thread_t thread;
        !           528: 
        !           529:        myprocessor->first_quantum = TRUE;
        !           530:        /*
        !           531:         *      Check for obvious simple case; local runq is
        !           532:         *      empty and global runq has entry at hint.
        !           533:         */
        !           534:        if (myprocessor->runq.count > 0) {
        !           535:                thread = choose_thread(myprocessor);
        !           536:                myprocessor->quantum = min_quantum;
        !           537:        }
        !           538:        else {
        !           539:                register processor_set_t pset;
        !           540: 
        !           541: #if    MACH_HOST
        !           542:                pset = myprocessor->processor_set;
        !           543: #else  /* MACH_HOST */
        !           544:                pset = &default_pset;
        !           545: #endif /* MACH_HOST */
        !           546:                simple_lock(&pset->runq.lock);
        !           547: #if    DEBUG
        !           548:                checkrq(&pset->runq, "thread_select");
        !           549: #endif /* DEBUG */
        !           550:                if (pset->runq.count == 0) {
        !           551:                        /*
        !           552:                         *      Nothing else runnable.  Return if this
        !           553:                         *      thread is still runnable on this processor.
        !           554:                         *      Check for priority update if required.
        !           555:                         */
        !           556:                        thread = current_thread();
        !           557:                        if ((thread->state == TH_RUN) &&
        !           558: #if    MACH_HOST
        !           559:                            (thread->processor_set == pset) &&
        !           560: #endif /* MACH_HOST */
        !           561:                            ((thread->bound_processor == PROCESSOR_NULL) ||
        !           562:                             (thread->bound_processor == myprocessor))) {
        !           563: 
        !           564:                                simple_unlock(&pset->runq.lock);
        !           565:                                thread_lock(thread);
        !           566:                                if (thread->sched_stamp != sched_tick)
        !           567:                                    update_priority(thread);
        !           568:                                thread_unlock(thread);
        !           569:                        }
        !           570:                        else {
        !           571:                                thread = choose_pset_thread(myprocessor, pset);
        !           572:                        }
        !           573:                }
        !           574:                else {
        !           575:                        register queue_t        q;
        !           576: 
        !           577:                        /*
        !           578:                         *      If there is a thread at hint, grab it,
        !           579:                         *      else call choose_pset_thread.
        !           580:                         */
        !           581:                        q = pset->runq.runq + pset->runq.low;
        !           582: 
        !           583:                        if (queue_empty(q)) {
        !           584:                                pset->runq.low++;
        !           585:                                thread = choose_pset_thread(myprocessor, pset);
        !           586:                        }
        !           587:                        else {
        !           588:                                thread = (thread_t) dequeue_head(q);
        !           589:                                thread->runq = RUN_QUEUE_NULL;
        !           590:                                pset->runq.count--;
        !           591: #if    MACH_FIXPRI
        !           592:                                /*
        !           593:                                 *      Cannot lazy evaluate pset->runq.low for
        !           594:                                 *      fixed priority policy
        !           595:                                 */
        !           596:                                if ((pset->runq.count > 0) &&
        !           597:                                    (pset->policies & POLICY_FIXEDPRI)) {
        !           598:                                            while (queue_empty(q)) {
        !           599:                                                pset->runq.low++;
        !           600:                                                q++;
        !           601:                                            }
        !           602:                                }
        !           603: #endif /* MACH_FIXPRI */
        !           604: #if    DEBUG
        !           605:                                checkrq(&pset->runq, "thread_select: after");
        !           606: #endif /* DEBUG */
        !           607:                                simple_unlock(&pset->runq.lock);
        !           608:                        }
        !           609:                }
        !           610: 
        !           611: #if    MACH_FIXPRI
        !           612:                if (thread->policy == POLICY_TIMESHARE) {
        !           613: #endif /* MACH_FIXPRI */
        !           614:                        myprocessor->quantum = pset->set_quantum;
        !           615: #if    MACH_FIXPRI
        !           616:                }
        !           617:                else {
        !           618:                        /*
        !           619:                         *      POLICY_FIXEDPRI
        !           620:                         */
        !           621:                        myprocessor->quantum = thread->sched_data;
        !           622:                }
        !           623: #endif /* MACH_FIXPRI */
        !           624:        }
        !           625: 
        !           626:        return thread;
        !           627: }
        !           628: 
        !           629: /*
        !           630:  *     Stop running the current thread and start running the new thread.
        !           631:  *     If continuation is non-zero, and the current thread is blocked,
        !           632:  *     then it will resume by executing continuation on a new stack.
        !           633:  *     Returns TRUE if the hand-off succeeds.
        !           634:  *     Assumes splsched.
        !           635:  */
        !           636: 
        !           637: boolean_t thread_invoke(
        !           638:        register thread_t old_thread,
        !           639:        continuation_t    continuation,
        !           640:        register thread_t new_thread)
        !           641: {
        !           642:        /*
        !           643:         *      Check for invoking the same thread.
        !           644:         */
        !           645:        if (old_thread == new_thread) {
        !           646:            /*
        !           647:             *  Mark thread interruptible.
        !           648:             *  Run continuation if there is one.
        !           649:             */
        !           650:            thread_lock(new_thread);
        !           651:            new_thread->state &= ~TH_UNINT;
        !           652:            thread_unlock(new_thread);
        !           653: 
        !           654:            if (continuation != (void (*)()) 0) {
        !           655:                (void) spl0();
        !           656:                call_continuation(continuation);
        !           657:                /*NOTREACHED*/
        !           658:            }
        !           659:            return TRUE;
        !           660:        }
        !           661: 
        !           662:        /*
        !           663:         *      Check for stack-handoff.
        !           664:         */
        !           665:        thread_lock(new_thread);
        !           666:        if ((old_thread->stack_privilege != current_stack()) &&
        !           667:            (continuation != (void (*)()) 0))
        !           668:        {
        !           669:            switch (new_thread->state & TH_SWAP_STATE) {
        !           670:                case TH_SWAPPED:
        !           671: 
        !           672:                    new_thread->state &= ~(TH_SWAPPED | TH_UNINT);
        !           673:                    thread_unlock(new_thread);
        !           674: 
        !           675: #if    NCPUS > 1
        !           676:                    new_thread->last_processor = current_processor();
        !           677: #endif /* NCPUS > 1 */
        !           678: 
        !           679:                    /*
        !           680:                     *  Set up ast context of new thread and
        !           681:                     *  switch to its timer.
        !           682:                     */
        !           683:                    ast_context(new_thread, cpu_number());
        !           684:                    timer_switch(&new_thread->system_timer);
        !           685: 
        !           686:                    stack_handoff(old_thread, new_thread);
        !           687: 
        !           688:                    /*
        !           689:                     *  We can dispatch the old thread now.
        !           690:                     *  This is like thread_dispatch, except
        !           691:                     *  that the old thread is left swapped
        !           692:                     *  *without* freeing its stack.
        !           693:                     *  This path is also much more frequent
        !           694:                     *  than actual calls to thread_dispatch.
        !           695:                     */
        !           696: 
        !           697:                    thread_lock(old_thread);
        !           698:                    old_thread->swap_func = continuation;
        !           699: 
        !           700:                    switch (old_thread->state) {
        !           701:                        case TH_RUN           | TH_SUSP:
        !           702:                        case TH_RUN           | TH_SUSP | TH_HALTED:
        !           703:                        case TH_RUN | TH_WAIT | TH_SUSP:
        !           704:                            /*
        !           705:                             *  Suspend the thread
        !           706:                             */
        !           707:                            old_thread->state = (old_thread->state & ~TH_RUN)
        !           708:                                                | TH_SWAPPED;
        !           709:                            if (old_thread->wake_active) {
        !           710:                                old_thread->wake_active = FALSE;
        !           711:                                thread_unlock(old_thread);
        !           712:                                thread_wakeup((event_t)&old_thread->wake_active);
        !           713: 
        !           714:                                goto after_old_thread;
        !           715:                            }
        !           716:                            break;
        !           717: 
        !           718:                        case TH_RUN           | TH_SUSP | TH_UNINT:
        !           719:                        case TH_RUN                     | TH_UNINT:
        !           720:                        case TH_RUN:
        !           721:                            /*
        !           722:                             *  We can`t suspend the thread yet,
        !           723:                             *  or it`s still running.
        !           724:                             *  Put back on a run queue.
        !           725:                             */
        !           726:                            old_thread->state |= TH_SWAPPED;
        !           727:                            thread_setrun(old_thread, FALSE);
        !           728:                            break;
        !           729: 
        !           730:                        case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
        !           731:                        case TH_RUN | TH_WAIT           | TH_UNINT:
        !           732:                        case TH_RUN | TH_WAIT:
        !           733:                            /*
        !           734:                             *  Waiting, and not suspendable.
        !           735:                             */
        !           736:                            old_thread->state = (old_thread->state & ~TH_RUN)
        !           737:                                                | TH_SWAPPED;
        !           738:                            break;
        !           739: 
        !           740:                        case TH_RUN | TH_IDLE:
        !           741:                            /*
        !           742:                             *  Drop idle thread -- it is already in
        !           743:                             *  idle_thread_array.
        !           744:                             */
        !           745:                            old_thread->state = TH_RUN | TH_IDLE | TH_SWAPPED;
        !           746:                            break;
        !           747: 
        !           748:                        default:
        !           749:                            state_panic(old_thread, "thread_invoke");
        !           750:                    }
        !           751:                    thread_unlock(old_thread);
        !           752:                after_old_thread:
        !           753: 
        !           754:                    /*
        !           755:                     *  call_continuation calls the continuation
        !           756:                     *  after resetting the current stack pointer
        !           757:                     *  to recover stack space.  If we called
        !           758:                     *  the continuation directly, we would risk
        !           759:                     *  running out of stack.
        !           760:                     */
        !           761: 
        !           762:                    counter_always(c_thread_invoke_hits++);
        !           763:                    (void) spl0();
        !           764:                    call_continuation(new_thread->swap_func);
        !           765:                    /*NOTREACHED*/
        !           766:                    return TRUE; /* help for the compiler */
        !           767: 
        !           768:                case TH_SW_COMING_IN:
        !           769:                    /*
        !           770:                     *  Waiting for a stack
        !           771:                     */
        !           772:                    thread_swapin(new_thread);
        !           773:                    thread_unlock(new_thread);
        !           774:                    counter_always(c_thread_invoke_misses++);
        !           775:                    return FALSE;
        !           776: 
        !           777:                case 0:
        !           778:                    /*
        !           779:                     *  Already has a stack - can`t handoff.
        !           780:                     */
        !           781:                    break;
        !           782:            }
        !           783:        }
        !           784: 
        !           785:        else {
        !           786:            /*
        !           787:             *  Check that the thread is swapped-in.
        !           788:             */
        !           789:            if (new_thread->state & TH_SWAPPED) {
        !           790:                if ((new_thread->state & TH_SW_COMING_IN) ||
        !           791:                    !stack_alloc_try(new_thread, thread_continue))
        !           792:                {
        !           793:                    thread_swapin(new_thread);
        !           794:                    thread_unlock(new_thread);
        !           795:                    counter_always(c_thread_invoke_misses++);
        !           796:                    return FALSE;
        !           797:                }
        !           798:            }
        !           799:        }
        !           800: 
        !           801:        new_thread->state &= ~(TH_SWAPPED | TH_UNINT);
        !           802:        thread_unlock(new_thread);
        !           803: 
        !           804:        /*
        !           805:         *      Thread is now interruptible.
        !           806:         */
        !           807: #if    NCPUS > 1
        !           808:        new_thread->last_processor = current_processor();
        !           809: #endif /* NCPUS > 1 */
        !           810: 
        !           811:        /*
        !           812:         *      Set up ast context of new thread and switch to its timer.
        !           813:         */
        !           814:        ast_context(new_thread, cpu_number());
        !           815:        timer_switch(&new_thread->system_timer);
        !           816: 
        !           817:        /*
        !           818:         *      switch_context is machine-dependent.  It does the
        !           819:         *      machine-dependent components of a context-switch, like
        !           820:         *      changing address spaces.  It updates active_threads.
        !           821:         *      It returns only if a continuation is not supplied.
        !           822:         */
        !           823:        counter_always(c_thread_invoke_csw++);
        !           824:        old_thread = switch_context(old_thread, continuation, new_thread);
        !           825: 
        !           826:        /*
        !           827:         *      We're back.  Now old_thread is the thread that resumed
        !           828:         *      us, and we have to dispatch it.
        !           829:         */
        !           830:        thread_dispatch(old_thread);
        !           831: 
        !           832:        return TRUE;
        !           833: }
        !           834: 
        !           835: /*
        !           836:  *     thread_continue:
        !           837:  *
        !           838:  *     Called when the current thread is given a new stack.
        !           839:  *     Called at splsched.
        !           840:  */
        !           841: void thread_continue(
        !           842:        register thread_t old_thread)
        !           843: {
        !           844:        register continuation_t continuation = current_thread()->swap_func;
        !           845: 
        !           846:        /*
        !           847:         *      We must dispatch the old thread and then
        !           848:         *      call the current thread's continuation.
        !           849:         *      There might not be an old thread, if we are
        !           850:         *      the first thread to run on this processor.
        !           851:         */
        !           852: 
        !           853:        if (old_thread != THREAD_NULL)
        !           854:                thread_dispatch(old_thread);
        !           855:        (void) spl0();
        !           856:        (*continuation)();
        !           857:        /*NOTREACHED*/
        !           858: }
        !           859: 
        !           860: 
        !           861: /*
        !           862:  *     thread_block:
        !           863:  *
        !           864:  *     Block the current thread.  If the thread is runnable
        !           865:  *     then someone must have woken it up between its request
        !           866:  *     to sleep and now.  In this case, it goes back on a
        !           867:  *     run queue.
        !           868:  *
        !           869:  *     If a continuation is specified, then thread_block will
        !           870:  *     attempt to discard the thread's kernel stack.  When the
        !           871:  *     thread resumes, it will execute the continuation function
        !           872:  *     on a new kernel stack.
        !           873:  */
        !           874: 
        !           875: void thread_block(
        !           876:        continuation_t  continuation)
        !           877: {
        !           878:        register thread_t thread = current_thread();
        !           879:        register processor_t myprocessor = cpu_to_processor(cpu_number());
        !           880:        register thread_t new_thread;
        !           881:        spl_t s;
        !           882: 
        !           883:        check_simple_locks();
        !           884: 
        !           885:        s = splsched();
        !           886: 
        !           887: #if    FAST_TAS
        !           888:        {
        !           889:                extern void recover_ras();
        !           890: 
        !           891:                if (csw_needed(thread, myprocessor))
        !           892:                        recover_ras(thread);
        !           893:        }
        !           894: #endif /* FAST_TAS */
        !           895: 
        !           896:        ast_off(cpu_number(), AST_BLOCK);
        !           897: 
        !           898:        do
        !           899:                new_thread = thread_select(myprocessor);
        !           900:        while (!thread_invoke(thread, continuation, new_thread));
        !           901: 
        !           902:        splx(s);
        !           903: }
        !           904: 
        !           905: /*
        !           906:  *     thread_run:
        !           907:  *
        !           908:  *     Switch directly from the current thread to a specified
        !           909:  *     thread.  Both the current and new threads must be
        !           910:  *     runnable.
        !           911:  *
        !           912:  *     If a continuation is specified, then thread_block will
        !           913:  *     attempt to discard the current thread's kernel stack.  When the
        !           914:  *     thread resumes, it will execute the continuation function
        !           915:  *     on a new kernel stack.
        !           916:  */
        !           917: void thread_run(
        !           918:        continuation_t          continuation,
        !           919:        register thread_t       new_thread)
        !           920: {
        !           921:        register thread_t thread = current_thread();
        !           922:        register processor_t myprocessor = cpu_to_processor(cpu_number());
        !           923:        spl_t s;
        !           924: 
        !           925:        check_simple_locks();
        !           926: 
        !           927:        s = splsched();
        !           928: 
        !           929:        while (!thread_invoke(thread, continuation, new_thread))
        !           930:                new_thread = thread_select(myprocessor);
        !           931: 
        !           932:        splx(s);
        !           933: }
        !           934: 
        !           935: /*
        !           936:  *     Dispatches a running thread that is not on a runq.
        !           937:  *     Called at splsched.
        !           938:  */
        !           939: 
        !           940: void thread_dispatch(
        !           941:        register thread_t       thread)
        !           942: {
        !           943:        /*
        !           944:         *      If we are discarding the thread's stack, we must do it
        !           945:         *      before the thread has a chance to run.
        !           946:         */
        !           947: 
        !           948:        thread_lock(thread);
        !           949: 
        !           950:        if (thread->swap_func != (void (*)()) 0) {
        !           951:                assert((thread->state & TH_SWAP_STATE) == 0);
        !           952:                thread->state |= TH_SWAPPED;
        !           953:                stack_free(thread);
        !           954:        }
        !           955: 
        !           956:        switch (thread->state &~ TH_SWAP_STATE) {
        !           957:            case TH_RUN           | TH_SUSP:
        !           958:            case TH_RUN           | TH_SUSP | TH_HALTED:
        !           959:            case TH_RUN | TH_WAIT | TH_SUSP:
        !           960:                /*
        !           961:                 *      Suspend the thread
        !           962:                 */
        !           963:                thread->state &= ~TH_RUN;
        !           964:                if (thread->wake_active) {
        !           965:                    thread->wake_active = FALSE;
        !           966:                    thread_unlock(thread);
        !           967:                    thread_wakeup((event_t)&thread->wake_active);
        !           968:                    return;
        !           969:                }
        !           970:                break;
        !           971: 
        !           972:            case TH_RUN           | TH_SUSP | TH_UNINT:
        !           973:            case TH_RUN                     | TH_UNINT:
        !           974:            case TH_RUN:
        !           975:                /*
        !           976:                 *      No reason to stop.  Put back on a run queue.
        !           977:                 */
        !           978:                thread_setrun(thread, FALSE);
        !           979:                break;
        !           980: 
        !           981:            case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
        !           982:            case TH_RUN | TH_WAIT           | TH_UNINT:
        !           983:            case TH_RUN | TH_WAIT:
        !           984:                /*
        !           985:                 *      Waiting, and not suspended.
        !           986:                 */
        !           987:                thread->state &= ~TH_RUN;
        !           988:                break;
        !           989: 
        !           990:            case TH_RUN | TH_IDLE:
        !           991:                /*
        !           992:                 *      Drop idle thread -- it is already in
        !           993:                 *      idle_thread_array.
        !           994:                 */
        !           995:                break;
        !           996: 
        !           997:            default:
        !           998:                state_panic(thread, "thread_dispatch");
        !           999:        }
        !          1000:        thread_unlock(thread);
        !          1001: }
        !          1002: 
        !          1003: 
        !          1004: /*
        !          1005:  *     Define shifts for simulating (5/8)**n
        !          1006:  */
        !          1007: 
        !          1008: shift_data_t   wait_shift[32] = {
        !          1009:        {1,1},{1,3},{1,-3},{2,-7},{3,5},{3,-5},{4,-8},{5,7},
        !          1010:        {5,-7},{6,-10},{7,10},{7,-9},{8,-11},{9,12},{9,-11},{10,-13},
        !          1011:        {11,14},{11,-13},{12,-15},{13,17},{13,-15},{14,-17},{15,19},{16,18},
        !          1012:        {16,-19},{17,22},{18,20},{18,-20},{19,26},{20,22},{20,-22},{21,-27}};
        !          1013: 
        !          1014: /*
        !          1015:  *     do_priority_computation:
        !          1016:  *
        !          1017:  *     Calculate new priority for thread based on its base priority plus
        !          1018:  *     accumulated usage.  PRI_SHIFT and PRI_SHIFT_2 convert from
        !          1019:  *     usage to priorities.  SCHED_SHIFT converts for the scaling
        !          1020:  *     of the sched_usage field by SCHED_SCALE.  This scaling comes
        !          1021:  *     from the multiplication by sched_load (thread_timer_delta)
        !          1022:  *     in sched.h.  sched_load is calculated as a scaled overload
        !          1023:  *     factor in compute_mach_factor (mach_factor.c).
        !          1024:  */
        !          1025: 
        !          1026: #ifdef PRI_SHIFT_2
        !          1027: #if    PRI_SHIFT_2 > 0
        !          1028: #define do_priority_computation(th, pri)                               \
        !          1029:        MACRO_BEGIN                                                     \
        !          1030:        (pri) = (th)->priority  /* start with base priority */          \
        !          1031:            + ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT))          \
        !          1032:            + ((th)->sched_usage >> (PRI_SHIFT_2 + SCHED_SHIFT));       \
        !          1033:        if ((pri) > 31) (pri) = 31;                                     \
        !          1034:        MACRO_END
        !          1035: #else  /* PRI_SHIFT_2 */
        !          1036: #define do_priority_computation(th, pri)                               \
        !          1037:        MACRO_BEGIN                                                     \
        !          1038:        (pri) = (th)->priority  /* start with base priority */          \
        !          1039:            + ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT))          \
        !          1040:            - ((th)->sched_usage >> (SCHED_SHIFT - PRI_SHIFT_2));       \
        !          1041:        if ((pri) > 31) (pri) = 31;                                     \
        !          1042:        MACRO_END
        !          1043: #endif /* PRI_SHIFT_2 */
        !          1044: #else  /* defined(PRI_SHIFT_2) */
        !          1045: #define do_priority_computation(th, pri)                               \
        !          1046:        MACRO_BEGIN                                                     \
        !          1047:        (pri) = (th)->priority  /* start with base priority */          \
        !          1048:            + ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT));         \
        !          1049:        if ((pri) > 31) (pri) = 31;                                     \
        !          1050:        MACRO_END
        !          1051: #endif /* defined(PRI_SHIFT_2) */
        !          1052: 
        !          1053: /*
        !          1054:  *     compute_priority:
        !          1055:  *
        !          1056:  *     Compute the effective priority of the specified thread.
        !          1057:  *     The effective priority computation is as follows:
        !          1058:  *
        !          1059:  *     Take the base priority for this thread and add
        !          1060:  *     to it an increment derived from its cpu_usage.
        !          1061:  *
        !          1062:  *     The thread *must* be locked by the caller.
        !          1063:  */
        !          1064: 
        !          1065: void compute_priority(
        !          1066:        register thread_t       thread,
        !          1067:        boolean_t               resched)
        !          1068: {
        !          1069:        register int    pri;
        !          1070: 
        !          1071: #if    MACH_FIXPRI
        !          1072:        if (thread->policy == POLICY_TIMESHARE) {
        !          1073: #endif /* MACH_FIXPRI */
        !          1074:            do_priority_computation(thread, pri);
        !          1075:            if (thread->depress_priority < 0)
        !          1076:                set_pri(thread, pri, resched);
        !          1077:            else
        !          1078:                thread->depress_priority = pri;
        !          1079: #if    MACH_FIXPRI
        !          1080:        }
        !          1081:        else {
        !          1082:            set_pri(thread, thread->priority, resched);
        !          1083:        }
        !          1084: #endif /* MACH_FIXPRI */
        !          1085: }
        !          1086: 
        !          1087: /*
        !          1088:  *     compute_my_priority:
        !          1089:  *
        !          1090:  *     Version of compute priority for current thread or thread
        !          1091:  *     being manipulated by scheduler (going on or off a runq).
        !          1092:  *     Only used for priority updates.  Policy or priority changes
        !          1093:  *     must call compute_priority above.  Caller must have thread
        !          1094:  *     locked and know it is timesharing and not depressed.
        !          1095:  */
        !          1096: 
        !          1097: void compute_my_priority(
        !          1098:        register thread_t       thread)
        !          1099: {
        !          1100:        register int temp_pri;
        !          1101: 
        !          1102:        do_priority_computation(thread,temp_pri);
        !          1103:        thread->sched_pri = temp_pri;
        !          1104: }
        !          1105: 
        !          1106: /*
        !          1107:  *     recompute_priorities:
        !          1108:  *
        !          1109:  *     Update the priorities of all threads periodically.
        !          1110:  */
        !          1111: void recompute_priorities(void)
        !          1112: {
        !          1113: #if    SIMPLE_CLOCK
        !          1114:        int     new_usec;
        !          1115: #endif /* SIMPLE_CLOCK */
        !          1116: 
        !          1117:        sched_tick++;           /* age usage one more time */
        !          1118:        set_timeout(&recompute_priorities_timer, hz);
        !          1119: #if    SIMPLE_CLOCK
        !          1120:        /*
        !          1121:         *      Compensate for clock drift.  sched_usec is an
        !          1122:         *      exponential average of the number of microseconds in
        !          1123:         *      a second.  It decays in the same fashion as cpu_usage.
        !          1124:         */
        !          1125:        new_usec = sched_usec_elapsed();
        !          1126:        sched_usec = (5*sched_usec + 3*new_usec)/8;
        !          1127: #endif /* SIMPLE_CLOCK */
        !          1128:        /*
        !          1129:         *      Wakeup scheduler thread.
        !          1130:         */
        !          1131:        if (sched_thread_id != THREAD_NULL) {
        !          1132:                clear_wait(sched_thread_id, THREAD_AWAKENED, FALSE);
        !          1133:        }
        !          1134: }
        !          1135: 
        !          1136: /*
        !          1137:  *     update_priority
        !          1138:  *
        !          1139:  *     Cause the priority computation of a thread that has been
        !          1140:  *     sleeping or suspended to "catch up" with the system.  Thread
        !          1141:  *     *MUST* be locked by caller.  If thread is running, then this
        !          1142:  *     can only be called by the thread on itself.
        !          1143:  */
        !          1144: void update_priority(
        !          1145:        register thread_t       thread)
        !          1146: {
        !          1147:        register unsigned int   ticks;
        !          1148:        register shift_t        shiftp;
        !          1149:        register int            temp_pri;
        !          1150: 
        !          1151:        ticks = sched_tick - thread->sched_stamp;
        !          1152: 
        !          1153:        assert(ticks != 0);
        !          1154: 
        !          1155:        /*
        !          1156:         *      If asleep for more than 30 seconds forget all
        !          1157:         *      cpu_usage, else catch up on missed aging.
        !          1158:         *      5/8 ** n is approximated by the two shifts
        !          1159:         *      in the wait_shift array.
        !          1160:         */
        !          1161:        thread->sched_stamp += ticks;
        !          1162:        thread_timer_delta(thread);
        !          1163:        if (ticks >  30) {
        !          1164:                thread->cpu_usage = 0;
        !          1165:                thread->sched_usage = 0;
        !          1166:        }
        !          1167:        else {
        !          1168:                thread->cpu_usage += thread->cpu_delta;
        !          1169:                thread->sched_usage += thread->sched_delta;
        !          1170:                shiftp = &wait_shift[ticks];
        !          1171:                if (shiftp->shift2 > 0) {
        !          1172:                    thread->cpu_usage =
        !          1173:                        (thread->cpu_usage >> shiftp->shift1) +
        !          1174:                        (thread->cpu_usage >> shiftp->shift2);
        !          1175:                    thread->sched_usage =
        !          1176:                        (thread->sched_usage >> shiftp->shift1) +
        !          1177:                        (thread->sched_usage >> shiftp->shift2);
        !          1178:                }
        !          1179:                else {
        !          1180:                    thread->cpu_usage =
        !          1181:                        (thread->cpu_usage >> shiftp->shift1) -
        !          1182:                        (thread->cpu_usage >> -(shiftp->shift2));
        !          1183:                    thread->sched_usage =
        !          1184:                        (thread->sched_usage >> shiftp->shift1) -
        !          1185:                        (thread->sched_usage >> -(shiftp->shift2));
        !          1186:                }
        !          1187:        }
        !          1188:        thread->cpu_delta = 0;
        !          1189:        thread->sched_delta = 0;
        !          1190:        /*
        !          1191:         *      Recompute priority if appropriate.
        !          1192:         */
        !          1193:        if (
        !          1194: #if    MACH_FIXPRI
        !          1195:            (thread->policy == POLICY_TIMESHARE) &&
        !          1196: #endif /* MACH_FIXPRI */
        !          1197:            (thread->depress_priority < 0)) {
        !          1198:                do_priority_computation(thread, temp_pri);
        !          1199:                thread->sched_pri = temp_pri;
        !          1200:        }
        !          1201: }
        !          1202: 
        !          1203: /*
        !          1204:  *     run_queue_enqueue macro for thread_setrun().
        !          1205:  */
        !          1206: #if    DEBUG
        !          1207: #define run_queue_enqueue(rq, th)                                      \
        !          1208:        MACRO_BEGIN                                                     \
        !          1209:            register unsigned int       whichq;                         \
        !          1210:                                                                        \
        !          1211:            whichq = (th)->sched_pri;                                   \
        !          1212:            if (whichq >= NRQS) {                                       \
        !          1213:        printf("thread_setrun: pri too high (%d)\n", (th)->sched_pri);  \
        !          1214:                whichq = NRQS - 1;                                      \
        !          1215:            }                                                           \
        !          1216:                                                                        \
        !          1217:            simple_lock(&(rq)->lock);   /* lock the run queue */        \
        !          1218:            checkrq((rq), "thread_setrun: before adding thread");       \
        !          1219:            enqueue_tail(&(rq)->runq[whichq], (queue_entry_t) (th));    \
        !          1220:                                                                        \
        !          1221:            if (whichq < (rq)->low || (rq)->count == 0)                 \
        !          1222:                 (rq)->low = whichq;    /* minimize */                  \
        !          1223:                                                                        \
        !          1224:            (rq)->count++;                                              \
        !          1225:            (th)->runq = (rq);                                          \
        !          1226:            thread_check((th), (rq));                                   \
        !          1227:            checkrq((rq), "thread_setrun: after adding thread");        \
        !          1228:            simple_unlock(&(rq)->lock);                                 \
        !          1229:        MACRO_END
        !          1230: #else  /* DEBUG */
        !          1231: #define run_queue_enqueue(rq, th)                                      \
        !          1232:        MACRO_BEGIN                                                     \
        !          1233:            register unsigned int       whichq;                         \
        !          1234:                                                                        \
        !          1235:            whichq = (th)->sched_pri;                                   \
        !          1236:            if (whichq >= NRQS) {                                       \
        !          1237:        printf("thread_setrun: pri too high (%d)\n", (th)->sched_pri);  \
        !          1238:                whichq = NRQS - 1;                                      \
        !          1239:            }                                                           \
        !          1240:                                                                        \
        !          1241:            simple_lock(&(rq)->lock);   /* lock the run queue */        \
        !          1242:            enqueue_tail(&(rq)->runq[whichq], (queue_entry_t) (th));    \
        !          1243:                                                                        \
        !          1244:            if (whichq < (rq)->low || (rq)->count == 0)                 \
        !          1245:                 (rq)->low = whichq;    /* minimize */                  \
        !          1246:                                                                        \
        !          1247:            (rq)->count++;                                              \
        !          1248:            (th)->runq = (rq);                                          \
        !          1249:            simple_unlock(&(rq)->lock);                                 \
        !          1250:        MACRO_END
        !          1251: #endif /* DEBUG */
        !          1252: /*
        !          1253:  *     thread_setrun:
        !          1254:  *
        !          1255:  *     Make thread runnable; dispatch directly onto an idle processor
        !          1256:  *     if possible.  Else put on appropriate run queue (processor
        !          1257:  *     if bound, else processor set.  Caller must have lock on thread.
        !          1258:  *     This is always called at splsched.
        !          1259:  */
        !          1260: 
        !          1261: void thread_setrun(
        !          1262:        register thread_t       th,
        !          1263:        boolean_t               may_preempt)
        !          1264: {
        !          1265:        register processor_t    processor;
        !          1266:        register run_queue_t    rq;
        !          1267: #if    NCPUS > 1
        !          1268:        register processor_set_t        pset;
        !          1269: #endif /* NCPUS > 1 */
        !          1270: 
        !          1271:        /*
        !          1272:         *      Update priority if needed.
        !          1273:         */
        !          1274:        if (th->sched_stamp != sched_tick) {
        !          1275:                update_priority(th);
        !          1276:        }
        !          1277: 
        !          1278:        assert(th->runq == RUN_QUEUE_NULL);
        !          1279: 
        !          1280: #if    NCPUS > 1
        !          1281:        /*
        !          1282:         *      Try to dispatch the thread directly onto an idle processor.
        !          1283:         */
        !          1284:        if ((processor = th->bound_processor) == PROCESSOR_NULL) {
        !          1285:            /*
        !          1286:             *  Not bound, any processor in the processor set is ok.
        !          1287:             */
        !          1288:            pset = th->processor_set;
        !          1289: #if    HW_FOOTPRINT
        !          1290:            /*
        !          1291:             *  But first check the last processor it ran on.
        !          1292:             */
        !          1293:            processor = th->last_processor;
        !          1294:            if (processor->state == PROCESSOR_IDLE) {
        !          1295:                    simple_lock(&processor->lock);
        !          1296:                    simple_lock(&pset->idle_lock);
        !          1297:                    if ((processor->state == PROCESSOR_IDLE)
        !          1298: #if    MACH_HOST
        !          1299:                        && (processor->processor_set == pset)
        !          1300: #endif /* MACH_HOST */
        !          1301:                        ) {
        !          1302:                            queue_remove(&pset->idle_queue, processor,
        !          1303:                                processor_t, processor_queue);
        !          1304:                            pset->idle_count--;
        !          1305:                            processor->next_thread = th;
        !          1306:                            processor->state = PROCESSOR_DISPATCHING;
        !          1307:                            simple_unlock(&pset->idle_lock);
        !          1308:                            simple_unlock(&processor->lock);
        !          1309:                            return;
        !          1310:                    }
        !          1311:                    simple_unlock(&pset->idle_lock);
        !          1312:                    simple_unlock(&processor->lock);
        !          1313:            }
        !          1314: #endif /* HW_FOOTPRINT */
        !          1315: 
        !          1316:            if (pset->idle_count > 0) {
        !          1317:                simple_lock(&pset->idle_lock);
        !          1318:                if (pset->idle_count > 0) {
        !          1319:                    processor = (processor_t) queue_first(&pset->idle_queue);
        !          1320:                    queue_remove(&(pset->idle_queue), processor, processor_t,
        !          1321:                                processor_queue);
        !          1322:                    pset->idle_count--;
        !          1323:                    processor->next_thread = th;
        !          1324:                    processor->state = PROCESSOR_DISPATCHING;
        !          1325:                    simple_unlock(&pset->idle_lock);
        !          1326:                    return;
        !          1327:                }
        !          1328:                simple_unlock(&pset->idle_lock);
        !          1329:            }
        !          1330:            rq = &(pset->runq);
        !          1331:            run_queue_enqueue(rq,th);
        !          1332:            /*
        !          1333:             * Preempt check
        !          1334:             */
        !          1335:            if (may_preempt &&
        !          1336: #if    MACH_HOST
        !          1337:                (pset == current_processor()->processor_set) &&
        !          1338: #endif /* MACH_HOST */
        !          1339:                (current_thread()->sched_pri > th->sched_pri)) {
        !          1340:                        /*
        !          1341:                         *      Turn off first_quantum to allow csw.
        !          1342:                         */
        !          1343:                        current_processor()->first_quantum = FALSE;
        !          1344:                        ast_on(cpu_number(), AST_BLOCK);
        !          1345:            }
        !          1346:        }
        !          1347:        else {
        !          1348:            /*
        !          1349:             *  Bound, can only run on bound processor.  Have to lock
        !          1350:             *  processor here because it may not be the current one.
        !          1351:             */
        !          1352:            if (processor->state == PROCESSOR_IDLE) {
        !          1353:                simple_lock(&processor->lock);
        !          1354:                pset = processor->processor_set;
        !          1355:                simple_lock(&pset->idle_lock);
        !          1356:                if (processor->state == PROCESSOR_IDLE) {
        !          1357:                    queue_remove(&pset->idle_queue, processor,
        !          1358:                        processor_t, processor_queue);
        !          1359:                    pset->idle_count--;
        !          1360:                    processor->next_thread = th;
        !          1361:                    processor->state = PROCESSOR_DISPATCHING;
        !          1362:                    simple_unlock(&pset->idle_lock);
        !          1363:                    simple_unlock(&processor->lock);
        !          1364:                    return;
        !          1365:                }
        !          1366:                simple_unlock(&pset->idle_lock);
        !          1367:                simple_unlock(&processor->lock);
        !          1368:            }
        !          1369:            rq = &(processor->runq);
        !          1370:            run_queue_enqueue(rq,th);
        !          1371: 
        !          1372:            /*
        !          1373:             *  Cause ast on processor if processor is on line.
        !          1374:             *
        !          1375:             *  XXX Don't do this remotely to master because this will
        !          1376:             *  XXX send an interprocessor interrupt, and that's too
        !          1377:             *  XXX expensive for all the unparallelized U*x code.
        !          1378:             */
        !          1379:            if (processor == current_processor()) {
        !          1380:                ast_on(cpu_number(), AST_BLOCK);
        !          1381:            }
        !          1382:            else if ((processor != master_processor) &&
        !          1383:                     (processor->state != PROCESSOR_OFF_LINE)) {
        !          1384:                        cause_ast_check(processor);
        !          1385:            }
        !          1386:        }
        !          1387: #else  /* NCPUS > 1 */
        !          1388:        /*
        !          1389:         *      XXX should replace queue with a boolean in this case.
        !          1390:         */
        !          1391:        if (default_pset.idle_count > 0) {
        !          1392:            processor = (processor_t) queue_first(&default_pset.idle_queue);
        !          1393:            queue_remove(&default_pset.idle_queue, processor,
        !          1394:                processor_t, processor_queue);
        !          1395:            default_pset.idle_count--;
        !          1396:            processor->next_thread = th;
        !          1397:            processor->state = PROCESSOR_DISPATCHING;
        !          1398:            return;
        !          1399:        }
        !          1400:        if (th->bound_processor == PROCESSOR_NULL) {
        !          1401:                rq = &(default_pset.runq);
        !          1402:        }
        !          1403:        else {
        !          1404:                rq = &(master_processor->runq);
        !          1405:                ast_on(cpu_number(), AST_BLOCK);
        !          1406:        }
        !          1407:        run_queue_enqueue(rq,th);
        !          1408: 
        !          1409:        /*
        !          1410:         * Preempt check
        !          1411:         */
        !          1412:        if (may_preempt && (current_thread()->sched_pri > th->sched_pri)) {
        !          1413:                /*
        !          1414:                 *      Turn off first_quantum to allow context switch.
        !          1415:                 */
        !          1416:                current_processor()->first_quantum = FALSE;
        !          1417:                ast_on(cpu_number(), AST_BLOCK);
        !          1418:        }
        !          1419: #endif /* NCPUS > 1 */
        !          1420: }
        !          1421: 
        !          1422: /*
        !          1423:  *     set_pri:
        !          1424:  *
        !          1425:  *     Set the priority of the specified thread to the specified
        !          1426:  *     priority.  This may cause the thread to change queues.
        !          1427:  *
        !          1428:  *     The thread *must* be locked by the caller.
        !          1429:  */
        !          1430: 
        !          1431: void set_pri(
        !          1432:        thread_t        th,
        !          1433:        int             pri,
        !          1434:        boolean_t       resched)
        !          1435: {
        !          1436:        register struct run_queue       *rq;
        !          1437: 
        !          1438:        rq = rem_runq(th);
        !          1439:        th->sched_pri = pri;
        !          1440:        if (rq != RUN_QUEUE_NULL) {
        !          1441:            if (resched)
        !          1442:                thread_setrun(th, TRUE);
        !          1443:            else
        !          1444:                run_queue_enqueue(rq, th);
        !          1445:        }
        !          1446: }
        !          1447: 
        !          1448: /*
        !          1449:  *     rem_runq:
        !          1450:  *
        !          1451:  *     Remove a thread from its run queue.
        !          1452:  *     The run queue that the process was on is returned
        !          1453:  *     (or RUN_QUEUE_NULL if not on a run queue).  Thread *must* be locked
        !          1454:  *     before calling this routine.  Unusual locking protocol on runq
        !          1455:  *     field in thread structure makes this code interesting; see thread.h.
        !          1456:  */
        !          1457: 
        !          1458: struct run_queue *rem_runq(
        !          1459:        thread_t                th)
        !          1460: {
        !          1461:        register struct run_queue       *rq;
        !          1462: 
        !          1463:        rq = th->runq;
        !          1464:        /*
        !          1465:         *      If rq is RUN_QUEUE_NULL, the thread will stay out of the
        !          1466:         *      run_queues because the caller locked the thread.  Otherwise
        !          1467:         *      the thread is on a runq, but could leave.
        !          1468:         */
        !          1469:        if (rq != RUN_QUEUE_NULL) {
        !          1470:                simple_lock(&rq->lock);
        !          1471: #if    DEBUG
        !          1472:                checkrq(rq, "rem_runq: at entry");
        !          1473: #endif /* DEBUG */
        !          1474:                if (rq == th->runq) {
        !          1475:                        /*
        !          1476:                         *      Thread is in a runq and we have a lock on
        !          1477:                         *      that runq.
        !          1478:                         */
        !          1479: #if    DEBUG
        !          1480:                        checkrq(rq, "rem_runq: before removing thread");
        !          1481:                        thread_check(th, rq);
        !          1482: #endif /* DEBUG */
        !          1483:                        remqueue(&rq->runq[0], (queue_entry_t) th);
        !          1484:                        rq->count--;
        !          1485: #if    DEBUG
        !          1486:                        checkrq(rq, "rem_runq: after removing thread");
        !          1487: #endif /* DEBUG */
        !          1488:                        th->runq = RUN_QUEUE_NULL;
        !          1489:                        simple_unlock(&rq->lock);
        !          1490:                }
        !          1491:                else {
        !          1492:                        /*
        !          1493:                         *      The thread left the runq before we could
        !          1494:                         *      lock the runq.  It is not on a runq now, and
        !          1495:                         *      can't move again because this routine's
        !          1496:                         *      caller locked the thread.
        !          1497:                         */
        !          1498:                        simple_unlock(&rq->lock);
        !          1499:                        rq = RUN_QUEUE_NULL;
        !          1500:                }
        !          1501:        }
        !          1502: 
        !          1503:        return rq;
        !          1504: }
        !          1505: 
        !          1506: 
        !          1507: /*
        !          1508:  *     choose_thread:
        !          1509:  *
        !          1510:  *     Choose a thread to execute.  The thread chosen is removed
        !          1511:  *     from its run queue.  Note that this requires only that the runq
        !          1512:  *     lock be held.
        !          1513:  *
        !          1514:  *     Strategy:
        !          1515:  *             Check processor runq first; if anything found, run it.
        !          1516:  *             Else check pset runq; if nothing found, return idle thread.
        !          1517:  *
        !          1518:  *     Second line of strategy is implemented by choose_pset_thread.
        !          1519:  *     This is only called on processor startup and when thread_block
        !          1520:  *     thinks there's something in the processor runq.
        !          1521:  */
        !          1522: 
        !          1523: thread_t choose_thread(
        !          1524:        processor_t myprocessor)
        !          1525: {
        !          1526:        thread_t th;
        !          1527:        register queue_t q;
        !          1528:        register run_queue_t runq;
        !          1529:        register int i;
        !          1530:        register processor_set_t pset;
        !          1531: 
        !          1532:        runq = &myprocessor->runq;
        !          1533: 
        !          1534:        simple_lock(&runq->lock);
        !          1535:        if (runq->count > 0) {
        !          1536:            q = runq->runq + runq->low;
        !          1537:            for (i = runq->low; i < NRQS ; i++, q++) {
        !          1538:                if (!queue_empty(q)) {
        !          1539:                    th = (thread_t) dequeue_head(q);
        !          1540:                    th->runq = RUN_QUEUE_NULL;
        !          1541:                    runq->count--;
        !          1542:                    runq->low = i;
        !          1543:                    simple_unlock(&runq->lock);
        !          1544:                    return th;
        !          1545:                }
        !          1546:            }
        !          1547:            panic("choose_thread");
        !          1548:            /*NOTREACHED*/
        !          1549:        }
        !          1550:        simple_unlock(&runq->lock);
        !          1551: 
        !          1552:        pset = myprocessor->processor_set;
        !          1553: 
        !          1554:        simple_lock(&pset->runq.lock);
        !          1555:        return choose_pset_thread(myprocessor,pset);
        !          1556: }
        !          1557: 
        !          1558: /*
        !          1559:  *     choose_pset_thread:  choose a thread from processor_set runq or
        !          1560:  *             set processor idle and choose its idle thread.
        !          1561:  *
        !          1562:  *     Caller must be at splsched and have a lock on the runq.  This
        !          1563:  *     lock is released by this routine.  myprocessor is always the current
        !          1564:  *     processor, and pset must be its processor set.
        !          1565:  *     This routine chooses and removes a thread from the runq if there
        !          1566:  *     is one (and returns it), else it sets the processor idle and
        !          1567:  *     returns its idle thread.
        !          1568:  */
        !          1569: 
        !          1570: thread_t choose_pset_thread(
        !          1571:        register processor_t    myprocessor,
        !          1572:        processor_set_t         pset)
        !          1573: {
        !          1574:        register run_queue_t runq;
        !          1575:        register thread_t th;
        !          1576:        register queue_t q;
        !          1577:        register int i;
        !          1578: 
        !          1579:        runq = &pset->runq;
        !          1580: 
        !          1581:        if (runq->count > 0) {
        !          1582:            q = runq->runq + runq->low;
        !          1583:            for (i = runq->low; i < NRQS ; i++, q++) {
        !          1584:                if (!queue_empty(q)) {
        !          1585:                    th = (thread_t) dequeue_head(q);
        !          1586:                    th->runq = RUN_QUEUE_NULL;
        !          1587:                    runq->count--;
        !          1588:                    /*
        !          1589:                     *  For POLICY_FIXEDPRI, runq->low must be
        !          1590:                     *  accurate!
        !          1591:                     */
        !          1592: #if    MACH_FIXPRI
        !          1593:                    if ((runq->count > 0) &&
        !          1594:                        (pset->policies & POLICY_FIXEDPRI)) {
        !          1595:                            while (queue_empty(q)) {
        !          1596:                                q++;
        !          1597:                                i++;
        !          1598:                            }
        !          1599:                    }
        !          1600: #endif /* MACH_FIXPRI */
        !          1601:                    runq->low = i;
        !          1602: #if    DEBUG
        !          1603:                    checkrq(runq, "choose_pset_thread");
        !          1604: #endif /* DEBUG */
        !          1605:                    simple_unlock(&runq->lock);
        !          1606:                    return th;
        !          1607:                }
        !          1608:            }
        !          1609:            panic("choose_pset_thread");
        !          1610:            /*NOTREACHED*/
        !          1611:        }
        !          1612:        simple_unlock(&runq->lock);
        !          1613: 
        !          1614:        /*
        !          1615:         *      Nothing is runnable, so set this processor idle if it
        !          1616:         *      was running.  If it was in an assignment or shutdown,
        !          1617:         *      leave it alone.  Return its idle thread.
        !          1618:         */
        !          1619:        simple_lock(&pset->idle_lock);
        !          1620:        if (myprocessor->state == PROCESSOR_RUNNING) {
        !          1621:            myprocessor->state = PROCESSOR_IDLE;
        !          1622:            /*
        !          1623:             *  XXX Until it goes away, put master on end of queue, others
        !          1624:             *  XXX on front so master gets used last.
        !          1625:             */
        !          1626:            if (myprocessor == master_processor) {
        !          1627:                queue_enter(&(pset->idle_queue), myprocessor,
        !          1628:                        processor_t, processor_queue);
        !          1629:            }
        !          1630:            else {
        !          1631:                queue_enter_first(&(pset->idle_queue), myprocessor,
        !          1632:                        processor_t, processor_queue);
        !          1633:            }
        !          1634: 
        !          1635:            pset->idle_count++;
        !          1636:        }
        !          1637:        simple_unlock(&pset->idle_lock);
        !          1638: 
        !          1639:        return myprocessor->idle_thread;
        !          1640: }
        !          1641: 
        !          1642: /*
        !          1643:  *     no_dispatch_count counts number of times processors go non-idle
        !          1644:  *     without being dispatched.  This should be very rare.
        !          1645:  */
        !          1646: int    no_dispatch_count = 0;
        !          1647: 
        !          1648: /*
        !          1649:  *     This is the idle thread, which just looks for other threads
        !          1650:  *     to execute.
        !          1651:  */
        !          1652: 
        !          1653: void idle_thread_continue(void)
        !          1654: {
        !          1655:        register processor_t myprocessor;
        !          1656:        register volatile thread_t *threadp;
        !          1657:        register volatile int *gcount;
        !          1658:        register volatile int *lcount;
        !          1659:        register thread_t new_thread;
        !          1660:        register int state;
        !          1661:        int mycpu;
        !          1662:        spl_t s;
        !          1663: 
        !          1664:        mycpu = cpu_number();
        !          1665:        myprocessor = current_processor();
        !          1666:        threadp = (volatile thread_t *) &myprocessor->next_thread;
        !          1667:        lcount = (volatile int *) &myprocessor->runq.count;
        !          1668: 
        !          1669:        while (TRUE) {
        !          1670: #ifdef MARK_CPU_IDLE
        !          1671:                MARK_CPU_IDLE(mycpu);
        !          1672: #endif /* MARK_CPU_IDLE */
        !          1673: 
        !          1674: #if    MACH_HOST
        !          1675:                gcount = (volatile int *)
        !          1676:                                &myprocessor->processor_set->runq.count;
        !          1677: #else  /* MACH_HOST */
        !          1678:                gcount = (volatile int *) &default_pset.runq.count;
        !          1679: #endif /* MACH_HOST */
        !          1680: 
        !          1681: /*
        !          1682:  *     This cpu will be dispatched (by thread_setrun) by setting next_thread
        !          1683:  *     to the value of the thread to run next.  Also check runq counts.
        !          1684:  */
        !          1685:                while ((*threadp == (volatile thread_t)THREAD_NULL) &&
        !          1686:                       (*gcount == 0) && (*lcount == 0)) {
        !          1687: 
        !          1688:                        /* check for ASTs while we wait */
        !          1689: 
        !          1690:                        if (need_ast[mycpu] &~ AST_SCHEDULING) {
        !          1691:                                (void) splsched();
        !          1692:                                /* don't allow scheduling ASTs */
        !          1693:                                need_ast[mycpu] &= ~AST_SCHEDULING;
        !          1694:                                ast_taken();
        !          1695:                                /* back at spl0 */
        !          1696:                        }
        !          1697: 
        !          1698:                        /*
        !          1699:                         * machine_idle is a machine dependent function,
        !          1700:                         * to conserve power.
        !          1701:                         */
        !          1702: #if    POWER_SAVE
        !          1703:                        machine_idle(mycpu);
        !          1704: #endif /* POWER_SAVE */
        !          1705:                }
        !          1706: 
        !          1707: #ifdef MARK_CPU_ACTIVE
        !          1708:                MARK_CPU_ACTIVE(mycpu);
        !          1709: #endif /* MARK_CPU_ACTIVE */
        !          1710: 
        !          1711:                s = splsched();
        !          1712: 
        !          1713:                /*
        !          1714:                 *      This is not a switch statement to avoid the
        !          1715:                 *      bounds checking code in the common case.
        !          1716:                 */
        !          1717: retry:
        !          1718:                state = myprocessor->state;
        !          1719:                if (state == PROCESSOR_DISPATCHING) {
        !          1720:                        /*
        !          1721:                         *      Commmon case -- cpu dispatched.
        !          1722:                         */
        !          1723:                        new_thread = (thread_t) *threadp;
        !          1724:                        *threadp = (volatile thread_t) THREAD_NULL;
        !          1725:                        myprocessor->state = PROCESSOR_RUNNING;
        !          1726:                        /*
        !          1727:                         *      set up quantum for new thread.
        !          1728:                         */
        !          1729: #if    MACH_FIXPRI
        !          1730:                        if (new_thread->policy == POLICY_TIMESHARE) {
        !          1731: #endif /* MACH_FIXPRI */
        !          1732:                                /*
        !          1733:                                 *  Just use set quantum.  No point in
        !          1734:                                 *  checking for shorter local runq quantum;
        !          1735:                                 *  csw_needed will handle correctly.
        !          1736:                                 */
        !          1737: #if    MACH_HOST
        !          1738:                                myprocessor->quantum = new_thread->
        !          1739:                                        processor_set->set_quantum;
        !          1740: #else  /* MACH_HOST */
        !          1741:                                myprocessor->quantum =
        !          1742:                                        default_pset.set_quantum;
        !          1743: #endif /* MACH_HOST */
        !          1744: 
        !          1745: #if    MACH_FIXPRI
        !          1746:                        }
        !          1747:                        else {
        !          1748:                                /*
        !          1749:                                 *      POLICY_FIXEDPRI
        !          1750:                                 */
        !          1751:                                myprocessor->quantum = new_thread->sched_data;
        !          1752:                        }
        !          1753: #endif /* MACH_FIXPRI */
        !          1754:                        myprocessor->first_quantum = TRUE;
        !          1755:                        counter(c_idle_thread_handoff++);
        !          1756:                        thread_run(idle_thread_continue, new_thread);
        !          1757:                }
        !          1758:                else if (state == PROCESSOR_IDLE) {
        !          1759:                        register processor_set_t pset;
        !          1760: 
        !          1761:                        pset = myprocessor->processor_set;
        !          1762:                        simple_lock(&pset->idle_lock);
        !          1763:                        if (myprocessor->state != PROCESSOR_IDLE) {
        !          1764:                                /*
        !          1765:                                 *      Something happened, try again.
        !          1766:                                 */
        !          1767:                                simple_unlock(&pset->idle_lock);
        !          1768:                                goto retry;
        !          1769:                        }
        !          1770:                        /*
        !          1771:                         *      Processor was not dispatched (Rare).
        !          1772:                         *      Set it running again.
        !          1773:                         */
        !          1774:                        no_dispatch_count++;
        !          1775:                        pset->idle_count--;
        !          1776:                        queue_remove(&pset->idle_queue, myprocessor,
        !          1777:                                processor_t, processor_queue);
        !          1778:                        myprocessor->state = PROCESSOR_RUNNING;
        !          1779:                        simple_unlock(&pset->idle_lock);
        !          1780:                        counter(c_idle_thread_block++);
        !          1781:                        thread_block(idle_thread_continue);
        !          1782:                }
        !          1783:                else if ((state == PROCESSOR_ASSIGN) ||
        !          1784:                         (state == PROCESSOR_SHUTDOWN)) {
        !          1785:                        /*
        !          1786:                         *      Changing processor sets, or going off-line.
        !          1787:                         *      Release next_thread if there is one.  Actual
        !          1788:                         *      thread to run is on a runq.
        !          1789:                         */
        !          1790:                        if ((new_thread = (thread_t)*threadp)!= THREAD_NULL) {
        !          1791:                                *threadp = (volatile thread_t) THREAD_NULL;
        !          1792:                                thread_setrun(new_thread, FALSE);
        !          1793:                        }
        !          1794: 
        !          1795:                        counter(c_idle_thread_block++);
        !          1796:                        thread_block(idle_thread_continue);
        !          1797:                }
        !          1798:                else {
        !          1799:                        printf(" Bad processor state %d (Cpu %d)\n",
        !          1800:                                cpu_state(mycpu), mycpu);
        !          1801:                        panic("idle_thread");
        !          1802:                }
        !          1803: 
        !          1804:                (void) splx(s);
        !          1805:        }
        !          1806: }
        !          1807: 
        !          1808: void idle_thread(void)
        !          1809: {
        !          1810:        register thread_t self = current_thread();
        !          1811:        spl_t s;
        !          1812: 
        !          1813:        stack_privilege(self);
        !          1814: 
        !          1815:        s = splsched();
        !          1816:        self->priority = 31;
        !          1817:        self->sched_pri = 31;
        !          1818: 
        !          1819:        /*
        !          1820:         *      Set the idle flag to indicate that this is an idle thread,
        !          1821:         *      enter ourselves in the idle array, and thread_block() to get
        !          1822:         *      out of the run queues (and set the processor idle when we
        !          1823:         *      run next time).
        !          1824:         */
        !          1825:        thread_lock(self);
        !          1826:        self->state |= TH_IDLE;
        !          1827:        thread_unlock(self);
        !          1828:        current_processor()->idle_thread = self;
        !          1829:        (void) splx(s);
        !          1830: 
        !          1831:        counter(c_idle_thread_block++);
        !          1832:        thread_block(idle_thread_continue);
        !          1833:        idle_thread_continue();
        !          1834:        /*NOTREACHED*/
        !          1835: }
        !          1836: 
        !          1837: /*
        !          1838:  *     sched_thread: scheduler thread.
        !          1839:  *
        !          1840:  *     This thread handles periodic calculations in the scheduler that
        !          1841:  *     we don't want to do at interrupt level.  This allows us to
        !          1842:  *     avoid blocking.
        !          1843:  */
        !          1844: void sched_thread_continue(void)
        !          1845: {
        !          1846:     while (TRUE) {
        !          1847:        (void) compute_mach_factor();
        !          1848: 
        !          1849:        /*
        !          1850:         *      Check for stuck threads.  This can't be done off of
        !          1851:         *      the callout queue because it requires operations that
        !          1852:         *      can't be used from interrupt level.
        !          1853:         */
        !          1854:        if (sched_tick & 1)
        !          1855:                do_thread_scan();
        !          1856: 
        !          1857:        assert_wait((event_t) 0, FALSE);
        !          1858:        counter(c_sched_thread_block++);
        !          1859:        thread_block(sched_thread_continue);
        !          1860:     }
        !          1861: }
        !          1862: 
        !          1863: void sched_thread(void)
        !          1864: {
        !          1865:     sched_thread_id = current_thread();
        !          1866: 
        !          1867:     /*
        !          1868:      * Sleep on event 0, recompute_priorities() will awaken
        !          1869:      * us by calling clear_wait().
        !          1870:      */
        !          1871:     assert_wait((event_t) 0, FALSE);
        !          1872:     counter(c_sched_thread_block++);
        !          1873:     thread_block(sched_thread_continue);
        !          1874:     sched_thread_continue();
        !          1875:     /*NOTREACHED*/
        !          1876: }
        !          1877: 
        !          1878: #define        MAX_STUCK_THREADS       16
        !          1879: 
        !          1880: /*
        !          1881:  *     do_thread_scan: scan for stuck threads.  A thread is stuck if
        !          1882:  *     it is runnable but its priority is so low that it has not
        !          1883:  *     run for several seconds.  Its priority should be higher, but
        !          1884:  *     won't be until it runs and calls update_priority.  The scanner
        !          1885:  *     finds these threads and does the updates.
        !          1886:  *
        !          1887:  *     Scanner runs in two passes.  Pass one squirrels likely
        !          1888:  *     thread ids away in an array, and removes them from the run queue.
        !          1889:  *     Pass two does the priority updates.  This is necessary because
        !          1890:  *     the run queue lock is required for the candidate scan, but
        !          1891:  *     cannot be held during updates [set_pri will deadlock].
        !          1892:  *
        !          1893:  *     Array length should be enough so that restart isn't necessary,
        !          1894:  *     but restart logic is included.  Does not scan processor runqs.
        !          1895:  *
        !          1896:  */
        !          1897: 
        !          1898: boolean_t do_thread_scan_debug = FALSE;
        !          1899: 
        !          1900: thread_t               stuck_threads[MAX_STUCK_THREADS];
        !          1901: int                    stuck_count = 0;
        !          1902: 
        !          1903: /*
        !          1904:  *     do_runq_scan is the guts of pass 1.  It scans a runq for
        !          1905:  *     stuck threads.  A boolean is returned indicating whether
        !          1906:  *     it ran out of space.
        !          1907:  */
        !          1908: 
        !          1909: boolean_t
        !          1910: do_runq_scan(
        !          1911:        run_queue_t     runq)
        !          1912: {
        !          1913:        register spl_t          s;
        !          1914:        register queue_t        q;
        !          1915:        register thread_t       thread;
        !          1916:        register int            count;
        !          1917: 
        !          1918:        s = splsched();
        !          1919:        simple_lock(&runq->lock);
        !          1920:        if((count = runq->count) > 0) {
        !          1921:            q = runq->runq + runq->low;
        !          1922:            while (count > 0) {
        !          1923:                thread = (thread_t) queue_first(q);
        !          1924:                while (!queue_end(q, (queue_entry_t) thread)) {
        !          1925:                    /*
        !          1926:                     *  Get the next thread now, since we may
        !          1927:                     *  remove this thread from the run queue.
        !          1928:                     */
        !          1929:                    thread_t next = (thread_t) queue_next(&thread->links);
        !          1930: 
        !          1931:                    if ((thread->state & TH_SCHED_STATE) == TH_RUN &&
        !          1932:                        sched_tick - thread->sched_stamp > 1) {
        !          1933:                            /*
        !          1934:                             *  Stuck, save its id for later.
        !          1935:                             */
        !          1936:                            if (stuck_count == MAX_STUCK_THREADS) {
        !          1937:                                /*
        !          1938:                                 *      !@#$% No more room.
        !          1939:                                 */
        !          1940:                                simple_unlock(&runq->lock);
        !          1941:                                splx(s);
        !          1942:                                return TRUE;
        !          1943:                            }
        !          1944:                            /*
        !          1945:                             *  We can`t take the thread_lock here,
        !          1946:                             *  since we already have the runq lock.
        !          1947:                             *  So we can`t grab a reference to the
        !          1948:                             *  thread.  However, a thread that is
        !          1949:                             *  in RUN state cannot be deallocated
        !          1950:                             *  until it stops running.  If it isn`t
        !          1951:                             *  on the runq, then thread_halt cannot
        !          1952:                             *  see it.  So we remove the thread
        !          1953:                             *  from the runq to make it safe.
        !          1954:                             */
        !          1955:                            remqueue(q, (queue_entry_t) thread);
        !          1956:                            runq->count--;
        !          1957:                            thread->runq = RUN_QUEUE_NULL;
        !          1958: 
        !          1959:                            stuck_threads[stuck_count++] = thread;
        !          1960: if (do_thread_scan_debug)
        !          1961:     printf("do_runq_scan: adding thread %#x\n", thread);
        !          1962:                    }
        !          1963:                    count--;
        !          1964:                    thread = next;
        !          1965:                }
        !          1966:                q++;
        !          1967:            }
        !          1968:        }
        !          1969:        simple_unlock(&runq->lock);
        !          1970:        splx(s);
        !          1971: 
        !          1972:        return FALSE;
        !          1973: }
        !          1974: 
        !          1975: void do_thread_scan(void)
        !          1976: {
        !          1977:        register spl_t          s;
        !          1978:        register boolean_t      restart_needed = 0;
        !          1979:        register thread_t       thread;
        !          1980: #if    MACH_HOST
        !          1981:        register processor_set_t        pset;
        !          1982: #endif /* MACH_HOST */
        !          1983: 
        !          1984:        do {
        !          1985: #if    MACH_HOST
        !          1986:            simple_lock(&all_psets_lock);
        !          1987:            queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
        !          1988:                if (restart_needed = do_runq_scan(&pset->runq))
        !          1989:                        break;
        !          1990:            }
        !          1991:            simple_unlock(&all_psets_lock);
        !          1992: #else  /* MACH_HOST */
        !          1993:            restart_needed = do_runq_scan(&default_pset.runq);
        !          1994: #endif /* MACH_HOST */
        !          1995:            if (!restart_needed)
        !          1996:                restart_needed = do_runq_scan(&master_processor->runq);
        !          1997: 
        !          1998:            /*
        !          1999:             *  Ok, we now have a collection of candidates -- fix them.
        !          2000:             */
        !          2001: 
        !          2002:            while (stuck_count > 0) {
        !          2003:                thread = stuck_threads[--stuck_count];
        !          2004:                stuck_threads[stuck_count] = THREAD_NULL;
        !          2005:                s = splsched();
        !          2006:                thread_lock(thread);
        !          2007:                if ((thread->state & TH_SCHED_STATE) == TH_RUN) {
        !          2008:                        /*
        !          2009:                         *      Do the priority update.  Call
        !          2010:                         *      thread_setrun because thread is
        !          2011:                         *      off the run queues.
        !          2012:                         */
        !          2013:                        update_priority(thread);
        !          2014:                        thread_setrun(thread, TRUE);
        !          2015:                }
        !          2016:                thread_unlock(thread);
        !          2017:                splx(s);
        !          2018:            }
        !          2019:        } while (restart_needed);
        !          2020: }
        !          2021: 
        !          2022: #if    DEBUG
        !          2023: void checkrq(
        !          2024:        run_queue_t     rq,
        !          2025:        char            *msg)
        !          2026: {
        !          2027:        register queue_t        q1;
        !          2028:        register int            i, j;
        !          2029:        register queue_entry_t  e;
        !          2030:        register int            low;
        !          2031: 
        !          2032:        low = -1;
        !          2033:        j = 0;
        !          2034:        q1 = rq->runq;
        !          2035:        for (i = 0; i < NRQS; i++) {
        !          2036:            if (q1->next == q1) {
        !          2037:                if (q1->prev != q1)
        !          2038:                    panic("checkrq: empty at %s", msg);
        !          2039:            }
        !          2040:            else {
        !          2041:                if (low == -1)
        !          2042:                    low = i;
        !          2043: 
        !          2044:                for (e = q1->next; e != q1; e = e->next) {
        !          2045:                    j++;
        !          2046:                    if (e->next->prev != e)
        !          2047:                        panic("checkrq-2 at %s", msg);
        !          2048:                    if (e->prev->next != e)
        !          2049:                        panic("checkrq-3 at %s", msg);
        !          2050:                }
        !          2051:            }
        !          2052:            q1++;
        !          2053:        }
        !          2054:        if (j != rq->count)
        !          2055:            panic("checkrq: count wrong at %s", msg);
        !          2056:        if (rq->count != 0 && low < rq->low)
        !          2057:            panic("checkrq: low wrong at %s", msg);
        !          2058: }
        !          2059: 
        !          2060: void thread_check(
        !          2061:        register thread_t       th,
        !          2062:        register run_queue_t    rq)
        !          2063: {
        !          2064:        register unsigned int   whichq;
        !          2065: 
        !          2066:        whichq = th->sched_pri;
        !          2067:        if (whichq >= NRQS) {
        !          2068:                printf("thread_check: priority too high\n");
        !          2069:                whichq = NRQS-1;
        !          2070:        }
        !          2071:        if ((th->links.next == &rq->runq[whichq]) &&
        !          2072:                (rq->runq[whichq].prev != (queue_entry_t)th))
        !          2073:                        panic("thread_check");
        !          2074: }
        !          2075: #endif /* DEBUG */

unix.superglobalmegacorp.com

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