Annotation of Gnu-Mach/kern/thread.c, revision 1.1.1.8

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1994-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:   kern/thread.c
                     28:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub
                     29:  *     Date:   1986
                     30:  *
                     31:  *     Thread management primitives implementation.
                     32:  */
                     33: 
1.1.1.4   root       34: #include <kern/printf.h>
1.1       root       35: #include <mach/std_types.h>
                     36: #include <mach/policy.h>
                     37: #include <mach/thread_info.h>
                     38: #include <mach/thread_special_ports.h>
                     39: #include <mach/thread_status.h>
                     40: #include <mach/time_value.h>
1.1.1.4   root       41: #include <machine/vm_param.h>
1.1       root       42: #include <kern/ast.h>
                     43: #include <kern/counters.h>
1.1.1.4   root       44: #include <kern/debug.h>
                     45: #include <kern/eventcount.h>
                     46: #include <kern/ipc_mig.h>
1.1       root       47: #include <kern/ipc_tt.h>
                     48: #include <kern/processor.h>
                     49: #include <kern/queue.h>
                     50: #include <kern/sched.h>
                     51: #include <kern/sched_prim.h>
1.1.1.4   root       52: #include <kern/syscall_subr.h>
1.1       root       53: #include <kern/thread.h>
                     54: #include <kern/thread_swap.h>
                     55: #include <kern/host.h>
1.1.1.4   root       56: #include <kern/kalloc.h>
                     57: #include <kern/slab.h>
                     58: #include <kern/mach_clock.h>
1.1       root       59: #include <vm/vm_kern.h>
1.1.1.5   root       60: #include <vm/vm_user.h>
1.1       root       61: #include <ipc/ipc_kmsg.h>
                     62: #include <ipc/ipc_port.h>
                     63: #include <ipc/mach_msg.h>
1.1.1.5   root       64: #include <ipc/mach_port.h>
1.1       root       65: #include <machine/machspl.h>           /* for splsched */
1.1.1.4   root       66: #include <machine/pcb.h>
1.1       root       67: #include <machine/thread.h>            /* for MACHINE_STACK */
                     68: 
                     69: thread_t active_threads[NCPUS];
                     70: vm_offset_t active_stacks[NCPUS];
                     71: 
1.1.1.4   root       72: struct kmem_cache thread_cache;
1.1.1.7   root       73: struct kmem_cache thread_stack_cache;
1.1       root       74: 
                     75: queue_head_t           reaper_queue;
                     76: decl_simple_lock_data(,        reaper_lock)
                     77: 
                     78: /* private */
                     79: struct thread  thread_template;
                     80: 
                     81: #if    MACH_DEBUG
                     82: #define        STACK_MARKER    0xdeadbeefU
                     83: boolean_t              stack_check_usage = FALSE;
                     84: decl_simple_lock_data(,        stack_usage_lock)
                     85: vm_size_t              stack_max_usage = 0;
                     86: #endif /* MACH_DEBUG */
                     87: 
                     88: /*
                     89:  *     Machine-dependent code must define:
                     90:  *             pcb_init
                     91:  *             pcb_terminate
                     92:  *             pcb_collect
                     93:  *
                     94:  *     The thread->pcb field is reserved for machine-dependent code.
                     95:  */
                     96: 
                     97: #ifdef MACHINE_STACK
                     98: /*
                     99:  *     Machine-dependent code must define:
                    100:  *             stack_alloc_try
                    101:  *             stack_alloc
                    102:  *             stack_free
                    103:  *             stack_handoff
                    104:  *             stack_collect
                    105:  *     and if MACH_DEBUG:
                    106:  *             stack_statistics
                    107:  */
                    108: #else  /* MACHINE_STACK */
                    109: /*
                    110:  *     We allocate stacks from generic kernel VM.
                    111:  *     Machine-dependent code must define:
                    112:  *             stack_attach
                    113:  *             stack_detach
                    114:  *             stack_handoff
                    115:  *
                    116:  *     The stack_free_list can only be accessed at splsched,
                    117:  *     because stack_alloc_try/thread_invoke operate at splsched.
                    118:  */
                    119: 
                    120: decl_simple_lock_data(, stack_lock_data)/* splsched only */
                    121: #define stack_lock()   simple_lock(&stack_lock_data)
                    122: #define stack_unlock() simple_unlock(&stack_lock_data)
                    123: 
                    124: vm_offset_t stack_free_list;           /* splsched only */
                    125: unsigned int stack_free_count = 0;     /* splsched only */
                    126: unsigned int stack_free_limit = 1;     /* patchable */
                    127: 
                    128: /*
                    129:  *     The next field is at the base of the stack,
                    130:  *     so the low end is left unsullied.
                    131:  */
                    132: 
                    133: #define stack_next(stack) (*((vm_offset_t *)((stack) + KERNEL_STACK_SIZE) - 1))
                    134: 
                    135: /*
                    136:  *     stack_alloc_try:
                    137:  *
                    138:  *     Non-blocking attempt to allocate a kernel stack.
                    139:  *     Called at splsched with the thread locked.
                    140:  */
                    141: 
                    142: boolean_t stack_alloc_try(
                    143:        thread_t        thread,
                    144:        void            (*resume)(thread_t))
                    145: {
1.1.1.5   root      146:        vm_offset_t stack;
1.1       root      147: 
                    148:        stack_lock();
                    149:        stack = stack_free_list;
                    150:        if (stack != 0) {
                    151:                stack_free_list = stack_next(stack);
                    152:                stack_free_count--;
                    153:        } else {
                    154:                stack = thread->stack_privilege;
                    155:        }
                    156:        stack_unlock();
                    157: 
                    158:        if (stack != 0) {
                    159:                stack_attach(thread, stack, resume);
1.1.1.6   root      160:                counter(c_stack_alloc_hits++);
1.1       root      161:                return TRUE;
                    162:        } else {
1.1.1.6   root      163:                counter(c_stack_alloc_misses++);
1.1       root      164:                return FALSE;
                    165:        }
                    166: }
                    167: 
                    168: /*
                    169:  *     stack_alloc:
                    170:  *
                    171:  *     Allocate a kernel stack for a thread.
                    172:  *     May block.
                    173:  */
                    174: 
1.1.1.6   root      175: kern_return_t stack_alloc(
1.1       root      176:        thread_t        thread,
                    177:        void            (*resume)(thread_t))
                    178: {
                    179:        vm_offset_t stack;
                    180:        spl_t s;
                    181: 
                    182:        /*
                    183:         *      We first try the free list.  It is probably empty,
                    184:         *      or stack_alloc_try would have succeeded, but possibly
                    185:         *      a stack was freed before the swapin thread got to us.
                    186:         */
                    187: 
                    188:        s = splsched();
                    189:        stack_lock();
                    190:        stack = stack_free_list;
                    191:        if (stack != 0) {
                    192:                stack_free_list = stack_next(stack);
                    193:                stack_free_count--;
                    194:        }
                    195:        stack_unlock();
                    196:        (void) splx(s);
                    197: 
                    198:        if (stack == 0) {
1.1.1.7   root      199:                stack = kmem_cache_alloc(&thread_stack_cache);
                    200:                assert(stack != 0);
1.1       root      201: #if    MACH_DEBUG
                    202:                stack_init(stack);
                    203: #endif /* MACH_DEBUG */
                    204:        }
                    205: 
                    206:        stack_attach(thread, stack, resume);
1.1.1.6   root      207:        return KERN_SUCCESS;
1.1       root      208: }
                    209: 
                    210: /*
                    211:  *     stack_free:
                    212:  *
                    213:  *     Free a thread's kernel stack.
                    214:  *     Called at splsched with the thread locked.
                    215:  */
                    216: 
                    217: void stack_free(
                    218:        thread_t thread)
                    219: {
1.1.1.5   root      220:        vm_offset_t stack;
1.1       root      221: 
                    222:        stack = stack_detach(thread);
                    223: 
                    224:        if (stack != thread->stack_privilege) {
                    225:                stack_lock();
                    226:                stack_next(stack) = stack_free_list;
                    227:                stack_free_list = stack;
1.1.1.6   root      228:                stack_free_count += 1;
                    229: #if    MACH_COUNTERS
                    230:                if (stack_free_count > c_stack_alloc_max)
                    231:                        c_stack_alloc_max = stack_free_count;
                    232: #endif /* MACH_COUNTERS */
1.1       root      233:                stack_unlock();
                    234:        }
                    235: }
                    236: 
                    237: /*
                    238:  *     stack_collect:
                    239:  *
                    240:  *     Free excess kernel stacks.
                    241:  *     May block.
                    242:  */
                    243: 
                    244: void stack_collect(void)
                    245: {
1.1.1.5   root      246:        vm_offset_t stack;
1.1       root      247:        spl_t s;
                    248: 
                    249:        s = splsched();
                    250:        stack_lock();
                    251:        while (stack_free_count > stack_free_limit) {
                    252:                stack = stack_free_list;
                    253:                stack_free_list = stack_next(stack);
                    254:                stack_free_count--;
                    255:                stack_unlock();
                    256:                (void) splx(s);
                    257: 
                    258: #if    MACH_DEBUG
                    259:                stack_finalize(stack);
                    260: #endif /* MACH_DEBUG */
1.1.1.7   root      261:                kmem_cache_free(&thread_stack_cache, stack);
1.1       root      262: 
                    263:                s = splsched();
                    264:                stack_lock();
                    265:        }
                    266:        stack_unlock();
                    267:        (void) splx(s);
                    268: }
                    269: #endif /* MACHINE_STACK */
                    270: 
                    271: /*
                    272:  *     stack_privilege:
                    273:  *
                    274:  *     stack_alloc_try on this thread must always succeed.
                    275:  */
                    276: 
                    277: void stack_privilege(
1.1.1.5   root      278:        thread_t thread)
1.1       root      279: {
                    280:        /*
                    281:         *      This implementation only works for the current thread.
                    282:         */
                    283: 
                    284:        if (thread != current_thread())
                    285:                panic("stack_privilege");
                    286: 
                    287:        if (thread->stack_privilege == 0)
                    288:                thread->stack_privilege = current_stack();
                    289: }
                    290: 
                    291: void thread_init(void)
                    292: {
1.1.1.4   root      293:        kmem_cache_init(&thread_cache, "thread", sizeof(struct thread), 0,
1.1.1.7   root      294:                        NULL, 0);
                    295:        /*
                    296:         *      Kernel stacks should be naturally aligned,
                    297:         *      so that it is easy to find the starting/ending
                    298:         *      addresses of a stack given an address in the middle.
                    299:         */
                    300:        kmem_cache_init(&thread_stack_cache, "thread_stack",
                    301:                        KERNEL_STACK_SIZE, KERNEL_STACK_SIZE,
                    302:                        NULL, 0);
1.1       root      303: 
                    304:        /*
                    305:         *      Fill in a template thread for fast initialization.
                    306:         *      [Fields that must be (or are typically) reset at
                    307:         *      time of creation are so noted.]
                    308:         */
                    309: 
                    310:        /* thread_template.links (none) */
                    311:        thread_template.runq = RUN_QUEUE_NULL;
                    312: 
                    313:        /* thread_template.task (later) */
                    314:        /* thread_template.thread_list (later) */
                    315:        /* thread_template.pset_threads (later) */
                    316: 
                    317:        /* thread_template.lock (later) */
                    318:        /* one ref for being alive; one for the guy who creates the thread */
                    319:        thread_template.ref_count = 2;
                    320: 
                    321:        thread_template.pcb = (pcb_t) 0;                /* (reset) */
                    322:        thread_template.kernel_stack = (vm_offset_t) 0;
                    323:        thread_template.stack_privilege = (vm_offset_t) 0;
                    324: 
                    325:        thread_template.wait_event = 0;
                    326:        /* thread_template.suspend_count (later) */
                    327:        thread_template.wait_result = KERN_SUCCESS;
                    328:        thread_template.wake_active = FALSE;
                    329:        thread_template.state = TH_SUSP | TH_SWAPPED;
                    330:        thread_template.swap_func = thread_bootstrap_return;
                    331: 
                    332: /*     thread_template.priority (later) */
                    333:        thread_template.max_priority = BASEPRI_USER;
                    334: /*     thread_template.sched_pri (later - compute_priority) */
                    335: #if    MACH_FIXPRI
                    336:        thread_template.sched_data = 0;
                    337:        thread_template.policy = POLICY_TIMESHARE;
                    338: #endif /* MACH_FIXPRI */
                    339:        thread_template.depress_priority = -1;
                    340:        thread_template.cpu_usage = 0;
                    341:        thread_template.sched_usage = 0;
                    342:        /* thread_template.sched_stamp (later) */
                    343: 
                    344:        thread_template.recover = (vm_offset_t) 0;
1.1.1.8 ! root      345:        thread_template.vm_privilege = 0;
1.1       root      346: 
                    347:        thread_template.user_stop_count = 1;
                    348: 
                    349:        /* thread_template.<IPC structures> (later) */
                    350: 
                    351:        timer_init(&(thread_template.user_timer));
                    352:        timer_init(&(thread_template.system_timer));
                    353:        thread_template.user_timer_save.low = 0;
                    354:        thread_template.user_timer_save.high = 0;
                    355:        thread_template.system_timer_save.low = 0;
                    356:        thread_template.system_timer_save.high = 0;
                    357:        thread_template.cpu_delta = 0;
                    358:        thread_template.sched_delta = 0;
                    359: 
                    360:        thread_template.active = FALSE; /* reset */
                    361:        thread_template.ast = AST_ZILCH;
                    362: 
                    363:        /* thread_template.processor_set (later) */
                    364:        thread_template.bound_processor = PROCESSOR_NULL;
                    365: #if    MACH_HOST
                    366:        thread_template.may_assign = TRUE;
                    367:        thread_template.assign_active = FALSE;
                    368: #endif /* MACH_HOST */
                    369: 
                    370: #if    NCPUS > 1
                    371:        /* thread_template.last_processor  (later) */
                    372: #endif /* NCPUS > 1 */
                    373: 
                    374:        /*
                    375:         *      Initialize other data structures used in
                    376:         *      this module.
                    377:         */
                    378: 
                    379:        queue_init(&reaper_queue);
                    380:        simple_lock_init(&reaper_lock);
                    381: 
                    382: #ifndef        MACHINE_STACK
                    383:        simple_lock_init(&stack_lock_data);
                    384: #endif /* MACHINE_STACK */
                    385: 
                    386: #if    MACH_DEBUG
                    387:        simple_lock_init(&stack_usage_lock);
                    388: #endif /* MACH_DEBUG */
                    389: 
                    390:        /*
                    391:         *      Initialize any machine-dependent
                    392:         *      per-thread structures necessary.
                    393:         */
                    394: 
                    395:        pcb_module_init();
                    396: }
                    397: 
                    398: kern_return_t thread_create(
1.1.1.5   root      399:        task_t  parent_task,
1.1       root      400:        thread_t        *child_thread)          /* OUT */
                    401: {
1.1.1.5   root      402:        thread_t        new_thread;
                    403:        processor_set_t pset;
1.1       root      404: 
                    405:        if (parent_task == TASK_NULL)
                    406:                return KERN_INVALID_ARGUMENT;
                    407: 
                    408:        /*
                    409:         *      Allocate a thread and initialize static fields
                    410:         */
                    411: 
1.1.1.4   root      412:        new_thread = (thread_t) kmem_cache_alloc(&thread_cache);
1.1       root      413: 
                    414:        if (new_thread == THREAD_NULL)
                    415:                return KERN_RESOURCE_SHORTAGE;
                    416: 
                    417:        *new_thread = thread_template;
                    418: 
1.1.1.3   root      419:        record_time_stamp (&new_thread->creation_time);
                    420: 
1.1       root      421:        /*
                    422:         *      Initialize runtime-dependent fields
                    423:         */
                    424: 
                    425:        new_thread->task = parent_task;
                    426:        simple_lock_init(&new_thread->lock);
                    427:        new_thread->sched_stamp = sched_tick;
                    428:        thread_timeout_setup(new_thread);
                    429: 
                    430:        /*
                    431:         *      Create a pcb.  The kernel stack is created later,
                    432:         *      when the thread is swapped-in.
                    433:         */
1.1.1.7   root      434:        pcb_init(parent_task, new_thread);
1.1       root      435: 
                    436:        ipc_thread_init(new_thread);
                    437: 
                    438:        /*
                    439:         *      Find the processor set for the parent task.
                    440:         */
                    441:        task_lock(parent_task);
                    442:        pset = parent_task->processor_set;
                    443:        pset_reference(pset);
                    444:        task_unlock(parent_task);
                    445: 
                    446:        /*
                    447:         *      Lock both the processor set and the task,
                    448:         *      so that the thread can be added to both
                    449:         *      simultaneously.  Processor set must be
                    450:         *      locked first.
                    451:         */
                    452: 
                    453:     Restart:
                    454:        pset_lock(pset);
                    455:        task_lock(parent_task);
                    456: 
                    457:        /*
                    458:         *      If the task has changed processor sets,
                    459:         *      catch up (involves lots of lock juggling).
                    460:         */
                    461:        {
                    462:            processor_set_t     cur_pset;
                    463: 
                    464:            cur_pset = parent_task->processor_set;
                    465:            if (!cur_pset->active)
                    466:                cur_pset = &default_pset;
                    467: 
                    468:            if (cur_pset != pset) {
                    469:                pset_reference(cur_pset);
                    470:                task_unlock(parent_task);
                    471:                pset_unlock(pset);
                    472:                pset_deallocate(pset);
                    473:                pset = cur_pset;
                    474:                goto Restart;
                    475:            }
                    476:        }
                    477: 
                    478:        /*
                    479:         *      Set the thread`s priority from the pset and task.
                    480:         */
                    481: 
                    482:        new_thread->priority = parent_task->priority;
                    483:        if (pset->max_priority > new_thread->max_priority)
                    484:                new_thread->max_priority = pset->max_priority;
                    485:        if (new_thread->max_priority > new_thread->priority)
                    486:                new_thread->priority = new_thread->max_priority;
                    487:        /*
                    488:         *      Don't need to lock thread here because it can't
                    489:         *      possibly execute and no one else knows about it.
                    490:         */
                    491:        compute_priority(new_thread, TRUE);
                    492: 
                    493:        /*
                    494:         *      Thread is suspended if the task is.  Add 1 to
                    495:         *      suspend count since thread is created in suspended
                    496:         *      state.
                    497:         */
                    498:        new_thread->suspend_count = parent_task->suspend_count + 1;
                    499: 
                    500:        /*
                    501:         *      Add the thread to the processor set.
                    502:         *      If the pset is empty, suspend the thread again.
                    503:         */
                    504: 
                    505:        pset_add_thread(pset, new_thread);
                    506:        if (pset->empty)
                    507:                new_thread->suspend_count++;
                    508: 
                    509: #if    HW_FOOTPRINT
                    510:        /*
                    511:         *      Need to set last_processor, idle processor would be best, but
                    512:         *      that requires extra locking nonsense.  Go for tail of
                    513:         *      processors queue to avoid master.
                    514:         */
                    515:        if (!pset->empty) {
                    516:                new_thread->last_processor = 
                    517:                        (processor_t)queue_first(&pset->processors);
                    518:        }
                    519:        else {
                    520:                /*
                    521:                 *      Thread created in empty processor set.  Pick
                    522:                 *      master processor as an acceptable legal value.
                    523:                 */
                    524:                new_thread->last_processor = master_processor;
                    525:        }
                    526: #else  /* HW_FOOTPRINT */
                    527:        /*
                    528:         *      Don't need to initialize because the context switch
                    529:         *      code will set it before it can be used.
                    530:         */
                    531: #endif /* HW_FOOTPRINT */
                    532: 
                    533: #if    MACH_PCSAMPLE
                    534:        new_thread->pc_sample.seqno = 0;
                    535:        new_thread->pc_sample.sampletypes = 0;
                    536: #endif /* MACH_PCSAMPLE */
                    537: 
                    538:        new_thread->pc_sample.buffer = 0;
                    539:        /*
                    540:         *      Add the thread to the task`s list of threads.
                    541:         *      The new thread holds another reference to the task.
                    542:         */
                    543: 
                    544:        parent_task->ref_count++;
                    545: 
                    546:        parent_task->thread_count++;
                    547:        queue_enter(&parent_task->thread_list, new_thread, thread_t,
                    548:                                        thread_list);
                    549: 
                    550:        /*
                    551:         *      Finally, mark the thread active.
                    552:         */
                    553: 
                    554:        new_thread->active = TRUE;
                    555: 
                    556:        if (!parent_task->active) {
                    557:                task_unlock(parent_task);
                    558:                pset_unlock(pset);
                    559:                (void) thread_terminate(new_thread);
                    560:                /* release ref we would have given our caller */
                    561:                thread_deallocate(new_thread);
                    562:                return KERN_FAILURE;
                    563:        }
                    564:        task_unlock(parent_task);
                    565:        pset_unlock(pset);
                    566: 
                    567:        ipc_thread_enable(new_thread);
                    568: 
                    569:        *child_thread = new_thread;
                    570:        return KERN_SUCCESS;
                    571: }
                    572: 
                    573: unsigned int thread_deallocate_stack = 0;
                    574: 
                    575: void thread_deallocate(
1.1.1.5   root      576:        thread_t        thread)
1.1       root      577: {
                    578:        spl_t           s;
1.1.1.5   root      579:        task_t          task;
                    580:        processor_set_t pset;
1.1       root      581: 
                    582:        time_value_t    user_time, system_time;
                    583: 
                    584:        if (thread == THREAD_NULL)
                    585:                return;
                    586: 
                    587:        /*
                    588:         *      First, check for new count > 0 (the common case).
                    589:         *      Only the thread needs to be locked.
                    590:         */
                    591:        s = splsched();
                    592:        thread_lock(thread);
                    593:        if (--thread->ref_count > 0) {
                    594:                thread_unlock(thread);
                    595:                (void) splx(s);
                    596:                return;
                    597:        }
                    598: 
                    599:        /*
                    600:         *      Count is zero.  However, the task's and processor set's
                    601:         *      thread lists have implicit references to
                    602:         *      the thread, and may make new ones.  Their locks also
                    603:         *      dominate the thread lock.  To check for this, we
                    604:         *      temporarily restore the one thread reference, unlock
                    605:         *      the thread, and then lock the other structures in
                    606:         *      the proper order.
                    607:         */
                    608:        thread->ref_count = 1;
                    609:        thread_unlock(thread);
                    610:        (void) splx(s);
                    611: 
                    612:        pset = thread->processor_set;
                    613:        pset_lock(pset);
                    614: 
                    615: #if    MACH_HOST
                    616:        /*
                    617:         *      The thread might have moved.
                    618:         */
                    619:        while (pset != thread->processor_set) {
                    620:            pset_unlock(pset);
                    621:            pset = thread->processor_set;
                    622:            pset_lock(pset);
                    623:        }
                    624: #endif /* MACH_HOST */
                    625: 
                    626:        task = thread->task;
                    627:        task_lock(task);
                    628: 
                    629:        s = splsched();
                    630:        thread_lock(thread);
                    631: 
                    632:        if (--thread->ref_count > 0) {
                    633:                /*
                    634:                 *      Task or processor_set made extra reference.
                    635:                 */
                    636:                thread_unlock(thread);
                    637:                (void) splx(s);
                    638:                task_unlock(task);
                    639:                pset_unlock(pset);
                    640:                return;
                    641:        }
                    642: 
                    643:        /*
                    644:         *      Thread has no references - we can remove it.
                    645:         */
                    646: 
                    647:        /*
                    648:         *      Remove pending timeouts.
                    649:         */
                    650:        reset_timeout_check(&thread->timer);
                    651: 
                    652:        reset_timeout_check(&thread->depress_timer);
                    653:        thread->depress_priority = -1;
                    654: 
                    655:        /*
                    656:         *      Accumulate times for dead threads in task.
                    657:         */
                    658:        thread_read_times(thread, &user_time, &system_time);
                    659:        time_value_add(&task->total_user_time, &user_time);
                    660:        time_value_add(&task->total_system_time, &system_time);
                    661: 
                    662:        /*
                    663:         *      Remove thread from task list and processor_set threads list.
                    664:         */
                    665:        task->thread_count--;
                    666:        queue_remove(&task->thread_list, thread, thread_t, thread_list);
                    667: 
                    668:        pset_remove_thread(pset, thread);
                    669: 
                    670:        thread_unlock(thread);          /* no more references - safe */
                    671:        (void) splx(s);
                    672:        task_unlock(task);
                    673:        pset_unlock(pset);
                    674:        pset_deallocate(pset);
                    675: 
                    676:        /*
                    677:         *      A couple of quick sanity checks
                    678:         */
                    679: 
                    680:        if (thread == current_thread()) {
                    681:            panic("thread deallocating itself");
                    682:        }
                    683:        if ((thread->state & ~(TH_RUN | TH_HALTED | TH_SWAPPED)) != TH_SUSP)
                    684:                panic("unstopped thread destroyed!");
                    685: 
                    686:        /*
                    687:         *      Deallocate the task reference, since we know the thread
                    688:         *      is not running.
                    689:         */
                    690:        task_deallocate(thread->task);                  /* may block */
                    691: 
                    692:        /*
                    693:         *      Clean up any machine-dependent resources.
                    694:         */
                    695:        if ((thread->state & TH_SWAPPED) == 0) {
1.1.1.4   root      696:                splsched();
1.1       root      697:                stack_free(thread);
                    698:                (void) splx(s);
                    699:                thread_deallocate_stack++;
                    700:        }
                    701:        /*
                    702:         * Rattle the event count machinery (gag)
                    703:         */
                    704:        evc_notify_abort(thread);
                    705: 
                    706:        pcb_terminate(thread);
1.1.1.4   root      707:        kmem_cache_free(&thread_cache, (vm_offset_t) thread);
1.1       root      708: }
                    709: 
                    710: void thread_reference(
1.1.1.5   root      711:        thread_t        thread)
1.1       root      712: {
                    713:        spl_t           s;
                    714: 
                    715:        if (thread == THREAD_NULL)
                    716:                return;
                    717: 
                    718:        s = splsched();
                    719:        thread_lock(thread);
                    720:        thread->ref_count++;
                    721:        thread_unlock(thread);
                    722:        (void) splx(s);
                    723: }
                    724: 
                    725: /*
                    726:  *     thread_terminate:
                    727:  *
                    728:  *     Permanently stop execution of the specified thread.
                    729:  *
                    730:  *     A thread to be terminated must be allowed to clean up any state
                    731:  *     that it has before it exits.  The thread is broken out of any
                    732:  *     wait condition that it is in, and signalled to exit.  It then
                    733:  *     cleans up its state and calls thread_halt_self on its way out of
                    734:  *     the kernel.  The caller waits for the thread to halt, terminates
                    735:  *     its IPC state, and then deallocates it.
                    736:  *
                    737:  *     If the caller is the current thread, it must still exit the kernel
                    738:  *     to clean up any state (thread and port references, messages, etc).
                    739:  *     When it exits the kernel, it then terminates its IPC state and
                    740:  *     queues itself for the reaper thread, which will wait for the thread
                    741:  *     to stop and then deallocate it.  (A thread cannot deallocate itself,
                    742:  *     since it needs a kernel stack to execute.)
                    743:  */
                    744: kern_return_t thread_terminate(
1.1.1.5   root      745:        thread_t        thread)
1.1       root      746: {
1.1.1.5   root      747:        thread_t                cur_thread = current_thread();
                    748:        task_t                  cur_task;
1.1       root      749:        spl_t                   s;
                    750: 
                    751:        if (thread == THREAD_NULL)
                    752:                return KERN_INVALID_ARGUMENT;
                    753: 
                    754:        /*
                    755:         *      Break IPC control over the thread.
                    756:         */
                    757:        ipc_thread_disable(thread);
                    758: 
                    759:        if (thread == cur_thread) {
                    760: 
                    761:            /*
                    762:             *  Current thread will queue itself for reaper when
                    763:             *  exiting kernel.
                    764:             */
                    765:            s = splsched();
                    766:            thread_lock(thread);
                    767:            if (thread->active) {
                    768:                    thread->active = FALSE;
                    769:                    thread_ast_set(thread, AST_TERMINATE);
                    770:            }
                    771:            thread_unlock(thread);
                    772:            ast_on(cpu_number(), AST_TERMINATE);
                    773:            splx(s);
                    774:            return KERN_SUCCESS;
                    775:        }
                    776: 
                    777:        /*
                    778:         *      Lock both threads and the current task
                    779:         *      to check termination races and prevent deadlocks.
                    780:         */
                    781:        cur_task = current_task();
                    782:        task_lock(cur_task);
                    783:        s = splsched();
                    784:        if ((vm_offset_t)thread < (vm_offset_t)cur_thread) {
                    785:                thread_lock(thread);
                    786:                thread_lock(cur_thread);
                    787:        }
                    788:        else {
                    789:                thread_lock(cur_thread);
                    790:                thread_lock(thread);
                    791:        }
                    792: 
                    793:        /*
                    794:         *      If the current thread is being terminated, help out.
                    795:         */
                    796:        if ((!cur_task->active) || (!cur_thread->active)) {
                    797:                thread_unlock(cur_thread);
                    798:                thread_unlock(thread);
                    799:                (void) splx(s);
                    800:                task_unlock(cur_task);
                    801:                thread_terminate(cur_thread);
                    802:                return KERN_FAILURE;
                    803:        }
                    804:     
                    805:        thread_unlock(cur_thread);
                    806:        task_unlock(cur_task);
                    807: 
                    808:        /*
                    809:         *      Terminate victim thread.
                    810:         */
                    811:        if (!thread->active) {
                    812:                /*
                    813:                 *      Someone else got there first.
                    814:                 */
                    815:                thread_unlock(thread);
                    816:                (void) splx(s);
                    817:                return KERN_FAILURE;
                    818:        }
                    819: 
                    820:        thread->active = FALSE;
                    821: 
                    822:        thread_unlock(thread);
                    823:        (void) splx(s);
                    824: 
                    825: #if    MACH_HOST
                    826:        /*
                    827:         *      Reassign thread to default pset if needed.
                    828:         */
                    829:        thread_freeze(thread);
                    830:        if (thread->processor_set != &default_pset) {
                    831:                thread_doassign(thread, &default_pset, FALSE);
                    832:        }
                    833: #endif /* MACH_HOST */
                    834: 
                    835:        /*
                    836:         *      Halt the victim at the clean point.
                    837:         */
                    838:        (void) thread_halt(thread, TRUE);
                    839: #if    MACH_HOST
                    840:        thread_unfreeze(thread);
                    841: #endif /* MACH_HOST */
                    842:        /*
                    843:         *      Shut down the victims IPC and deallocate its
                    844:         *      reference to itself.
                    845:         */
                    846:        ipc_thread_terminate(thread);
                    847:        thread_deallocate(thread);
                    848:        return KERN_SUCCESS;
                    849: }
                    850: 
1.1.1.5   root      851: kern_return_t thread_terminate_release(
                    852:        thread_t thread,
                    853:        task_t task,
                    854:        mach_port_t thread_name,
                    855:        mach_port_t reply_port,
                    856:        vm_offset_t address,
                    857:        vm_size_t size)
                    858: {
                    859:        if (task == NULL)
                    860:                return KERN_INVALID_ARGUMENT;
                    861: 
                    862:        mach_port_deallocate(task->itk_space, thread_name);
                    863: 
                    864:        if (reply_port != MACH_PORT_NULL)
                    865:                mach_port_destroy(task->itk_space, reply_port);
                    866: 
                    867:        if ((address != 0) || (size != 0))
                    868:                vm_deallocate(task->map, address, size);
                    869: 
                    870:        return thread_terminate(thread);
                    871: }
                    872: 
1.1       root      873: /*
                    874:  *     thread_force_terminate:
                    875:  *
                    876:  *     Version of thread_terminate called by task_terminate.  thread is
                    877:  *     not the current thread.  task_terminate is the dominant operation,
                    878:  *     so we can force this thread to stop.
                    879:  */
                    880: void
                    881: thread_force_terminate(
1.1.1.5   root      882:        thread_t        thread)
1.1       root      883: {
1.1.1.4   root      884:        boolean_t       deallocate_here;
1.1       root      885:        spl_t s;
                    886: 
                    887:        ipc_thread_disable(thread);
                    888: 
                    889: #if    MACH_HOST
                    890:        /*
                    891:         *      Reassign thread to default pset if needed.
                    892:         */
                    893:        thread_freeze(thread);
                    894:        if (thread->processor_set != &default_pset)
                    895:                thread_doassign(thread, &default_pset, FALSE);
                    896: #endif /* MACH_HOST */
                    897: 
                    898:        s = splsched();
                    899:        thread_lock(thread);
                    900:        deallocate_here = thread->active;
                    901:        thread->active = FALSE;
                    902:        thread_unlock(thread);
                    903:        (void) splx(s);
                    904: 
                    905:        (void) thread_halt(thread, TRUE);
                    906:        ipc_thread_terminate(thread);
                    907: 
                    908: #if    MACH_HOST
                    909:        thread_unfreeze(thread);
                    910: #endif /* MACH_HOST */
                    911: 
                    912:        if (deallocate_here)
                    913:                thread_deallocate(thread);
                    914: }
                    915: 
                    916: 
                    917: /*
                    918:  *     Halt a thread at a clean point, leaving it suspended.
                    919:  *
                    920:  *     must_halt indicates whether thread must halt.
                    921:  *
                    922:  */
                    923: kern_return_t thread_halt(
1.1.1.5   root      924:        thread_t        thread,
1.1       root      925:        boolean_t               must_halt)
                    926: {
1.1.1.5   root      927:        thread_t        cur_thread = current_thread();
                    928:        kern_return_t   ret;
1.1       root      929:        spl_t   s;
                    930: 
                    931:        if (thread == cur_thread)
                    932:                panic("thread_halt: trying to halt current thread.");
                    933:        /*
                    934:         *      If must_halt is FALSE, then a check must be made for
                    935:         *      a cycle of halt operations.
                    936:         */
                    937:        if (!must_halt) {
                    938:                /*
                    939:                 *      Grab both thread locks.
                    940:                 */
                    941:                s = splsched();
                    942:                if ((vm_offset_t)thread < (vm_offset_t)cur_thread) {
                    943:                        thread_lock(thread);
                    944:                        thread_lock(cur_thread);
                    945:                }
                    946:                else {
                    947:                        thread_lock(cur_thread);
                    948:                        thread_lock(thread);
                    949:                }
                    950: 
                    951:                /*
                    952:                 *      If target thread is already halted, grab a hold
                    953:                 *      on it and return.
                    954:                 */
                    955:                if (thread->state & TH_HALTED) {
                    956:                        thread->suspend_count++;
                    957:                        thread_unlock(cur_thread);
                    958:                        thread_unlock(thread);
                    959:                        (void) splx(s);
                    960:                        return KERN_SUCCESS;
                    961:                }
                    962: 
                    963:                /*
                    964:                 *      If someone is trying to halt us, we have a potential
                    965:                 *      halt cycle.  Break the cycle by interrupting anyone
                    966:                 *      who is trying to halt us, and causing this operation
                    967:                 *      to fail; retry logic will only retry operations
                    968:                 *      that cannot deadlock.  (If must_halt is TRUE, this
                    969:                 *      operation can never cause a deadlock.)
                    970:                 */
                    971:                if (cur_thread->ast & AST_HALT) {
1.1.1.5   root      972:                        thread_wakeup_with_result(TH_EV_WAKE_ACTIVE(cur_thread),
1.1       root      973:                                THREAD_INTERRUPTED);
                    974:                        thread_unlock(thread);
                    975:                        thread_unlock(cur_thread);
                    976:                        (void) splx(s);
                    977:                        return KERN_FAILURE;
                    978:                }
                    979: 
                    980:                thread_unlock(cur_thread);
                    981:        
                    982:        }
                    983:        else {
                    984:                /*
                    985:                 *      Lock thread and check whether it is already halted.
                    986:                 */
                    987:                s = splsched();
                    988:                thread_lock(thread);
                    989:                if (thread->state & TH_HALTED) {
                    990:                        thread->suspend_count++;
                    991:                        thread_unlock(thread);
                    992:                        (void) splx(s);
                    993:                        return KERN_SUCCESS;
                    994:                }
                    995:        }
                    996: 
                    997:        /*
                    998:         *      Suspend thread - inline version of thread_hold() because
                    999:         *      thread is already locked.
                   1000:         */
                   1001:        thread->suspend_count++;
                   1002:        thread->state |= TH_SUSP;
                   1003: 
                   1004:        /*
                   1005:         *      If someone else is halting it, wait for that to complete.
                   1006:         *      Fail if wait interrupted and must_halt is false.
                   1007:         */
                   1008:        while ((thread->ast & AST_HALT) && (!(thread->state & TH_HALTED))) {
                   1009:                thread->wake_active = TRUE;
1.1.1.5   root     1010:                thread_sleep(TH_EV_WAKE_ACTIVE(thread),
1.1       root     1011:                        simple_lock_addr(thread->lock), TRUE);
                   1012: 
                   1013:                if (thread->state & TH_HALTED) {
                   1014:                        (void) splx(s);
                   1015:                        return KERN_SUCCESS;
                   1016:                }
                   1017:                if ((current_thread()->wait_result != THREAD_AWAKENED)
                   1018:                    && !(must_halt)) {
                   1019:                        (void) splx(s);
                   1020:                        thread_release(thread);
                   1021:                        return KERN_FAILURE;
                   1022:                }
                   1023:                thread_lock(thread);
                   1024:        }
                   1025: 
                   1026:        /*
                   1027:         *      Otherwise, have to do it ourselves.
                   1028:         */
                   1029:                
                   1030:        thread_ast_set(thread, AST_HALT);
                   1031: 
                   1032:        while (TRUE) {
                   1033:                /*
                   1034:                 *      Wait for thread to stop.
                   1035:                 */
                   1036:                thread_unlock(thread);
                   1037:                (void) splx(s);
                   1038: 
                   1039:                ret = thread_dowait(thread, must_halt);
                   1040: 
                   1041:                /*
                   1042:                 *      If the dowait failed, so do we.  Drop AST_HALT, and
                   1043:                 *      wake up anyone else who might be waiting for it.
                   1044:                 */
                   1045:                if (ret != KERN_SUCCESS) {
                   1046:                        s = splsched();
                   1047:                        thread_lock(thread);
                   1048:                        thread_ast_clear(thread, AST_HALT);
1.1.1.5   root     1049:                        thread_wakeup_with_result(TH_EV_WAKE_ACTIVE(thread),
1.1       root     1050:                                THREAD_INTERRUPTED);
                   1051:                        thread_unlock(thread);
                   1052:                        (void) splx(s);
                   1053: 
                   1054:                        thread_release(thread);
                   1055:                        return ret;
                   1056:                }
                   1057: 
                   1058:                /*
                   1059:                 *      Clear any interruptible wait.
                   1060:                 */
                   1061:                clear_wait(thread, THREAD_INTERRUPTED, TRUE);
                   1062: 
                   1063:                /*
                   1064:                 *      If the thread's at a clean point, we're done.
                   1065:                 *      Don't need a lock because it really is stopped.
                   1066:                 */
                   1067:                if (thread->state & TH_HALTED) {
                   1068:                        return KERN_SUCCESS;
                   1069:                }
                   1070: 
                   1071:                /*
                   1072:                 *      If the thread is at a nice continuation,
                   1073:                 *      or a continuation with a cleanup routine,
                   1074:                 *      call the cleanup routine.
                   1075:                 */
                   1076:                if ((((thread->swap_func == mach_msg_continue) ||
                   1077:                      (thread->swap_func == mach_msg_receive_continue)) &&
                   1078:                     mach_msg_interrupt(thread)) ||
                   1079:                    (thread->swap_func == thread_exception_return) ||
                   1080:                    (thread->swap_func == thread_bootstrap_return)) {
                   1081:                        s = splsched();
                   1082:                        thread_lock(thread);
                   1083:                        thread->state |= TH_HALTED;
                   1084:                        thread_ast_clear(thread, AST_HALT);
                   1085:                        thread_unlock(thread);
                   1086:                        splx(s);
                   1087: 
                   1088:                        return KERN_SUCCESS;
                   1089:                }
                   1090: 
                   1091:                /*
                   1092:                 *      Force the thread to stop at a clean
                   1093:                 *      point, and arrange to wait for it.
                   1094:                 *
                   1095:                 *      Set it running, so it can notice.  Override
                   1096:                 *      the suspend count.  We know that the thread
                   1097:                 *      is suspended and not waiting.
                   1098:                 *
                   1099:                 *      Since the thread may hit an interruptible wait
                   1100:                 *      before it reaches a clean point, we must force it
                   1101:                 *      to wake us up when it does so.  This involves some
                   1102:                 *      trickery:
                   1103:                 *        We mark the thread SUSPENDED so that thread_block
                   1104:                 *      will suspend it and wake us up.
                   1105:                 *        We mark the thread RUNNING so that it will run.
                   1106:                 *        We mark the thread UN-INTERRUPTIBLE (!) so that
                   1107:                 *      some other thread trying to halt or suspend it won't
                   1108:                 *      take it off the run queue before it runs.  Since
                   1109:                 *      dispatching a thread (the tail of thread_invoke) marks
                   1110:                 *      the thread interruptible, it will stop at the next
                   1111:                 *      context switch or interruptible wait.
                   1112:                 */
                   1113: 
                   1114:                s = splsched();
                   1115:                thread_lock(thread);
                   1116:                if ((thread->state & TH_SCHED_STATE) != TH_SUSP)
                   1117:                        panic("thread_halt");
                   1118:                thread->state |= TH_RUN | TH_UNINT;
                   1119:                thread_setrun(thread, FALSE);
                   1120: 
                   1121:                /*
                   1122:                 *      Continue loop and wait for thread to stop.
                   1123:                 */
                   1124:        }
                   1125: }
                   1126: 
1.1.1.5   root     1127: void __attribute__((noreturn)) walking_zombie(void)
1.1       root     1128: {
                   1129:        panic("the zombie walks!");
                   1130: }
                   1131: 
                   1132: /*
                   1133:  *     Thread calls this routine on exit from the kernel when it
                   1134:  *     notices a halt request.
                   1135:  */
1.1.1.6   root     1136: void   thread_halt_self(continuation_t continuation)
1.1       root     1137: {
1.1.1.5   root     1138:        thread_t        thread = current_thread();
1.1       root     1139:        spl_t   s;
                   1140: 
                   1141:        if (thread->ast & AST_TERMINATE) {
                   1142:                /*
                   1143:                 *      Thread is terminating itself.  Shut
                   1144:                 *      down IPC, then queue it up for the
                   1145:                 *      reaper thread.
                   1146:                 */
                   1147:                ipc_thread_terminate(thread);
                   1148: 
                   1149:                thread_hold(thread);
                   1150: 
                   1151:                s = splsched();
                   1152:                simple_lock(&reaper_lock);
1.1.1.5   root     1153:                enqueue_tail(&reaper_queue, &(thread->links));
1.1       root     1154:                simple_unlock(&reaper_lock);
                   1155: 
                   1156:                thread_lock(thread);
                   1157:                thread->state |= TH_HALTED;
                   1158:                thread_unlock(thread);
                   1159:                (void) splx(s);
                   1160: 
                   1161:                thread_wakeup((event_t)&reaper_queue);
                   1162:                counter(c_thread_halt_self_block++);
                   1163:                thread_block(walking_zombie);
                   1164:                /*NOTREACHED*/
                   1165:        } else {
                   1166:                /*
                   1167:                 *      Thread was asked to halt - show that it
                   1168:                 *      has done so.
                   1169:                 */
                   1170:                s = splsched();
                   1171:                thread_lock(thread);
                   1172:                thread->state |= TH_HALTED;
                   1173:                thread_ast_clear(thread, AST_HALT);
                   1174:                thread_unlock(thread);
                   1175:                splx(s);
                   1176:                counter(c_thread_halt_self_block++);
1.1.1.6   root     1177:                thread_block(continuation);
1.1       root     1178:                /*
                   1179:                 *      thread_release resets TH_HALTED.
                   1180:                 */
                   1181:        }
                   1182: }
                   1183: 
                   1184: /*
                   1185:  *     thread_hold:
                   1186:  *
                   1187:  *     Suspend execution of the specified thread.
                   1188:  *     This is a recursive-style suspension of the thread, a count of
                   1189:  *     suspends is maintained.
                   1190:  */
                   1191: void thread_hold(
1.1.1.5   root     1192:        thread_t        thread)
1.1       root     1193: {
                   1194:        spl_t                   s;
                   1195: 
                   1196:        s = splsched();
                   1197:        thread_lock(thread);
                   1198:        thread->suspend_count++;
                   1199:        thread->state |= TH_SUSP;
                   1200:        thread_unlock(thread);
                   1201:        (void) splx(s);
                   1202: }
                   1203: 
                   1204: /*
                   1205:  *     thread_dowait:
                   1206:  *
                   1207:  *     Wait for a thread to actually enter stopped state.
                   1208:  *
                   1209:  *     must_halt argument indicates if this may fail on interruption.
                   1210:  *     This is FALSE only if called from thread_abort via thread_halt.
                   1211:  */
                   1212: kern_return_t
                   1213: thread_dowait(
1.1.1.5   root     1214:        thread_t                thread,
1.1       root     1215:        boolean_t               must_halt)
                   1216: {
1.1.1.5   root     1217:        boolean_t               need_wakeup;
                   1218:        kern_return_t           ret = KERN_SUCCESS;
1.1       root     1219:        spl_t                   s;
                   1220: 
                   1221:        if (thread == current_thread())
                   1222:                panic("thread_dowait");
                   1223: 
                   1224:        /*
                   1225:         *      If a thread is not interruptible, it may not be suspended
                   1226:         *      until it becomes interruptible.  In this case, we wait for
                   1227:         *      the thread to stop itself, and indicate that we are waiting
                   1228:         *      for it to stop so that it can wake us up when it does stop.
                   1229:         *
                   1230:         *      If the thread is interruptible, we may be able to suspend
                   1231:         *      it immediately.  There are several cases:
                   1232:         *
                   1233:         *      1) The thread is already stopped (trivial)
                   1234:         *      2) The thread is runnable (marked RUN and on a run queue).
                   1235:         *         We pull it off the run queue and mark it stopped.
                   1236:         *      3) The thread is running.  We wait for it to stop.
                   1237:         */
                   1238: 
                   1239:        need_wakeup = FALSE;
                   1240:        s = splsched();
                   1241:        thread_lock(thread);
                   1242: 
                   1243:        for (;;) {
                   1244:            switch (thread->state & TH_SCHED_STATE) {
                   1245:                case                    TH_SUSP:
                   1246:                case          TH_WAIT | TH_SUSP:
                   1247:                    /*
                   1248:                     *  Thread is already suspended, or sleeping in an
                   1249:                     *  interruptible wait.  We win!
                   1250:                     */
                   1251:                    break;
                   1252: 
                   1253:                case TH_RUN           | TH_SUSP:
                   1254:                    /*
                   1255:                     *  The thread is interruptible.  If we can pull
                   1256:                     *  it off a runq, stop it here.
                   1257:                     */
                   1258:                    if (rem_runq(thread) != RUN_QUEUE_NULL) {
                   1259:                        thread->state &= ~TH_RUN;
                   1260:                        need_wakeup = thread->wake_active;
                   1261:                        thread->wake_active = FALSE;
                   1262:                        break;
                   1263:                    }
                   1264: #if    NCPUS > 1
                   1265:                    /*
                   1266:                     *  The thread must be running, so make its
                   1267:                     *  processor execute ast_check().  This
                   1268:                     *  should cause the thread to take an ast and
                   1269:                     *  context switch to suspend for us.
                   1270:                     */
                   1271:                    cause_ast_check(thread->last_processor);
                   1272: #endif /* NCPUS > 1 */
                   1273: 
                   1274:                    /*
                   1275:                     *  Fall through to wait for thread to stop.
                   1276:                     */
                   1277: 
                   1278:                case TH_RUN           | TH_SUSP | TH_UNINT:
                   1279:                case TH_RUN | TH_WAIT | TH_SUSP:
                   1280:                case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
                   1281:                case          TH_WAIT | TH_SUSP | TH_UNINT:
                   1282:                    /*
                   1283:                     *  Wait for the thread to stop, or sleep interruptibly
                   1284:                     *  (thread_block will stop it in the latter case).
                   1285:                     *  Check for failure if interrupted.
                   1286:                     */
                   1287:                    thread->wake_active = TRUE;
1.1.1.5   root     1288:                    thread_sleep(TH_EV_WAKE_ACTIVE(thread),
1.1       root     1289:                                simple_lock_addr(thread->lock), TRUE);
                   1290:                    thread_lock(thread);
                   1291:                    if ((current_thread()->wait_result != THREAD_AWAKENED) &&
                   1292:                            !must_halt) {
                   1293:                        ret = KERN_FAILURE;
                   1294:                        break;
                   1295:                    }
                   1296: 
                   1297:                    /*
                   1298:                     *  Repeat loop to check thread`s state.
                   1299:                     */
                   1300:                    continue;
                   1301:            }
                   1302:            /*
                   1303:             *  Thread is stopped at this point.
                   1304:             */
                   1305:            break;
                   1306:        }
                   1307: 
                   1308:        thread_unlock(thread);
                   1309:        (void) splx(s);
                   1310: 
                   1311:        if (need_wakeup)
1.1.1.5   root     1312:            thread_wakeup(TH_EV_WAKE_ACTIVE(thread));
1.1       root     1313: 
                   1314:        return ret;
                   1315: }
                   1316: 
                   1317: void thread_release(
1.1.1.5   root     1318:        thread_t        thread)
1.1       root     1319: {
                   1320:        spl_t                   s;
                   1321: 
                   1322:        s = splsched();
                   1323:        thread_lock(thread);
                   1324:        if (--thread->suspend_count == 0) {
                   1325:                thread->state &= ~(TH_SUSP | TH_HALTED);
                   1326:                if ((thread->state & (TH_WAIT | TH_RUN)) == 0) {
                   1327:                        /* was only suspended */
                   1328:                        thread->state |= TH_RUN;
                   1329:                        thread_setrun(thread, TRUE);
                   1330:                }
                   1331:        }
                   1332:        thread_unlock(thread);
                   1333:        (void) splx(s);
                   1334: }
                   1335: 
                   1336: kern_return_t thread_suspend(
1.1.1.5   root     1337:        thread_t        thread)
1.1       root     1338: {
1.1.1.5   root     1339:        boolean_t               hold;
1.1       root     1340:        spl_t                   spl;
                   1341: 
                   1342:        if (thread == THREAD_NULL)
                   1343:                return KERN_INVALID_ARGUMENT;
                   1344: 
                   1345:        hold = FALSE;
                   1346:        spl = splsched();
                   1347:        thread_lock(thread);
1.1.1.4   root     1348:        /* Wait for thread to get interruptible */
                   1349:        while (thread->state & TH_UNINT) {
1.1.1.5   root     1350:                assert_wait(TH_EV_STATE(thread), TRUE);
1.1.1.4   root     1351:                thread_unlock(thread);
1.1.1.6   root     1352:                thread_block(thread_no_continuation);
1.1.1.4   root     1353:                thread_lock(thread);
                   1354:        }
1.1       root     1355:        if (thread->user_stop_count++ == 0) {
                   1356:                hold = TRUE;
                   1357:                thread->suspend_count++;
                   1358:                thread->state |= TH_SUSP;
                   1359:        }
                   1360:        thread_unlock(thread);
                   1361:        (void) splx(spl);
                   1362: 
                   1363:        /*
                   1364:         *      Now  wait for the thread if necessary.
                   1365:         */
                   1366:        if (hold) {
                   1367:                if (thread == current_thread()) {
                   1368:                        /*
                   1369:                         *      We want to call thread_block on our way out,
                   1370:                         *      to stop running.
                   1371:                         */
                   1372:                        spl = splsched();
                   1373:                        ast_on(cpu_number(), AST_BLOCK);
                   1374:                        (void) splx(spl);
                   1375:                } else
                   1376:                        (void) thread_dowait(thread, TRUE);
                   1377:        }
                   1378:        return KERN_SUCCESS;
                   1379: }
                   1380: 
                   1381: 
                   1382: kern_return_t thread_resume(
1.1.1.5   root     1383:        thread_t        thread)
1.1       root     1384: {
1.1.1.5   root     1385:        kern_return_t           ret;
1.1       root     1386:        spl_t                   s;
                   1387: 
                   1388:        if (thread == THREAD_NULL)
                   1389:                return KERN_INVALID_ARGUMENT;
                   1390: 
                   1391:        ret = KERN_SUCCESS;
                   1392: 
                   1393:        s = splsched();
                   1394:        thread_lock(thread);
                   1395:        if (thread->user_stop_count > 0) {
                   1396:            if (--thread->user_stop_count == 0) {
                   1397:                if (--thread->suspend_count == 0) {
                   1398:                    thread->state &= ~(TH_SUSP | TH_HALTED);
                   1399:                    if ((thread->state & (TH_WAIT | TH_RUN)) == 0) {
                   1400:                            /* was only suspended */
                   1401:                            thread->state |= TH_RUN;
                   1402:                            thread_setrun(thread, TRUE);
                   1403:                    }
                   1404:                }
                   1405:            }
                   1406:        }
                   1407:        else {
                   1408:                ret = KERN_FAILURE;
                   1409:        }
                   1410: 
                   1411:        thread_unlock(thread);
                   1412:        (void) splx(s);
                   1413: 
                   1414:        return ret;
                   1415: }
                   1416: 
                   1417: /*
                   1418:  *     Return thread's machine-dependent state.
                   1419:  */
                   1420: kern_return_t thread_get_state(
1.1.1.5   root     1421:        thread_t                thread,
1.1       root     1422:        int                     flavor,
                   1423:        thread_state_t          old_state,      /* pointer to OUT array */
                   1424:        natural_t               *old_state_count)       /*IN/OUT*/
                   1425: {
                   1426:        kern_return_t           ret;
                   1427: 
1.1.1.8 ! root     1428: #if defined(__i386__) || defined(__x86_64__)
        !          1429:        if (flavor == i386_DEBUG_STATE && thread == current_thread())
        !          1430:                /* This state can be obtained directly for the curren thread.  */
        !          1431:                return thread_getstatus(thread, flavor, old_state, old_state_count);
        !          1432: #endif
        !          1433: 
1.1       root     1434:        if (thread == THREAD_NULL || thread == current_thread()) {
                   1435:                return KERN_INVALID_ARGUMENT;
                   1436:        }
                   1437: 
                   1438:        thread_hold(thread);
                   1439:        (void) thread_dowait(thread, TRUE);
                   1440: 
                   1441:        ret = thread_getstatus(thread, flavor, old_state, old_state_count);
                   1442: 
                   1443:        thread_release(thread);
                   1444:        return ret;
                   1445: }
                   1446: 
                   1447: /*
                   1448:  *     Change thread's machine-dependent state.
                   1449:  */
                   1450: kern_return_t thread_set_state(
1.1.1.5   root     1451:        thread_t                thread,
1.1       root     1452:        int                     flavor,
                   1453:        thread_state_t          new_state,
                   1454:        natural_t               new_state_count)
                   1455: {
                   1456:        kern_return_t           ret;
                   1457: 
1.1.1.8 ! root     1458: #if defined(__i386__) || defined(__x86_64__)
        !          1459:        if (flavor == i386_DEBUG_STATE && thread == current_thread())
        !          1460:                /* This state can be set directly for the curren thread.  */
        !          1461:                return thread_setstatus(thread, flavor, new_state, new_state_count);
        !          1462: #endif
        !          1463: 
1.1       root     1464:        if (thread == THREAD_NULL || thread == current_thread()) {
                   1465:                return KERN_INVALID_ARGUMENT;
                   1466:        }
                   1467: 
                   1468:        thread_hold(thread);
                   1469:        (void) thread_dowait(thread, TRUE);
                   1470: 
                   1471:        ret = thread_setstatus(thread, flavor, new_state, new_state_count);
                   1472: 
                   1473:        thread_release(thread);
                   1474:        return ret;
                   1475: }
                   1476: 
                   1477: kern_return_t thread_info(
1.1.1.5   root     1478:        thread_t                thread,
1.1       root     1479:        int                     flavor,
                   1480:        thread_info_t           thread_info_out,    /* pointer to OUT array */
                   1481:        natural_t               *thread_info_count) /*IN/OUT*/
                   1482: {
                   1483:        int                     state, flags;
                   1484:        spl_t                   s;
                   1485: 
                   1486:        if (thread == THREAD_NULL)
                   1487:                return KERN_INVALID_ARGUMENT;
                   1488: 
                   1489:        if (flavor == THREAD_BASIC_INFO) {
1.1.1.5   root     1490:            thread_basic_info_t basic_info;
1.1       root     1491: 
1.1.1.3   root     1492:            /* Allow *thread_info_count to be one smaller than the
                   1493:               usual amount, because creation_time is a new member
                   1494:               that some callers might not know about. */
                   1495: 
                   1496:            if (*thread_info_count < THREAD_BASIC_INFO_COUNT - 1) {
1.1       root     1497:                return KERN_INVALID_ARGUMENT;
                   1498:            }
                   1499: 
                   1500:            basic_info = (thread_basic_info_t) thread_info_out;
                   1501: 
                   1502:            s = splsched();
                   1503:            thread_lock(thread);
                   1504: 
                   1505:            /*
                   1506:             *  Update lazy-evaluated scheduler info because someone wants it.
                   1507:             */
                   1508:            if ((thread->state & TH_RUN) == 0 &&
                   1509:                thread->sched_stamp != sched_tick)
                   1510:                    update_priority(thread);
                   1511: 
                   1512:            /* fill in info */
                   1513: 
                   1514:            thread_read_times(thread,
                   1515:                        &basic_info->user_time,
                   1516:                        &basic_info->system_time);
                   1517:            basic_info->base_priority   = thread->priority;
                   1518:            basic_info->cur_priority    = thread->sched_pri;
1.1.1.6   root     1519:            read_time_stamp(&thread->creation_time,
                   1520:                            &basic_info->creation_time);
1.1       root     1521: 
                   1522:            /*
                   1523:             *  To calculate cpu_usage, first correct for timer rate,
                   1524:             *  then for 5/8 ageing.  The correction factor [3/5] is
                   1525:             *  (1/(5/8) - 1).
                   1526:             */
                   1527:            basic_info->cpu_usage = thread->cpu_usage /
                   1528:                                        (TIMER_RATE/TH_USAGE_SCALE);
                   1529:            basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5;
                   1530: #if    SIMPLE_CLOCK
                   1531:            /*
                   1532:             *  Clock drift compensation.
                   1533:             */
                   1534:            basic_info->cpu_usage =
                   1535:                (basic_info->cpu_usage * 1000000)/sched_usec;
                   1536: #endif /* SIMPLE_CLOCK */
                   1537: 
1.1.1.2   root     1538:            flags = 0;
1.1       root     1539:            if (thread->state & TH_SWAPPED)
1.1.1.2   root     1540:                flags |= TH_FLAGS_SWAPPED;
                   1541:            if (thread->state & TH_IDLE)
                   1542:                flags |= TH_FLAGS_IDLE;
1.1       root     1543: 
                   1544:            if (thread->state & TH_HALTED)
                   1545:                state = TH_STATE_HALTED;
                   1546:            else
                   1547:            if (thread->state & TH_RUN)
                   1548:                state = TH_STATE_RUNNING;
                   1549:            else
                   1550:            if (thread->state & TH_UNINT)
                   1551:                state = TH_STATE_UNINTERRUPTIBLE;
                   1552:            else
                   1553:            if (thread->state & TH_SUSP)
                   1554:                state = TH_STATE_STOPPED;
                   1555:            else
                   1556:            if (thread->state & TH_WAIT)
                   1557:                state = TH_STATE_WAITING;
                   1558:            else
                   1559:                state = 0;              /* ? */
                   1560: 
                   1561:            basic_info->run_state = state;
                   1562:            basic_info->flags = flags;
                   1563:            basic_info->suspend_count = thread->user_stop_count;
                   1564:            if (state == TH_STATE_RUNNING)
                   1565:                basic_info->sleep_time = 0;
                   1566:            else
                   1567:                basic_info->sleep_time = sched_tick - thread->sched_stamp;
                   1568: 
                   1569:            thread_unlock(thread);
                   1570:            splx(s);
                   1571: 
1.1.1.3   root     1572:            if (*thread_info_count > THREAD_BASIC_INFO_COUNT)
                   1573:              *thread_info_count = THREAD_BASIC_INFO_COUNT;
1.1       root     1574:            return KERN_SUCCESS;
                   1575:        }
                   1576:        else if (flavor == THREAD_SCHED_INFO) {
1.1.1.5   root     1577:            thread_sched_info_t sched_info;
1.1       root     1578: 
                   1579:            if (*thread_info_count < THREAD_SCHED_INFO_COUNT) {
                   1580:                return KERN_INVALID_ARGUMENT;
                   1581:            }
                   1582: 
                   1583:            sched_info = (thread_sched_info_t) thread_info_out;
                   1584: 
                   1585:            s = splsched();
                   1586:            thread_lock(thread);
                   1587: 
                   1588: #if    MACH_FIXPRI
                   1589:            sched_info->policy = thread->policy;
                   1590:            if (thread->policy == POLICY_FIXEDPRI) {
                   1591:                sched_info->data = (thread->sched_data * tick)/1000;
                   1592:            }
                   1593:            else {
                   1594:                sched_info->data = 0;
                   1595:            }
                   1596: #else  /* MACH_FIXPRI */
                   1597:            sched_info->policy = POLICY_TIMESHARE;
                   1598:            sched_info->data = 0;
                   1599: #endif /* MACH_FIXPRI */
                   1600: 
                   1601:            sched_info->base_priority = thread->priority;
                   1602:            sched_info->max_priority = thread->max_priority;
                   1603:            sched_info->cur_priority = thread->sched_pri;
                   1604:            
                   1605:            sched_info->depressed = (thread->depress_priority >= 0);
                   1606:            sched_info->depress_priority = thread->depress_priority;
                   1607: 
                   1608:            thread_unlock(thread);
                   1609:            splx(s);
                   1610: 
                   1611:            *thread_info_count = THREAD_SCHED_INFO_COUNT;
                   1612:            return KERN_SUCCESS;
                   1613:        }
                   1614: 
                   1615:        return KERN_INVALID_ARGUMENT;
                   1616: }
                   1617: 
                   1618: kern_return_t  thread_abort(
1.1.1.5   root     1619:        thread_t        thread)
1.1       root     1620: {
                   1621:        if (thread == THREAD_NULL || thread == current_thread()) {
                   1622:                return KERN_INVALID_ARGUMENT;
                   1623:        }
                   1624: 
                   1625:        /*
                   1626:         *
                   1627:          *     clear it of an event wait 
                   1628:          */
                   1629:        evc_notify_abort(thread);
                   1630: 
                   1631:        /*
                   1632:         *      Try to force the thread to a clean point
                   1633:         *      If the halt operation fails return KERN_ABORTED.
                   1634:         *      ipc code will convert this to an ipc interrupted error code.
                   1635:         */
                   1636:        if (thread_halt(thread, FALSE) != KERN_SUCCESS)
                   1637:                return KERN_ABORTED;
                   1638: 
                   1639:        /*
                   1640:         *      If the thread was in an exception, abort that too.
                   1641:         */
                   1642:        mach_msg_abort_rpc(thread);
                   1643: 
                   1644:        /*
                   1645:         *      Then set it going again.
                   1646:         */
                   1647:        thread_release(thread);
                   1648: 
                   1649:        /*
                   1650:         *      Also abort any depression.
                   1651:         */
                   1652:        if (thread->depress_priority != -1)
                   1653:                thread_depress_abort(thread);
                   1654: 
                   1655:        return KERN_SUCCESS;
                   1656: }
                   1657: 
                   1658: /*
                   1659:  *     thread_start:
                   1660:  *
                   1661:  *     Start a thread at the specified routine.
                   1662:  *     The thread must be in a swapped state.
                   1663:  */
                   1664: 
                   1665: void
                   1666: thread_start(
                   1667:        thread_t        thread,
                   1668:        continuation_t  start)
                   1669: {
                   1670:        thread->swap_func = start;
                   1671: }
                   1672: 
                   1673: /*
                   1674:  *     kernel_thread:
                   1675:  *
                   1676:  *     Start up a kernel thread in the specified task.
                   1677:  */
                   1678: 
                   1679: thread_t kernel_thread(
                   1680:        task_t          task,
                   1681:        continuation_t  start,
                   1682:        void *          arg)
                   1683: {
1.1.1.6   root     1684:        kern_return_t   kr;
1.1       root     1685:        thread_t        thread;
                   1686: 
1.1.1.6   root     1687:        kr = thread_create(task, &thread);
                   1688:        if (kr != KERN_SUCCESS)
                   1689:                return THREAD_NULL;
                   1690: 
1.1       root     1691:        /* release "extra" ref that thread_create gave us */
                   1692:        thread_deallocate(thread);
                   1693:        thread_start(thread, start);
                   1694:        thread->ith_other = arg;
                   1695: 
                   1696:        /*
                   1697:         *      We ensure that the kernel thread starts with a stack.
                   1698:         *      The swapin mechanism might not be operational yet.
                   1699:         */
                   1700:        thread_doswapin(thread);
                   1701:        thread->max_priority = BASEPRI_SYSTEM;
                   1702:        thread->priority = BASEPRI_SYSTEM;
                   1703:        thread->sched_pri = BASEPRI_SYSTEM;
                   1704:        (void) thread_resume(thread);
                   1705:        return thread;
                   1706: }
                   1707: 
                   1708: /*
                   1709:  *     reaper_thread:
                   1710:  *
                   1711:  *     This kernel thread runs forever looking for threads to destroy
                   1712:  *     (when they request that they be destroyed, of course).
                   1713:  */
1.1.1.5   root     1714: void __attribute__((noreturn)) reaper_thread_continue(void)
1.1       root     1715: {
                   1716:        for (;;) {
1.1.1.5   root     1717:                thread_t thread;
1.1       root     1718:                spl_t s;
                   1719: 
                   1720:                s = splsched();
                   1721:                simple_lock(&reaper_lock);
                   1722: 
                   1723:                while ((thread = (thread_t) dequeue_head(&reaper_queue))
                   1724:                                                        != THREAD_NULL) {
                   1725:                        simple_unlock(&reaper_lock);
                   1726:                        (void) splx(s);
                   1727: 
                   1728:                        (void) thread_dowait(thread, TRUE);     /* may block */
                   1729:                        thread_deallocate(thread);              /* may block */
                   1730: 
                   1731:                        s = splsched();
                   1732:                        simple_lock(&reaper_lock);
                   1733:                }
                   1734: 
                   1735:                assert_wait((event_t) &reaper_queue, FALSE);
                   1736:                simple_unlock(&reaper_lock);
                   1737:                (void) splx(s);
                   1738:                counter(c_reaper_thread_block++);
                   1739:                thread_block(reaper_thread_continue);
                   1740:        }
                   1741: }
                   1742: 
                   1743: void reaper_thread(void)
                   1744: {
                   1745:        reaper_thread_continue();
                   1746:        /*NOTREACHED*/
                   1747: }
                   1748: 
                   1749: #if    MACH_HOST
                   1750: /*
                   1751:  *     thread_assign:
                   1752:  *
                   1753:  *     Change processor set assignment.
                   1754:  *     Caller must hold an extra reference to the thread (if this is
                   1755:  *     called directly from the ipc interface, this is an operation
                   1756:  *     in progress reference).  Caller must hold no locks -- this may block.
                   1757:  */
                   1758: 
                   1759: kern_return_t
                   1760: thread_assign(
                   1761:        thread_t        thread,
                   1762:        processor_set_t new_pset)
                   1763: {
                   1764:        if (thread == THREAD_NULL || new_pset == PROCESSOR_SET_NULL) {
                   1765:                return KERN_INVALID_ARGUMENT;
                   1766:        }
                   1767: 
                   1768:        thread_freeze(thread);
                   1769:        thread_doassign(thread, new_pset, TRUE);
                   1770: 
                   1771:        return KERN_SUCCESS;
                   1772: }
                   1773: 
                   1774: /*
                   1775:  *     thread_freeze:
                   1776:  *
                   1777:  *     Freeze thread's assignment.  Prelude to assigning thread.
                   1778:  *     Only one freeze may be held per thread.  
                   1779:  */
                   1780: void
                   1781: thread_freeze(
                   1782:        thread_t        thread)
                   1783: {
                   1784:        spl_t   s;
                   1785:        /*
                   1786:         *      Freeze the assignment, deferring to a prior freeze.
                   1787:         */
                   1788:        s = splsched();
                   1789:        thread_lock(thread);
                   1790:        while (thread->may_assign == FALSE) {
                   1791:                thread->assign_active = TRUE;
                   1792:                thread_sleep((event_t) &thread->assign_active,
                   1793:                        simple_lock_addr(thread->lock), FALSE);
                   1794:                thread_lock(thread);
                   1795:        }
                   1796:        thread->may_assign = FALSE;
                   1797:        thread_unlock(thread);
                   1798:        (void) splx(s);
                   1799: 
                   1800: }
                   1801: 
                   1802: /*
                   1803:  *     thread_unfreeze: release freeze on thread's assignment.
                   1804:  */
                   1805: void
                   1806: thread_unfreeze(
                   1807:        thread_t        thread)
                   1808: {
                   1809:        spl_t   s;
                   1810: 
                   1811:        s = splsched();
                   1812:        thread_lock(thread);
                   1813:        thread->may_assign = TRUE;
                   1814:        if (thread->assign_active) {
                   1815:                thread->assign_active = FALSE;
                   1816:                thread_wakeup((event_t)&thread->assign_active);
                   1817:        }
                   1818:        thread_unlock(thread);
                   1819:        splx(s);
                   1820: }
                   1821: 
                   1822: /*
                   1823:  *     thread_doassign:
                   1824:  *
                   1825:  *     Actually do thread assignment.  thread_will_assign must have been
                   1826:  *     called on the thread.  release_freeze argument indicates whether
                   1827:  *     to release freeze on thread.
                   1828:  */
                   1829: 
                   1830: void
                   1831: thread_doassign(
1.1.1.5   root     1832:        thread_t                        thread,
                   1833:        processor_set_t                 new_pset,
1.1       root     1834:        boolean_t                       release_freeze)
                   1835: {
1.1.1.5   root     1836:        processor_set_t                 pset;
                   1837:        boolean_t                       old_empty, new_empty;
1.1       root     1838:        boolean_t                       recompute_pri = FALSE;
                   1839:        spl_t                           s;
                   1840:        
                   1841:        /*
                   1842:         *      Check for silly no-op.
                   1843:         */
                   1844:        pset = thread->processor_set;
                   1845:        if (pset == new_pset) {
                   1846:                if (release_freeze)
                   1847:                        thread_unfreeze(thread);
                   1848:                return;
                   1849:        }
                   1850:        /*
                   1851:         *      Suspend the thread and stop it if it's not the current thread.
                   1852:         */
                   1853:        thread_hold(thread);
                   1854:        if (thread != current_thread())
                   1855:                (void) thread_dowait(thread, TRUE);
                   1856: 
                   1857:        /*
                   1858:         *      Lock both psets now, use ordering to avoid deadlocks.
                   1859:         */
                   1860: Restart:
                   1861:        if ((vm_offset_t)pset < (vm_offset_t)new_pset) {
                   1862:            pset_lock(pset);
                   1863:            pset_lock(new_pset);
                   1864:        }
                   1865:        else {
                   1866:            pset_lock(new_pset);
                   1867:            pset_lock(pset);
                   1868:        }
                   1869: 
                   1870:        /*
                   1871:         *      Check if new_pset is ok to assign to.  If not, reassign
                   1872:         *      to default_pset.
                   1873:         */
                   1874:        if (!new_pset->active) {
                   1875:            pset_unlock(pset);
                   1876:            pset_unlock(new_pset);
                   1877:            new_pset = &default_pset;
                   1878:            goto Restart;
                   1879:        }
                   1880: 
                   1881:        pset_reference(new_pset);
                   1882: 
                   1883:        /*
                   1884:         *      Grab the thread lock and move the thread.
                   1885:         *      Then drop the lock on the old pset and the thread's
                   1886:         *      reference to it.
                   1887:         */
                   1888:        s = splsched();
                   1889:        thread_lock(thread);
                   1890: 
                   1891:        thread_change_psets(thread, pset, new_pset);
                   1892: 
                   1893:        old_empty = pset->empty;
                   1894:        new_empty = new_pset->empty;
                   1895: 
                   1896:        pset_unlock(pset);
                   1897: 
                   1898:        /*
                   1899:         *      Reset policy and priorities if needed.
                   1900:         */
                   1901: #if    MACH_FIXPRI
                   1902:        if (thread->policy & new_pset->policies == 0) {
                   1903:            thread->policy = POLICY_TIMESHARE;
                   1904:            recompute_pri = TRUE;
                   1905:        }
                   1906: #endif /* MACH_FIXPRI */
                   1907: 
                   1908:        if (thread->max_priority < new_pset->max_priority) {
                   1909:            thread->max_priority = new_pset->max_priority;
                   1910:            if (thread->priority < thread->max_priority) {
                   1911:                thread->priority = thread->max_priority;
                   1912:                recompute_pri = TRUE;
                   1913:            }
                   1914:            else {
                   1915:                if ((thread->depress_priority >= 0) &&
                   1916:                    (thread->depress_priority < thread->max_priority)) {
                   1917:                        thread->depress_priority = thread->max_priority;
                   1918:                }
                   1919:            }
                   1920:        }
                   1921: 
                   1922:        pset_unlock(new_pset);
                   1923: 
                   1924:        if (recompute_pri)
                   1925:                compute_priority(thread, TRUE);
                   1926: 
                   1927:        if (release_freeze) {
                   1928:                thread->may_assign = TRUE;
                   1929:                if (thread->assign_active) {
                   1930:                        thread->assign_active = FALSE;
                   1931:                        thread_wakeup((event_t)&thread->assign_active);
                   1932:                }
                   1933:        }
                   1934: 
                   1935:        thread_unlock(thread);
                   1936:        splx(s);
                   1937: 
                   1938:        pset_deallocate(pset);
                   1939: 
                   1940:        /*
                   1941:         *      Figure out hold status of thread.  Threads assigned to empty
                   1942:         *      psets must be held.  Therefore:
                   1943:         *              If old pset was empty release its hold.
                   1944:         *              Release our hold from above unless new pset is empty.
                   1945:         */
                   1946: 
                   1947:        if (old_empty)
                   1948:                thread_release(thread);
                   1949:        if (!new_empty)
                   1950:                thread_release(thread);
                   1951: 
                   1952:        /*
                   1953:         *      If current_thread is assigned, context switch to force
                   1954:         *      assignment to happen.  This also causes hold to take
                   1955:         *      effect if the new pset is empty.
                   1956:         */
                   1957:        if (thread == current_thread()) {
                   1958:                s = splsched();
                   1959:                ast_on(cpu_number(), AST_BLOCK);
                   1960:                (void) splx(s);
                   1961:        }
                   1962: }
                   1963: #else  /* MACH_HOST */
                   1964: kern_return_t
                   1965: thread_assign(
                   1966:        thread_t        thread,
                   1967:        processor_set_t new_pset)
                   1968: {
                   1969:        return KERN_FAILURE;
                   1970: }
                   1971: #endif /* MACH_HOST */
                   1972: 
                   1973: /*
                   1974:  *     thread_assign_default:
                   1975:  *
                   1976:  *     Special version of thread_assign for assigning threads to default
                   1977:  *     processor set.
                   1978:  */
                   1979: kern_return_t
                   1980: thread_assign_default(
                   1981:        thread_t        thread)
                   1982: {
                   1983:        return thread_assign(thread, &default_pset);
                   1984: }
                   1985: 
                   1986: /*
                   1987:  *     thread_get_assignment
                   1988:  *
                   1989:  *     Return current assignment for this thread.
                   1990:  */        
                   1991: kern_return_t thread_get_assignment(
                   1992:        thread_t        thread,
                   1993:        processor_set_t *pset)
                   1994: {
1.1.1.6   root     1995:        if (thread == THREAD_NULL)
                   1996:                return KERN_INVALID_ARGUMENT;
                   1997: 
1.1       root     1998:        *pset = thread->processor_set;
                   1999:        pset_reference(*pset);
                   2000:        return KERN_SUCCESS;
                   2001: }
                   2002: 
                   2003: /*
                   2004:  *     thread_priority:
                   2005:  *
                   2006:  *     Set priority (and possibly max priority) for thread.
                   2007:  */
                   2008: kern_return_t
                   2009: thread_priority(
                   2010:        thread_t        thread,
                   2011:        int             priority,
                   2012:        boolean_t       set_max)
                   2013: {
                   2014:     spl_t              s;
                   2015:     kern_return_t      ret = KERN_SUCCESS;
                   2016: 
                   2017:     if ((thread == THREAD_NULL) || invalid_pri(priority))
                   2018:        return KERN_INVALID_ARGUMENT;
                   2019: 
                   2020:     s = splsched();
                   2021:     thread_lock(thread);
                   2022: 
                   2023:     /*
                   2024:      * Check for violation of max priority
                   2025:      */
                   2026:     if (priority < thread->max_priority) {
                   2027:        ret = KERN_FAILURE;
                   2028:     }
                   2029:     else {
                   2030:        /*
                   2031:         *      Set priorities.  If a depression is in progress,
                   2032:         *      change the priority to restore.
                   2033:         */
                   2034:        if (thread->depress_priority >= 0) {
                   2035:            thread->depress_priority = priority;
                   2036:        }
                   2037:        else {
                   2038:            thread->priority = priority;
                   2039:            compute_priority(thread, TRUE);
                   2040:        }
                   2041: 
                   2042:        if (set_max)
                   2043:            thread->max_priority = priority;
                   2044:     }
                   2045:     thread_unlock(thread);
                   2046:     (void) splx(s);
                   2047: 
                   2048:     return ret;
                   2049: }
                   2050: 
                   2051: /*
                   2052:  *     thread_set_own_priority:
                   2053:  *
                   2054:  *     Internal use only; sets the priority of the calling thread.
                   2055:  *     Will adjust max_priority if necessary.
                   2056:  */
                   2057: void
                   2058: thread_set_own_priority(
                   2059:        int     priority)
                   2060: {
                   2061:     spl_t      s;
                   2062:     thread_t   thread = current_thread();
                   2063: 
                   2064:     s = splsched();
                   2065:     thread_lock(thread);
                   2066: 
                   2067:     if (priority < thread->max_priority)
                   2068:        thread->max_priority = priority;
                   2069:     thread->priority = priority;
                   2070:     compute_priority(thread, TRUE);
                   2071: 
                   2072:     thread_unlock(thread);
                   2073:     (void) splx(s);
                   2074: }
                   2075: 
                   2076: /*
                   2077:  *     thread_max_priority:
                   2078:  *
                   2079:  *     Reset the max priority for a thread.
                   2080:  */
                   2081: kern_return_t
                   2082: thread_max_priority(
                   2083:        thread_t        thread,
                   2084:        processor_set_t pset,
                   2085:        int             max_priority)
                   2086: {
                   2087:     spl_t              s;
                   2088:     kern_return_t      ret = KERN_SUCCESS;
                   2089: 
                   2090:     if ((thread == THREAD_NULL) || (pset == PROCESSOR_SET_NULL) ||
                   2091:        invalid_pri(max_priority))
                   2092:            return KERN_INVALID_ARGUMENT;
                   2093: 
                   2094:     s = splsched();
                   2095:     thread_lock(thread);
                   2096: 
                   2097: #if    MACH_HOST
                   2098:     /*
                   2099:      * Check for wrong processor set.
                   2100:      */
                   2101:     if (pset != thread->processor_set) {
                   2102:        ret = KERN_FAILURE;
                   2103:     }
                   2104:     else {
                   2105: #endif /* MACH_HOST */
                   2106:        thread->max_priority = max_priority;
                   2107: 
                   2108:        /*
                   2109:         *      Reset priority if it violates new max priority
                   2110:         */
                   2111:        if (max_priority > thread->priority) {
                   2112:            thread->priority = max_priority;
                   2113: 
                   2114:            compute_priority(thread, TRUE);
                   2115:        }
                   2116:        else {
                   2117:            if (thread->depress_priority >= 0 &&
                   2118:                max_priority > thread->depress_priority)
                   2119:                    thread->depress_priority = max_priority;
                   2120:            }
                   2121: #if    MACH_HOST
                   2122:     }
                   2123: #endif /* MACH_HOST */
                   2124: 
                   2125:     thread_unlock(thread);
                   2126:     (void) splx(s);
                   2127: 
                   2128:     return ret;
                   2129: }
                   2130: 
                   2131: /*
                   2132:  *     thread_policy:
                   2133:  *
                   2134:  *     Set scheduling policy for thread.
                   2135:  */
                   2136: kern_return_t
                   2137: thread_policy(
                   2138:        thread_t        thread,
                   2139:        int             policy,
                   2140:        int             data)
                   2141: {
                   2142: #if    MACH_FIXPRI
1.1.1.5   root     2143:        kern_return_t   ret = KERN_SUCCESS;
                   2144:        int             temp;
1.1       root     2145:        spl_t           s;
                   2146: #endif /* MACH_FIXPRI */
                   2147: 
                   2148:        if ((thread == THREAD_NULL) || invalid_policy(policy))
                   2149:                return KERN_INVALID_ARGUMENT;
                   2150: 
                   2151: #if    MACH_FIXPRI
                   2152:        s = splsched();
                   2153:        thread_lock(thread);
                   2154: 
                   2155:        /*
                   2156:         *      Check if changing policy.
                   2157:         */
                   2158:        if (policy == thread->policy) {
                   2159:            /*
                   2160:             *  Just changing data.  This is meaningless for
                   2161:             *  timesharing, quantum for fixed priority (but
                   2162:             *  has no effect until current quantum runs out).
                   2163:             */
                   2164:            if (policy == POLICY_FIXEDPRI) {
                   2165:                temp = data * 1000;
                   2166:                if (temp % tick)
                   2167:                        temp += tick;
                   2168:                thread->sched_data = temp/tick;
                   2169:            }
                   2170:        }
                   2171:        else {
                   2172:            /*
                   2173:             *  Changing policy.  Check if new policy is allowed.
                   2174:             */
                   2175:            if ((thread->processor_set->policies & policy) == 0) {
                   2176:                    ret = KERN_FAILURE;
                   2177:            }
                   2178:            else {
                   2179:                /*
                   2180:                 *      Changing policy.  Save data and calculate new
                   2181:                 *      priority.
                   2182:                 */
                   2183:                thread->policy = policy;
                   2184:                if (policy == POLICY_FIXEDPRI) {
                   2185:                        temp = data * 1000;
                   2186:                        if (temp % tick)
                   2187:                                temp += tick;
                   2188:                        thread->sched_data = temp/tick;
                   2189:                }
                   2190:                compute_priority(thread, TRUE);
                   2191:            }
                   2192:        }
                   2193:        thread_unlock(thread);
                   2194:        (void) splx(s);
                   2195: 
                   2196:        return ret;
                   2197: #else  /* MACH_FIXPRI */
                   2198:        if (policy == POLICY_TIMESHARE)
                   2199:                return KERN_SUCCESS;
                   2200:        else
                   2201:                return KERN_FAILURE;
                   2202: #endif /* MACH_FIXPRI */
                   2203: }
                   2204: 
                   2205: /*
                   2206:  *     thread_wire:
                   2207:  *
                   2208:  *     Specify that the target thread must always be able
                   2209:  *     to run and to allocate memory.
                   2210:  */
                   2211: kern_return_t
                   2212: thread_wire(
                   2213:        host_t          host,
                   2214:        thread_t        thread,
                   2215:        boolean_t       wired)
                   2216: {
                   2217:        spl_t           s;
                   2218: 
                   2219:        if (host == HOST_NULL)
                   2220:            return KERN_INVALID_ARGUMENT;
                   2221: 
                   2222:        if (thread == THREAD_NULL)
                   2223:            return KERN_INVALID_ARGUMENT;
                   2224: 
                   2225:        /*
                   2226:         * This implementation only works for the current thread.
                   2227:         * See stack_privilege.
                   2228:         */
                   2229:        if (thread != current_thread())
                   2230:            return KERN_INVALID_ARGUMENT;
                   2231: 
                   2232:        s = splsched();
                   2233:        thread_lock(thread);
                   2234: 
                   2235:        if (wired) {
1.1.1.8 ! root     2236:            thread->vm_privilege = 1;
1.1       root     2237:            stack_privilege(thread);
                   2238:        }
                   2239:        else {
1.1.1.8 ! root     2240:            thread->vm_privilege = 0;
1.1       root     2241: /*XXX      stack_unprivilege(thread); */
                   2242:            thread->stack_privilege = 0;
                   2243:        }
                   2244: 
                   2245:        thread_unlock(thread);
                   2246:        splx(s);
                   2247: 
                   2248:        return KERN_SUCCESS;
                   2249: }
                   2250: 
                   2251: /*
                   2252:  *     thread_collect_scan:
                   2253:  *
                   2254:  *     Attempt to free resources owned by threads.
                   2255:  *     pcb_collect doesn't do anything yet.
                   2256:  */
                   2257: 
                   2258: void thread_collect_scan(void)
                   2259: {
                   2260:        register thread_t       thread, prev_thread;
                   2261:        processor_set_t         pset, prev_pset;
                   2262: 
                   2263:        prev_thread = THREAD_NULL;
                   2264:        prev_pset = PROCESSOR_SET_NULL;
                   2265: 
                   2266:        simple_lock(&all_psets_lock);
                   2267:        queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
                   2268:                pset_lock(pset);
                   2269:                queue_iterate(&pset->threads, thread, thread_t, pset_threads) {
                   2270:                        spl_t   s = splsched();
                   2271:                        thread_lock(thread);
                   2272: 
                   2273:                        /*
                   2274:                         *      Only collect threads which are
                   2275:                         *      not runnable and are swapped.
                   2276:                         */
                   2277: 
                   2278:                        if ((thread->state & (TH_RUN|TH_SWAPPED))
                   2279:                                                        == TH_SWAPPED) {
                   2280:                                thread->ref_count++;
                   2281:                                thread_unlock(thread);
                   2282:                                (void) splx(s);
                   2283:                                pset->ref_count++;
                   2284:                                pset_unlock(pset);
                   2285:                                simple_unlock(&all_psets_lock);
                   2286: 
                   2287:                                pcb_collect(thread);
                   2288: 
                   2289:                                if (prev_thread != THREAD_NULL)
                   2290:                                        thread_deallocate(prev_thread);
                   2291:                                prev_thread = thread;
                   2292: 
                   2293:                                if (prev_pset != PROCESSOR_SET_NULL)
                   2294:                                        pset_deallocate(prev_pset);
                   2295:                                prev_pset = pset;
                   2296: 
                   2297:                                simple_lock(&all_psets_lock);
                   2298:                                pset_lock(pset);
                   2299:                        } else {
                   2300:                                thread_unlock(thread);
                   2301:                                (void) splx(s);
                   2302:                        }
                   2303:                }
                   2304:                pset_unlock(pset);
                   2305:        }
                   2306:        simple_unlock(&all_psets_lock);
                   2307: 
                   2308:        if (prev_thread != THREAD_NULL)
                   2309:                thread_deallocate(prev_thread);
                   2310:        if (prev_pset != PROCESSOR_SET_NULL)
                   2311:                pset_deallocate(prev_pset);
                   2312: }
                   2313: 
                   2314: boolean_t thread_collect_allowed = TRUE;
                   2315: unsigned thread_collect_last_tick = 0;
                   2316: unsigned thread_collect_max_rate = 0;          /* in ticks */
                   2317: 
                   2318: /*
                   2319:  *     consider_thread_collect:
                   2320:  *
                   2321:  *     Called by the pageout daemon when the system needs more free pages.
                   2322:  */
                   2323: 
                   2324: void consider_thread_collect(void)
                   2325: {
                   2326:        /*
                   2327:         *      By default, don't attempt thread collection more frequently
                   2328:         *      than once a second.
                   2329:         */
                   2330: 
                   2331:        if (thread_collect_max_rate == 0)
                   2332:                thread_collect_max_rate = hz;
                   2333: 
                   2334:        if (thread_collect_allowed &&
                   2335:            (sched_tick >
                   2336:             (thread_collect_last_tick + thread_collect_max_rate))) {
                   2337:                thread_collect_last_tick = sched_tick;
                   2338:                thread_collect_scan();
                   2339:        }
                   2340: }
                   2341: 
                   2342: #if    MACH_DEBUG
                   2343: 
                   2344: vm_size_t stack_usage(
1.1.1.5   root     2345:        vm_offset_t stack)
1.1       root     2346: {
1.1.1.7   root     2347:        unsigned i;
1.1       root     2348: 
                   2349:        for (i = 0; i < KERNEL_STACK_SIZE/sizeof(unsigned int); i++)
                   2350:            if (((unsigned int *)stack)[i] != STACK_MARKER)
                   2351:                break;
                   2352: 
                   2353:        return KERNEL_STACK_SIZE - i * sizeof(unsigned int);
                   2354: }
                   2355: 
                   2356: /*
                   2357:  *     Machine-dependent code should call stack_init
                   2358:  *     before doing its own initialization of the stack.
                   2359:  */
                   2360: 
                   2361: void stack_init(
1.1.1.5   root     2362:        vm_offset_t stack)
1.1       root     2363: {
                   2364:        if (stack_check_usage) {
1.1.1.7   root     2365:            unsigned i;
1.1       root     2366: 
                   2367:            for (i = 0; i < KERNEL_STACK_SIZE/sizeof(unsigned int); i++)
                   2368:                ((unsigned int *)stack)[i] = STACK_MARKER;
                   2369:        }
                   2370: }
                   2371: 
                   2372: /*
                   2373:  *     Machine-dependent code should call stack_finalize
                   2374:  *     before releasing the stack memory.
                   2375:  */
                   2376: 
                   2377: void stack_finalize(
1.1.1.5   root     2378:        vm_offset_t stack)
1.1       root     2379: {
                   2380:        if (stack_check_usage) {
                   2381:            vm_size_t used = stack_usage(stack);
                   2382: 
                   2383:            simple_lock(&stack_usage_lock);
                   2384:            if (used > stack_max_usage)
                   2385:                stack_max_usage = used;
                   2386:            simple_unlock(&stack_usage_lock);
                   2387:        }
                   2388: }
                   2389: 
                   2390: #ifndef        MACHINE_STACK
                   2391: /*
                   2392:  *     stack_statistics:
                   2393:  *
                   2394:  *     Return statistics on cached kernel stacks.
                   2395:  *     *maxusagep must be initialized by the caller.
                   2396:  */
                   2397: 
                   2398: void stack_statistics(
                   2399:        natural_t *totalp,
                   2400:        vm_size_t *maxusagep)
                   2401: {
                   2402:        spl_t   s;
                   2403: 
                   2404:        s = splsched();
                   2405:        stack_lock();
                   2406:        if (stack_check_usage) {
                   2407:                vm_offset_t stack;
                   2408: 
                   2409:                /*
                   2410:                 *      This is pretty expensive to do at splsched,
                   2411:                 *      but it only happens when someone makes
                   2412:                 *      a debugging call, so it should be OK.
                   2413:                 */
                   2414: 
                   2415:                for (stack = stack_free_list; stack != 0;
                   2416:                     stack = stack_next(stack)) {
                   2417:                        vm_size_t usage = stack_usage(stack);
                   2418: 
                   2419:                        if (usage > *maxusagep)
                   2420:                                *maxusagep = usage;
                   2421:                }
                   2422:        }
                   2423: 
                   2424:        *totalp = stack_free_count;
                   2425:        stack_unlock();
                   2426:        (void) splx(s);
                   2427: }
                   2428: #endif /* MACHINE_STACK */
                   2429: 
                   2430: kern_return_t host_stack_usage(
                   2431:        host_t          host,
                   2432:        vm_size_t       *reservedp,
                   2433:        unsigned int    *totalp,
                   2434:        vm_size_t       *spacep,
                   2435:        vm_size_t       *residentp,
                   2436:        vm_size_t       *maxusagep,
                   2437:        vm_offset_t     *maxstackp)
                   2438: {
1.1.1.4   root     2439:        natural_t total;
1.1       root     2440:        vm_size_t maxusage;
                   2441: 
                   2442:        if (host == HOST_NULL)
                   2443:                return KERN_INVALID_HOST;
                   2444: 
                   2445:        simple_lock(&stack_usage_lock);
                   2446:        maxusage = stack_max_usage;
                   2447:        simple_unlock(&stack_usage_lock);
                   2448: 
                   2449:        stack_statistics(&total, &maxusage);
                   2450: 
                   2451:        *reservedp = 0;
                   2452:        *totalp = total;
                   2453:        *spacep = *residentp = total * round_page(KERNEL_STACK_SIZE);
                   2454:        *maxusagep = maxusage;
                   2455:        *maxstackp = 0;
                   2456:        return KERN_SUCCESS;
                   2457: }
                   2458: 
                   2459: kern_return_t processor_set_stack_usage(
                   2460:        processor_set_t pset,
                   2461:        unsigned int    *totalp,
                   2462:        vm_size_t       *spacep,
                   2463:        vm_size_t       *residentp,
                   2464:        vm_size_t       *maxusagep,
                   2465:        vm_offset_t     *maxstackp)
                   2466: {
                   2467:        unsigned int total;
                   2468:        vm_size_t maxusage;
                   2469:        vm_offset_t maxstack;
                   2470: 
1.1.1.5   root     2471:        thread_t *threads;
                   2472:        thread_t tmp_thread;
1.1       root     2473: 
                   2474:        unsigned int actual;    /* this many things */
                   2475:        unsigned int i;
                   2476: 
                   2477:        vm_size_t size, size_needed;
                   2478:        vm_offset_t addr;
                   2479: 
                   2480:        if (pset == PROCESSOR_SET_NULL)
                   2481:                return KERN_INVALID_ARGUMENT;
                   2482: 
                   2483:        size = 0; addr = 0;
                   2484: 
                   2485:        for (;;) {
                   2486:                pset_lock(pset);
                   2487:                if (!pset->active) {
                   2488:                        pset_unlock(pset);
                   2489:                        return KERN_INVALID_ARGUMENT;
                   2490:                }
                   2491: 
                   2492:                actual = pset->thread_count;
                   2493: 
                   2494:                /* do we have the memory we need? */
                   2495: 
                   2496:                size_needed = actual * sizeof(thread_t);
                   2497:                if (size_needed <= size)
                   2498:                        break;
                   2499: 
                   2500:                /* unlock the pset and allocate more memory */
                   2501:                pset_unlock(pset);
                   2502: 
                   2503:                if (size != 0)
                   2504:                        kfree(addr, size);
                   2505: 
                   2506:                assert(size_needed > 0);
                   2507:                size = size_needed;
                   2508: 
                   2509:                addr = kalloc(size);
                   2510:                if (addr == 0)
                   2511:                        return KERN_RESOURCE_SHORTAGE;
                   2512:        }
                   2513: 
                   2514:        /* OK, have memory and the processor_set is locked & active */
                   2515: 
                   2516:        threads = (thread_t *) addr;
                   2517:        for (i = 0, tmp_thread = (thread_t) queue_first(&pset->threads);
                   2518:             i < actual;
                   2519:             i++,
                   2520:             tmp_thread = (thread_t) queue_next(&tmp_thread->pset_threads)) {
                   2521:                thread_reference(tmp_thread);
                   2522:                threads[i] = tmp_thread;
                   2523:        }
                   2524:        assert(queue_end(&pset->threads, (queue_entry_t) tmp_thread));
                   2525: 
                   2526:        /* can unlock processor set now that we have the thread refs */
                   2527:        pset_unlock(pset);
                   2528: 
                   2529:        /* calculate maxusage and free thread references */
                   2530: 
                   2531:        total = 0;
                   2532:        maxusage = 0;
                   2533:        maxstack = 0;
                   2534:        for (i = 0; i < actual; i++) {
                   2535:                thread_t thread = threads[i];
                   2536:                vm_offset_t stack = 0;
                   2537: 
                   2538:                /*
                   2539:                 *      thread->kernel_stack is only accurate if the
                   2540:                 *      thread isn't swapped and is not executing.
                   2541:                 *
                   2542:                 *      Of course, we don't have the appropriate locks
                   2543:                 *      for these shenanigans.
                   2544:                 */
                   2545: 
                   2546:                if ((thread->state & TH_SWAPPED) == 0) {
                   2547:                        int cpu;
                   2548: 
                   2549:                        stack = thread->kernel_stack;
                   2550: 
                   2551:                        for (cpu = 0; cpu < NCPUS; cpu++)
                   2552:                                if (active_threads[cpu] == thread) {
                   2553:                                        stack = active_stacks[cpu];
                   2554:                                        break;
                   2555:                                }
                   2556:                }
                   2557: 
                   2558:                if (stack != 0) {
                   2559:                        total++;
                   2560: 
                   2561:                        if (stack_check_usage) {
                   2562:                                vm_size_t usage = stack_usage(stack);
                   2563: 
                   2564:                                if (usage > maxusage) {
                   2565:                                        maxusage = usage;
                   2566:                                        maxstack = (vm_offset_t) thread;
                   2567:                                }
                   2568:                        }
                   2569:                }
                   2570: 
                   2571:                thread_deallocate(thread);
                   2572:        }
                   2573: 
                   2574:        if (size != 0)
                   2575:                kfree(addr, size);
                   2576: 
                   2577:        *totalp = total;
                   2578:        *residentp = *spacep = total * round_page(KERNEL_STACK_SIZE);
                   2579:        *maxusagep = maxusage;
                   2580:        *maxstackp = maxstack;
                   2581:        return KERN_SUCCESS;
                   2582: }
                   2583: 
                   2584: /*
                   2585:  *     Useful in the debugger:
                   2586:  */
                   2587: void
                   2588: thread_stats(void)
                   2589: {
1.1.1.5   root     2590:        thread_t thread;
1.1       root     2591:        int total = 0, rpcreply = 0;
                   2592: 
                   2593:        queue_iterate(&default_pset.threads, thread, thread_t, pset_threads) {
                   2594:                total++;
                   2595:                if (thread->ith_rpc_reply != IP_NULL)
                   2596:                        rpcreply++;
                   2597:        }
                   2598: 
                   2599:        printf("%d total threads.\n", total);
                   2600:        printf("%d using rpc_reply.\n", rpcreply);
                   2601: }
                   2602: #endif /* MACH_DEBUG */

unix.superglobalmegacorp.com

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