Annotation of kernel/kern/thread.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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