Annotation of XNU/osfmk/kern/thread.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_FREE_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: /*
                     53:  *     File:   kern/thread.c
                     54:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub
                     55:  *     Date:   1986
                     56:  *
                     57:  *     Thread/thread_shuttle management primitives implementation.
                     58:  */
                     59: /*
                     60:  * Copyright (c) 1993 The University of Utah and
                     61:  * the Computer Systems Laboratory (CSL).  All rights reserved.
                     62:  *
                     63:  * Permission to use, copy, modify and distribute this software and its
                     64:  * documentation is hereby granted, provided that both the copyright
                     65:  * notice and this permission notice appear in all copies of the
                     66:  * software, derivative works or modified versions, and any portions
                     67:  * thereof, and that both notices appear in supporting documentation.
                     68:  *
                     69:  * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
                     70:  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
                     71:  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     72:  *
                     73:  * CSL requests users of this software to return to [email protected] any
                     74:  * improvements that they make and grant CSL redistribution rights.
                     75:  *
                     76:  */
                     77: 
                     78: #include <cpus.h>
                     79: #include <mach_host.h>
                     80: #include <simple_clock.h>
                     81: #include <mach_debug.h>
                     82: #include <mach_prof.h>
                     83: #include <dipc.h>
                     84: #include <stack_usage.h>
                     85: 
                     86: #include <mach/boolean.h>
                     87: #include <mach/policy.h>
                     88: #include <mach/thread_info.h>
                     89: #include <mach/thread_special_ports.h>
                     90: #include <mach/thread_status.h>
                     91: #include <mach/time_value.h>
                     92: #include <mach/vm_param.h>
                     93: #include <kern/ast.h>
                     94: #include <kern/cpu_data.h>
                     95: #include <kern/counters.h>
                     96: #include <kern/etap_macros.h>
                     97: #include <kern/ipc_mig.h>
                     98: #include <kern/ipc_tt.h>
                     99: #include <kern/mach_param.h>
                    100: #include <kern/machine.h>
                    101: #include <kern/misc_protos.h>
                    102: #include <kern/processor.h>
                    103: #include <kern/queue.h>
                    104: #include <kern/sched.h>
                    105: #include <kern/sched_prim.h>
                    106: #include <kern/sf.h>
                    107: #include <kern/mk_sp.h>        /*** ??? fix so this can be removed ***/
                    108: #include <kern/task.h>
                    109: #include <kern/thread.h>
                    110: #include <kern/thread_act.h>
                    111: #include <kern/thread_swap.h>
                    112: #include <kern/host.h>
                    113: #include <kern/zalloc.h>
                    114: #include <vm/vm_kern.h>
                    115: #include <ipc/ipc_kmsg.h>
                    116: #include <ipc/ipc_port.h>
                    117: #include <machine/thread.h>            /* for MACHINE_STACK */
                    118: #include <kern/profile.h>
                    119: #include <kern/assert.h>
                    120: #include <sys/kdebug.h>
                    121: 
                    122: /*
                    123:  * Exported interfaces
                    124:  */
                    125: 
                    126: #include <mach/thread_act_server.h>
                    127: #include <mach/mach_host_server.h>
                    128: 
                    129: /*
                    130:  * Per-Cpu stashed global state
                    131:  */
                    132: vm_offset_t                    active_stacks[NCPUS];   /* per-cpu active stacks        */
                    133: vm_offset_t                    kernel_stack[NCPUS];    /* top of active stacks         */
                    134: thread_act_t           active_kloaded[NCPUS];  /*  + act if kernel loaded      */
                    135: 
                    136: decl_mutex_data(,      funnel_lock)
                    137: 
                    138: struct zone                    *thread_shuttle_zone;
                    139: 
                    140: queue_head_t           reaper_queue;
                    141: decl_simple_lock_data(,reaper_lock)
                    142: thread_call_t          thread_reaper_call;
                    143: 
                    144: extern int             tick;
                    145: 
                    146: extern void            pcb_module_init(void);
                    147: 
                    148: /* private */
                    149: static struct thread_shuttle   thr_sh_template;
                    150: 
                    151: #if    MACH_DEBUG
                    152: #if    STACK_USAGE
                    153: static void    stack_init(vm_offset_t stack, unsigned int bytes);
                    154: void           stack_finalize(vm_offset_t stack);
                    155: vm_size_t      stack_usage(vm_offset_t stack);
                    156: #else  /*STACK_USAGE*/
                    157: #define stack_init(stack, size)
                    158: #define stack_finalize(stack)
                    159: #define stack_usage(stack) (vm_size_t)0
                    160: #endif /*STACK_USAGE*/
                    161: 
                    162: #ifdef MACHINE_STACK
                    163: extern
                    164: #endif
                    165:     void       stack_statistics(
                    166:                        unsigned int    *totalp,
                    167:                        vm_size_t       *maxusagep);
                    168: 
                    169: #define        STACK_MARKER    0xdeadbeef
                    170: #if    STACK_USAGE
                    171: boolean_t              stack_check_usage = TRUE;
                    172: #else  /* STACK_USAGE */
                    173: boolean_t              stack_check_usage = FALSE;
                    174: #endif /* STACK_USAGE */
                    175: decl_simple_lock_data(,stack_usage_lock)
                    176: vm_size_t              stack_max_usage = 0;
                    177: vm_size_t              stack_max_use = KERNEL_STACK_SIZE - 64;
                    178: #endif /* MACH_DEBUG */
                    179: 
                    180: /* Forwards */
                    181: void           thread_collect_scan(void);
                    182: 
                    183: kern_return_t thread_create_shuttle(
                    184:        thread_act_t                    thr_act,
                    185:        sp_attributes_t                 policy_attributes,
                    186:        void                                    (*start_at)(void),
                    187:        thread_t                                *new_thread);
                    188: 
                    189: extern void            Load_context(
                    190:        thread_t                thread);
                    191: 
                    192: 
                    193: /*
                    194:  *     Machine-dependent code must define:
                    195:  *             thread_machine_init
                    196:  *             thread_machine_terminate
                    197:  *             thread_machine_collect
                    198:  *
                    199:  *     The thread->pcb field is reserved for machine-dependent code.
                    200:  */
                    201: 
                    202: #ifdef MACHINE_STACK
                    203: /*
                    204:  *     Machine-dependent code must define:
                    205:  *             stack_alloc_try
                    206:  *             stack_alloc
                    207:  *             stack_free
                    208:  *             stack_collect
                    209:  *     and if MACH_DEBUG:
                    210:  *             stack_statistics
                    211:  */
                    212: #else  /* MACHINE_STACK */
                    213: /*
                    214:  *     We allocate stacks from generic kernel VM.
                    215:  *     Machine-dependent code must define:
                    216:  *             machine_kernel_stack_init
                    217:  *
                    218:  *     The stack_free_list can only be accessed at splsched,
                    219:  *     because stack_alloc_try/thread_invoke operate at splsched.
                    220:  */
                    221: 
                    222: decl_simple_lock_data(,stack_lock_data)         /* splsched only */
                    223: #define stack_lock()   simple_lock(&stack_lock_data)
                    224: #define stack_unlock() simple_unlock(&stack_lock_data)
                    225: 
                    226: vm_offset_t stack_free_list;           /* splsched only */
                    227: unsigned int stack_free_count = 0;     /* splsched only */
                    228: unsigned int stack_free_limit = 1;     /* patchable */
                    229: 
                    230: unsigned int stack_alloc_hits = 0;     /* debugging */
                    231: unsigned int stack_alloc_misses = 0;   /* debugging */
                    232: unsigned int stack_alloc_max = 0;      /* debugging */
                    233: 
                    234: unsigned int stack_alloc_total = 0;
                    235: unsigned int stack_alloc_hiwater = 0;
                    236: 
                    237: /*
                    238:  *     The next field is at the base of the stack,
                    239:  *     so the low end is left unsullied.
                    240:  */
                    241: 
                    242: #define stack_next(stack) (*((vm_offset_t *)((stack) + KERNEL_STACK_SIZE) - 1))
                    243: 
                    244: /*
                    245:  *     stack_alloc:
                    246:  *
                    247:  *     Allocate a kernel stack for an activation.
                    248:  *     May block.
                    249:  */
                    250: vm_offset_t
                    251: stack_alloc(
                    252:        thread_t thread,
                    253:        void (*continuation)(void))
                    254: {
                    255:        vm_offset_t stack;
                    256:        spl_t   s;
                    257: 
                    258:        /*
                    259:         *      We first try the free list.  It is probably empty,
                    260:         *      or stack_alloc_try would have succeeded, but possibly
                    261:         *      a stack was freed before the swapin thread got to us.
                    262:         */
                    263: 
                    264:        s = splsched();
                    265:        stack_lock();
                    266:        stack = stack_free_list;
                    267:        if (stack != 0) {
                    268:                stack_free_list = stack_next(stack);
                    269:                stack_free_count--;
                    270:        }
                    271:        stack_unlock();
                    272:        splx(s);
                    273: 
                    274:        if (stack == 0) {
                    275:                /*
                    276:                 *      Kernel stacks should be naturally aligned,
                    277:                 *      so that it is easy to find the starting/ending
                    278:                 *      addresses of a stack given an address in the middle.
                    279:                 */
                    280: 
                    281:                if (kmem_alloc_aligned(kernel_map, &stack,
                    282:                                round_page(KERNEL_STACK_SIZE)) != KERN_SUCCESS)
                    283:                        panic("stack_alloc");
                    284: 
                    285:                stack_alloc_total++;
                    286:                if (stack_alloc_total > stack_alloc_hiwater)
                    287:                  stack_alloc_hiwater = stack_alloc_total;
                    288: 
                    289: #if    MACH_DEBUG
                    290:                stack_init(stack, round_page(KERNEL_STACK_SIZE));
                    291: #endif /* MACH_DEBUG */
                    292: 
                    293:                /*
                    294:                 * If using fractional pages, free the remainder(s)
                    295:                 */
                    296:                if (KERNEL_STACK_SIZE < round_page(KERNEL_STACK_SIZE)) {
                    297:                    vm_offset_t ptr  = stack + KERNEL_STACK_SIZE;
                    298:                    vm_offset_t endp = stack + round_page(KERNEL_STACK_SIZE);
                    299:                    while (ptr < endp) {
                    300: #if    MACH_DEBUG
                    301:                            /*
                    302:                             * We need to initialize just the end of the 
                    303:                             * region.
                    304:                             */
                    305:                            stack_init(ptr, (unsigned int) (endp - ptr));
                    306: #endif
                    307:                                stack_lock();
                    308:                                stack_next(stack) = stack_free_list;
                    309:                                stack_free_list = stack;
                    310:                                if (++stack_free_count > stack_alloc_max)
                    311:                                  stack_alloc_max = stack_free_count;
                    312:                                stack_unlock();
                    313:                            ptr += KERNEL_STACK_SIZE;
                    314:                    }
                    315:                }
                    316:        }
                    317:        stack_attach(thread, stack, continuation);
                    318:        return (stack);
                    319: }
                    320: 
                    321: /*
                    322:  *     stack_free:
                    323:  *
                    324:  *     Free a kernel stack.
                    325:  *     Called at splsched.
                    326:  */
                    327: 
                    328: void
                    329: stack_free(
                    330:        thread_t thread)
                    331: {
                    332:     vm_offset_t stack = stack_detach(thread);
                    333:        assert(stack);
                    334:        if (stack != thread->stack_privilege) {
                    335:          stack_lock();
                    336:          stack_next(stack) = stack_free_list;
                    337:          stack_free_list = stack;
                    338:          if (++stack_free_count > stack_alloc_max)
                    339:                stack_alloc_max = stack_free_count;
                    340:          stack_unlock();
                    341:        }
                    342: }
                    343: 
                    344: /*
                    345:  *     stack_collect:
                    346:  *
                    347:  *     Free excess kernel stacks.
                    348:  *     May block.
                    349:  */
                    350: 
                    351: void
                    352: stack_collect(void)
                    353: {
                    354:        register vm_offset_t stack;
                    355:        spl_t   s;
                    356: 
                    357:        /* If using fractional pages, Cannot just call kmem_free(),
                    358:         * and we're too lazy to coalesce small chunks.
                    359:         */
                    360:        if (KERNEL_STACK_SIZE < round_page(KERNEL_STACK_SIZE))
                    361:                return;
                    362: 
                    363:        s = splsched();
                    364:        stack_lock();
                    365:        while (stack_free_count > stack_free_limit) {
                    366:                stack = stack_free_list;
                    367:                stack_free_list = stack_next(stack);
                    368:                stack_free_count--;
                    369:                stack_unlock();
                    370:                splx(s);
                    371: 
                    372: #if    MACH_DEBUG
                    373:                stack_finalize(stack);
                    374: #endif /* MACH_DEBUG */
                    375:                kmem_free(kernel_map, stack, KERNEL_STACK_SIZE);
                    376: 
                    377:                s = splsched();
                    378:                stack_alloc_total--;
                    379:                stack_lock();
                    380:        }
                    381:        stack_unlock();
                    382:        splx(s);
                    383: }
                    384: 
                    385: 
                    386: #if    MACH_DEBUG
                    387: /*
                    388:  *     stack_statistics:
                    389:  *
                    390:  *     Return statistics on cached kernel stacks.
                    391:  *     *maxusagep must be initialized by the caller.
                    392:  */
                    393: 
                    394: void
                    395: stack_statistics(
                    396:        unsigned int    *totalp,
                    397:        vm_size_t       *maxusagep)
                    398: {
                    399:        spl_t   s;
                    400: 
                    401:        s = splsched();
                    402:        stack_lock();
                    403: 
                    404: #if    STACK_USAGE
                    405:        if (stack_check_usage) {
                    406:                vm_offset_t stack;
                    407: 
                    408:                /*
                    409:                 *      This is pretty expensive to do at splsched,
                    410:                 *      but it only happens when someone makes
                    411:                 *      a debugging call, so it should be OK.
                    412:                 */
                    413: 
                    414:                for (stack = stack_free_list; stack != 0;
                    415:                     stack = stack_next(stack)) {
                    416:                        vm_size_t usage = stack_usage(stack);
                    417: 
                    418:                        if (usage > *maxusagep)
                    419:                                *maxusagep = usage;
                    420:                }
                    421:        }
                    422: #endif /* STACK_USAGE */
                    423: 
                    424:        *totalp = stack_free_count;
                    425:        stack_unlock();
                    426:        splx(s);
                    427: }
                    428: #endif /* MACH_DEBUG */
                    429: 
                    430: #endif /* MACHINE_STACK */
                    431: 
                    432: 
                    433: /*
                    434:  *     stack_privilege:
                    435:  *
                    436:  *     stack_alloc_try on this thread must always succeed.
                    437:  */
                    438: 
                    439: void
                    440: stack_privilege(
                    441:        register thread_t thread)
                    442: {
                    443:        /*
                    444:         *      This implementation only works for the current thread.
                    445:         */
                    446: 
                    447:        if (thread != current_thread())
                    448:                panic("stack_privilege");
                    449: 
                    450:        if (thread->stack_privilege == 0)
                    451:                thread->stack_privilege = current_stack();
                    452: }
                    453: 
                    454: /*
                    455:  *     stack_alloc_try:
                    456:  *
                    457:  *     Non-blocking attempt to allocate a kernel stack.
                    458:  *     Called at splsched with the thread locked.
                    459:  */
                    460: 
                    461: boolean_t stack_alloc_try(
                    462:        thread_t        thread,
                    463:        void            (*resume)(void))
                    464: {
                    465:        register vm_offset_t stack;
                    466: 
                    467:        if ((stack = thread->stack_privilege) == (vm_offset_t)0) {
                    468:          stack_lock();
                    469:          stack = stack_free_list;
                    470:          if (stack != (vm_offset_t)0) {
                    471:            stack_free_list = stack_next(stack);
                    472:            stack_free_count--;
                    473:          }
                    474:          stack_unlock();
                    475:        }
                    476: 
                    477:        if (stack != 0) {
                    478:                stack_attach(thread, stack, resume);
                    479:                stack_alloc_hits++;
                    480:                return TRUE;
                    481:        } else {
                    482:                stack_alloc_misses++;
                    483:                return FALSE;
                    484:        }
                    485: }
                    486: 
                    487: void
                    488: thread_init(void)
                    489: {
                    490:        thread_shuttle_zone = zinit(
                    491:                        sizeof(struct thread_shuttle),
                    492:                        THREAD_MAX * sizeof(struct thread_shuttle),
                    493:                        THREAD_CHUNK * sizeof(struct thread_shuttle),
                    494:                        "threads");
                    495: 
                    496:        /*
                    497:         *      Fill in a template thread_shuttle for fast initialization.
                    498:         *      [Fields that must be (or are typically) reset at
                    499:         *      time of creation are so noted.]
                    500:         */
                    501: 
                    502:        /* thr_sh_template.links (none) */
                    503:        thr_sh_template.runq = RUN_QUEUE_NULL;
                    504: 
                    505: 
                    506:        /* thr_sh_template.task (later) */
                    507:        /* thr_sh_template.thread_list (later) */
                    508:        /* thr_sh_template.pset_threads (later) */
                    509: 
                    510:        /* one ref for being alive, one to return to the creator */
                    511:        thr_sh_template.ref_count = 2;
                    512: 
                    513:        thr_sh_template.wait_event = NO_EVENT;
                    514:        thr_sh_template.wait_result = KERN_SUCCESS;
                    515:        thr_sh_template.wait_queue = WAIT_QUEUE_NULL;
                    516:        thr_sh_template.wake_active = FALSE;
                    517:        /*thr_sh_template.state = TH_SUSP;*/
                    518:        thr_sh_template.state = 0;
                    519:        thr_sh_template.continuation = (void (*)(void))thread_bootstrap_return;
                    520:        thr_sh_template.top_act = THR_ACT_NULL;
                    521: 
                    522: /*     thr_sh_template.priority (later) */
                    523: /***???        thr_sh_template.max_priority = BASEPRI_USER; ***/
                    524: /*     thr_sh_template.sched_pri (later - compute_priority) */
                    525: /***???        thr_sh_template.sched_data = 0; ***/
                    526:        thr_sh_template.policy = POLICY_TIMESHARE;
                    527: /***???        thr_sh_template.depress_priority = -1; ***/
                    528: /***???        thr_sh_template.cpu_usage = 0; ***/
                    529: /***???        thr_sh_template.sched_usage = 0; ***/
                    530:        /* thr_sh_template.sched_stamp (later) */
                    531: /***???        thr_sh_template.sched_change_stamp = 1; ***/
                    532: 
                    533:        thr_sh_template.vm_privilege = FALSE;
                    534: 
                    535:        /* thr_sh_template.<IPC structures> (later) */
                    536: 
                    537:        timer_init(&(thr_sh_template.user_timer));
                    538:        timer_init(&(thr_sh_template.system_timer));
                    539:        thr_sh_template.user_timer_save.low = 0;
                    540:        thr_sh_template.user_timer_save.high = 0;
                    541:        thr_sh_template.system_timer_save.low = 0;
                    542:        thr_sh_template.system_timer_save.high = 0;
                    543:        thr_sh_template.cpu_delta = 0;
                    544:        thr_sh_template.sched_delta = 0;
                    545: 
                    546:        thr_sh_template.active = FALSE; /* reset */
                    547: 
                    548:        /* thr_sh_template.processor_set (later) */
                    549: #if    NCPUS > 1
                    550:        thr_sh_template.bound_processor = PROCESSOR_NULL;
                    551: #endif /*NCPUS > 1*/
                    552: #if    MACH_HOST
                    553:        thr_sh_template.may_assign = TRUE;
                    554:        thr_sh_template.assign_active = FALSE;
                    555: #endif /* MACH_HOST */
                    556:        thr_sh_template.funnel_state = 0;
                    557: 
                    558: #if    NCPUS > 1
                    559:        /* thr_sh_template.last_processor  (later) */
                    560: #endif /* NCPUS > 1 */
                    561: 
                    562:        /*
                    563:         *      Initialize other data structures used in
                    564:         *      this module.
                    565:         */
                    566: 
                    567:        queue_init(&reaper_queue);
                    568:        simple_lock_init(&reaper_lock, ETAP_THREAD_REAPER);
                    569:        mutex_init(&funnel_lock,0);
                    570: 
                    571: #ifndef MACHINE_STACK
                    572:        simple_lock_init(&stack_lock_data, ETAP_THREAD_STACK);
                    573: #endif  /* MACHINE_STACK */
                    574: 
                    575: #if    MACH_DEBUG
                    576:        simple_lock_init(&stack_usage_lock, ETAP_THREAD_STACK_USAGE);
                    577: #endif /* MACH_DEBUG */
                    578: 
                    579: #if    MACH_LDEBUG
                    580:        thr_sh_template.kthread = FALSE;
                    581:        thr_sh_template.mutex_count = 0;
                    582: #endif /* MACH_LDEBUG */
                    583: 
                    584:        /*
                    585:         *      Initialize any machine-dependent
                    586:         *      per-thread structures necessary.
                    587:         */
                    588:        thread_machine_init();
                    589: }
                    590: 
                    591: void
                    592: thread_reaper_enqueue(
                    593:        thread_t                thread)
                    594: {
                    595:        /*
                    596:         * thread lock is already held, splsched()
                    597:         * not necessary here.
                    598:         */
                    599:        simple_lock(&reaper_lock);
                    600: 
                    601:        enqueue_tail(&reaper_queue, (queue_entry_t)thread);
                    602: #if 0 /* CHECKME! */
                    603:        /*
                    604:         * Since thread has been put in the reaper_queue, it must no longer
                    605:         * be preempted (otherwise, it could be put back in a run queue).
                    606:         */
                    607:        thread->preempt = TH_NOT_PREEMPTABLE;
                    608: #endif
                    609: 
                    610:        simple_unlock(&reaper_lock);
                    611: 
                    612:        thread_call_enter(thread_reaper_call);
                    613: }
                    614: 
                    615: void
                    616: thread_terminate_self(void)
                    617: {
                    618:        register thread_t       thread = current_thread();
                    619:        thread_act_t            thr_act, prev_act;
                    620:        task_t                          task;
                    621:        sched_policy_t          *policy;
                    622:        spl_t                           s;
                    623: 
                    624:        /*      
                    625:         *      Check for rpc chain. If so, switch to the previous 
                    626:         *      activation, set error code, switch stacks and jump
                    627:         *      to mach_rpc_return_error.
                    628:         */
                    629:        thr_act = thread->top_act;
                    630:        thread = thr_act->thread;
                    631:        task = thr_act->task;
                    632: 
                    633:        if (task) {
                    634:                time_value_t    user_time, system_time;
                    635:                void                    *proc = NULL;
                    636: 
                    637:                /*
                    638:                 * Accumulate times for dead threads into task.
                    639:                 */
                    640:                thread_read_times(thread, &user_time, &system_time);
                    641: 
                    642:                task_lock(task);
                    643:                time_value_add(&task->total_user_time, &user_time);
                    644:                time_value_add(&task->total_system_time, &system_time);
                    645:                if (task->thr_act_count == 1)
                    646:                        proc = task->bsd_info;
                    647:                task_unlock(task);
                    648: 
                    649:                if (proc)
                    650:                        proc_exit(proc);
                    651:        }
                    652: 
                    653:        thread = act_lock_thread(thr_act);
                    654: 
                    655:        /* Unlink the thr_act from the task's thr_act list,
                    656:         * so it doesn't appear in calls to task_threads and such.
                    657:         * The thr_act still keeps its ref on the task, however.
                    658:         */
                    659:        task_lock(task);
                    660:        mutex_lock(&task->act_list_lock);
                    661:        queue_remove(&task->thr_acts, thr_act, thread_act_t, thr_acts);
                    662: 
                    663:        /*
                    664:         * Decrement the act count for this task.
                    665:         */
                    666:        task->thr_act_count--;
                    667:                
                    668: #if    THREAD_SWAPPER
                    669:        /*
                    670:         * Thread is supposed to be unswappable by now...
                    671:         */
                    672:        assert(thr_act->swap_state == TH_SW_UNSWAPPABLE ||
                    673:                       !(thread_swap_unwire_stack ||
                    674:                         thread_swap_unwire_user_stack));
                    675: #endif /* THREAD_SWAPPER */
                    676:        task->res_act_count--;
                    677:        thr_act->thr_acts.next = NULL;
                    678:        mutex_unlock(&task->act_list_lock);
                    679:        task_unlock(task);
                    680: 
                    681: #ifdef CALLOUT_RPC_MODEL
                    682:        if (thr_act->lower) {
                    683:                /*
                    684:                 * JMM - RPC will not be using a callout/stack manipulation
                    685:                 * mechanism.  instead we will let it return normally as if
                    686:                 * from a continuation.  Accordingly, these need to be cleaned
                    687:                 * up a bit.
                    688:                 */
                    689:                act_unlock(thr_act);
                    690:                act_switch_swapcheck(thread, (ipc_port_t)0);
                    691:                act_lock(thr_act);      /* hierarchy violation XXX */
                    692:                (void) switch_act(THR_ACT_NULL);
                    693:                assert(thr_act->ref_count == 1);        /* XXX */
                    694:                /* act_deallocate(thr_act);                XXX */
                    695:                prev_act = thread->top_act;
                    696:                /* disable preemption to protect kernel stack changes */
                    697:                disable_preemption();
                    698:                MACH_RPC_RET(prev_act) = KERN_RPC_SERVER_TERMINATED;
                    699:                 * machine_kernel_stack_init(thread, 
                    700:                 *      (void (*)(void)) mach_rpc_return_error);
                    701:                 * Load_context(thread);
                    702:                 */
                    703:                /* NOTREACHED */
                    704:        }
                    705: 
                    706: #else /* !CALLOUT_RPC_MODEL */
                    707: 
                    708:        assert(!thr_act->lower);
                    709: 
                    710: #endif /* CALLOUT_RPC_MODEL */
                    711: 
                    712:        act_unlock_thread(thr_act);
                    713: 
                    714:        s = splsched();
                    715:        thread_lock(thread);
                    716:        policy = &sched_policy[thread->policy];
                    717:        thr_act = thread->top_act;
                    718:        thread->active = FALSE;
                    719:        thread_unlock(thread);
                    720:        splx(s);
                    721: 
                    722:        policy->sp_ops.sp_thread_depress_abort(policy, thread);
                    723:        thread_cancel_timer();
                    724: 
                    725:        /* flush any lazy HW state while in own context */
                    726:        thread_machine_flush(thr_act);
                    727: 
                    728:        /* Reap times from dying threads */
                    729:        ipc_thr_act_disable(thr_act);
                    730: 
                    731:        /*
                    732:         * the test for task_active seems unnecessary because
                    733:         * the thread holds a reference to the task (so it
                    734:         * can't be deleted out from under it).
                    735:         */
                    736:        if( task && task->active) {
                    737: #if    THREAD_SWAPPER
                    738:                thread_swap_disable(thr_act);
                    739: #endif /* THREAD_SWAPPER */
                    740: 
                    741:                task_lock(task);
                    742: 
                    743:                /* Make act inactive iff it was born as a base activation */
                    744:                act_lock_thread(thr_act);
                    745:                if( thr_act->active && (thr_act->pool_port == IP_NULL))
                    746:                        act_disable_task_locked( thr_act );
                    747:                act_unlock_thread(thr_act);
                    748:                task_unlock( task );
                    749:        }
                    750: 
                    751:        thread_deallocate(thread); /* take caller's ref; 1 left for reaper */
                    752: 
                    753:        ipc_thread_terminate(thread);
                    754: 
                    755:        s = splsched();
                    756:        thread_lock(thread);
                    757:        thread->state |= (TH_HALTED|TH_TERMINATE);
                    758:        assert((thread->state & TH_UNINT) == 0);
                    759: #if 0 /* CHECKME! */
                    760:        /*
                    761:         * Since thread has been put in the reaper_queue, it must no longer
                    762:         * be preempted (otherwise, it could be put back in a run queue).
                    763:         */
                    764:        thread->preempt = TH_NOT_PREEMPTABLE;
                    765: #endif
                    766:        thread_mark_wait_locked(thread);
                    767:        thread_unlock(thread);
                    768:        /* splx(s); */
                    769: 
                    770:        ETAP_SET_REASON(thread, BLOCKED_ON_TERMINATION);
                    771:        thread_block((void (*)(void)) 0);
                    772:        panic("the zombie walks!");
                    773:        /*NOTREACHED*/
                    774: }
                    775: 
                    776: 
                    777: /*
                    778:  * Create a new thread in the specified activation (i.e. "populate" the
                    779:  * activation).  The activation can be either user or kernel, but it must
                    780:  * be brand-new: no thread, no pool_port, nobody else knows about it.
                    781:  * Doesn't start the thread running; use thread_setrun to start it.
                    782:  */
                    783: kern_return_t
                    784: thread_create_shuttle(
                    785:        thread_act_t                    thr_act,
                    786:        sp_attributes_t                 attributes,
                    787:        void                                    (*start_at)(void),
                    788:        thread_t                                *new_thread)
                    789: {
                    790:        thread_t                                new_shuttle;
                    791:        task_t                                  parent_task = thr_act->task;
                    792:        processor_set_t                 pset;
                    793:        kern_return_t                   result;
                    794:        sched_policy_t                  *policy;
                    795:        sf_return_t                             sfr;
                    796:        int                                             suspcnt;
                    797: 
                    798:        /*
                    799:         *      Allocate a thread and initialize static fields
                    800:         */
                    801:        new_shuttle = (thread_t)zalloc(thread_shuttle_zone);
                    802:        if (new_shuttle == THREAD_NULL)
                    803:                return (KERN_RESOURCE_SHORTAGE);
                    804: 
                    805:        *new_shuttle = thr_sh_template;
                    806: 
                    807:        /* Allocate space for scheduling information and attributes */
                    808:        /*** Think about integrating with shuttle structure someday ***/
                    809:        new_shuttle->sp_info = (sp_info_t)kalloc(max_sched_info_size);
                    810:        if (new_shuttle->sp_info == SP_INFO_NULL) {
                    811:                zfree(thread_shuttle_zone, (vm_offset_t)new_shuttle);
                    812:                return (KERN_RESOURCE_SHORTAGE);
                    813:        }
                    814:        new_shuttle->pending_sched_attr =
                    815:                                        (sp_attributes_t)kalloc(max_sched_attributes_size);
                    816:        if (new_shuttle->pending_sched_attr == SP_ATTRIBUTES_NULL) {
                    817:                kfree((vm_offset_t)new_shuttle->sp_info,
                    818:                                                        (vm_size_t)max_sched_info_size);
                    819:                zfree(thread_shuttle_zone, (vm_offset_t)new_shuttle);
                    820:                return (KERN_RESOURCE_SHORTAGE);
                    821:        }
                    822: 
                    823:        thread_lock_init(new_shuttle);
                    824:        rpc_lock_init(new_shuttle);
                    825:        wake_lock_init(new_shuttle);
                    826:        new_shuttle->sleep_stamp = sched_tick;
                    827: 
                    828:        /*
                    829:         * No need to lock thr_act, since it can't be known to anyone --
                    830:         * we set its suspend_count to one more than the task suspend_count
                    831:         * by calling thread_hold.
                    832:         */
                    833:        thr_act->user_stop_count = 1;
                    834:        for (suspcnt = thr_act->task->suspend_count + 1; suspcnt; --suspcnt)
                    835:                thread_hold(thr_act);
                    836: 
                    837:        simple_lock_init(&new_shuttle->lock, ETAP_THREAD_NEW);
                    838: 
                    839:        /*
                    840:         * Initialize system-dependent part.
                    841:         */
                    842:        result = thread_machine_create(new_shuttle, thr_act, start_at);
                    843:        if (result != KERN_SUCCESS) {
                    844:                kfree((vm_offset_t)new_shuttle->pending_sched_attr,
                    845:                                                        (vm_size_t)max_sched_attributes_size);
                    846:                kfree((vm_offset_t)new_shuttle->sp_info,
                    847:                                                        (vm_size_t)max_sched_info_size);
                    848:                zfree(thread_shuttle_zone, (vm_offset_t)new_shuttle);
                    849:                return (result);
                    850:        }
                    851: 
                    852:        /* Attach the thread to the activation.  */
                    853:        assert(!thr_act->thread);
                    854:        assert(!thr_act->pool_port);
                    855:        /* Synchronize with act_lock_thread() et al. */
                    856:        act_lock(thr_act);
                    857:        /* Thread holds a ref to the thr_act */
                    858:        act_locked_act_reference(thr_act);
                    859:        act_attach(thr_act, new_shuttle, 0);
                    860:        act_unlock(thr_act);
                    861: 
                    862:        /*
                    863:         *      Initialize runtime-dependent fields
                    864:         */
                    865:        thread_timer_setup(new_shuttle);
                    866:        machine_kernel_stack_init(new_shuttle, (void (*)(void))thread_continue);
                    867:        ipc_thread_init(new_shuttle);
                    868:        thread_start(new_shuttle, start_at);
                    869: 
                    870:        pset = parent_task->processor_set;
                    871:        if (!pset->active) {
                    872:                pset = &default_pset;
                    873:        }
                    874:        pset_lock(pset);
                    875: 
                    876:        task_lock(parent_task);
                    877: 
                    878:        if (attributes == SP_ATTRIBUTES_NULL)
                    879:                attributes = parent_task->sp_attributes;
                    880: 
                    881:        /* Associate the thread with that scheduling policy */
                    882:        new_shuttle->policy = attributes->policy_id;
                    883:        policy = &sched_policy[new_shuttle->policy];
                    884:        sfr = policy->sp_ops.sp_thread_attach(policy, new_shuttle);
                    885:        if (sfr != SF_SUCCESS)
                    886:                panic("thread_create_shuttle: sp_thread_attach");
                    887: 
                    888:        /* Indicate that no change in scheduling policy is pending */
                    889:        new_shuttle->pending_policy = POLICY_NULL;
                    890: 
                    891:        /* Associate the thread with the processor set */
                    892:        sfr = policy->sp_ops.sp_thread_processor_set(policy, new_shuttle, pset);
                    893:        if (sfr != SF_SUCCESS)
                    894:                panic("thread_create_shuttle: sp_thread_proceessor_set");
                    895: 
                    896:        /* Set the thread's scheduling parameters */
                    897:        sfr = policy->sp_ops.sp_thread_set(policy, new_shuttle, attributes);
                    898:        if (sfr != SF_SUCCESS)
                    899:                panic("thread_create_shuttle: sp_thread_set");
                    900: 
                    901:        /***
                    902:         *** ??? Have to do something here.  I want the call above to
                    903:         *** send the parameters to the policy and have the policy do
                    904:         *** its thing.  Unfortunately, I can't see the "artful" way
                    905:         *** to use the current MK SP routines to do this without
                    906:         *** alteration.
                    907:         ***
                    908:         *** I must return to this.
                    909:         ***
                    910:         *** Perhaps a state bit should be associated with each thread
                    911:         *** under the MK SP indicating whether that thread is runnable.
                    912:         *** If it is not, `compute_priority()' or one of its siblings
                    913:         *** is used to adjust scheduling parameter values; if it is
                    914:         *** runnable, then the scheduling parameter adjustments can be
                    915:         *** followed by code that tries to place the thread on the
                    916:         *** appropriate run queue, or tries to run it immediately.
                    917:         ***/
                    918: 
                    919: #if    ETAP_EVENT_MONITOR
                    920:        new_thread->etap_reason = 0;
                    921:        new_thread->etap_trace  = FALSE;
                    922: #endif /* ETAP_EVENT_MONITOR */
                    923: 
                    924:        new_shuttle->active = TRUE;
                    925: 
                    926:        /*
                    927:         *      Don't need to initialize because the context switch
                    928:         *      code will set it before it can be used.
                    929:         */
                    930:        if (!parent_task->active) {
                    931:                task_unlock(parent_task);
                    932:                pset_unlock(pset);
                    933:                thread_deallocate(new_shuttle);
                    934:                /* Drop ref we'd have given caller */
                    935:                thread_deallocate(new_shuttle);
                    936: 
                    937:                return (KERN_FAILURE);
                    938:        }
                    939: 
                    940:        task_unlock(parent_task);
                    941:        pset_unlock(pset);
                    942: 
                    943:        *new_thread = new_shuttle;
                    944: 
                    945:        {
                    946:          long dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4;
                    947: 
                    948:          KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_DATA, 1)) | DBG_FUNC_NONE,
                    949:                                new_shuttle, 0,0,0,0);
                    950: 
                    951:          kdbg_trace_string(parent_task->bsd_info, &dbg_arg1, &dbg_arg2, &dbg_arg3, 
                    952:                            &dbg_arg4);
                    953:           KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING, 1)) | DBG_FUNC_NONE,
                    954:                                dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0);
                    955:        }
                    956: 
                    957:        return (KERN_SUCCESS);
                    958: }
                    959: 
                    960: kern_return_t
                    961: thread_create(
                    962:        task_t                          task,
                    963:        thread_act_t            *new_act)
                    964: {
                    965:        thread_act_t            thr_act;
                    966:        thread_t                        thread;
                    967:        kern_return_t           result;
                    968:        sched_policy_t          *policy;
                    969:        sf_return_t                     sfr;
                    970:        spl_t                           s;
                    971:        extern void                     thread_bootstrap_return(void);
                    972: 
                    973:        result = act_create(task, NULL_PARAMS, &thr_act);
                    974:        if (result != KERN_SUCCESS)
                    975:                return (result);
                    976: 
                    977:        result = thread_create_shuttle(thr_act, SP_ATTRIBUTES_NULL,
                    978:                                                                                thread_bootstrap_return, &thread);
                    979:        if (result != KERN_SUCCESS) {
                    980:                thread_terminate(thr_act);
                    981:                act_deallocate(thr_act);
                    982:                return (result);
                    983:        }
                    984: 
                    985:        if (task->kernel_loaded)
                    986:                thread_user_to_kernel(thread);
                    987: 
                    988:        /* Start the thread running (it will immediately suspend itself).  */
                    989:        s = splsched();
                    990:        thread_ast_set(thr_act, AST_APC);
                    991:        thread_lock(thread);
                    992:        thread->state |= TH_RUN;        /*** ??? I think this is okay ***/
                    993: 
                    994:        /* Allow the thread to execute */
                    995:        policy = &sched_policy[thread->policy];
                    996:        sfr = policy->sp_ops.sp_thread_dispatch(policy, thread);
                    997:        if (sfr != SF_SUCCESS)
                    998:                panic("thread_create: sp_thread_dispatch");
                    999: 
                   1000:        thread_unlock(thread);
                   1001:        splx(s);
                   1002:        
                   1003:        /*****
                   1004:        act_lock_thread(thr_act);
                   1005:        thread_dowait( thr_act, FALSE);
                   1006:        act_unlock_thread(thr_act);
                   1007:        *****/
                   1008: 
                   1009:        *new_act = thr_act;
                   1010: 
                   1011:        return (KERN_SUCCESS);
                   1012: }
                   1013: 
                   1014: /*
                   1015:  * Update thread that belongs to a task created via kernel_task_create().
                   1016:  */
                   1017: void
                   1018: thread_user_to_kernel(
                   1019:        thread_t                thread)
                   1020: {
                   1021:        /*
                   1022:         * Used to set special swap_func here...
                   1023:         */
                   1024: }
                   1025: 
                   1026: kern_return_t
                   1027: thread_create_running(
                   1028:        register task_t         parent_task,
                   1029:        int                     flavor,
                   1030:        thread_state_t          new_state,
                   1031:        mach_msg_type_number_t  new_state_count,
                   1032:        thread_act_t                    *child_act)             /* OUT */
                   1033: {
                   1034:        register kern_return_t  result;
                   1035: 
                   1036:        result = thread_create(parent_task, child_act);
                   1037:        if (result != KERN_SUCCESS)
                   1038:                return (result);
                   1039: 
                   1040:        result = act_set_state(*child_act, flavor, new_state, new_state_count);
                   1041:        if (result != KERN_SUCCESS) {
                   1042:                (void) thread_terminate(*child_act);
                   1043:                return (result);
                   1044:        }
                   1045: 
                   1046:        result = thread_resume(*child_act);
                   1047:        if (result != KERN_SUCCESS) {
                   1048:                (void) thread_terminate(*child_act);
                   1049:                return (result);
                   1050:        }
                   1051: 
                   1052:        return (result);
                   1053: }
                   1054: 
                   1055: /*
                   1056:  *     kernel_thread:
                   1057:  *
                   1058:  *     Create and kernel thread in the specified task, and
                   1059:  *     optionally start it running.
                   1060:  */
                   1061: thread_t
                   1062: kernel_thread_with_attributes(
                   1063:        task_t                          task,
                   1064:        sp_attributes_t         attributes,
                   1065:        void                            (*start_at)(void),
                   1066:        boolean_t                       start_running)
                   1067: {
                   1068:        kern_return_t           result;
                   1069:        thread_t                        thread;
                   1070:        thread_act_t            thr_act;
                   1071:        sched_policy_t          *policy;
                   1072:        sf_return_t                     sfr;
                   1073:        spl_t                           s;
                   1074: 
                   1075:        result = act_create(task, NULL_PARAMS, &thr_act);
                   1076:        if (result != KERN_SUCCESS) {
                   1077:                printf("kernel_thread act_create %x\n", result);
                   1078:                panic("act_create failure");
                   1079:        }
                   1080: 
                   1081:        result = thread_create_shuttle(thr_act, attributes, start_at, &thread);
                   1082:        if (result != KERN_SUCCESS) {
                   1083:                printf("kernel_thread create_shuttle %x\n", result);
                   1084:                panic("create_shuttle failure");
                   1085:        }
                   1086: 
                   1087:        thread_swappable(thr_act, FALSE);
                   1088: 
                   1089:        s = splsched();
                   1090:        thread_lock(thread);
                   1091: 
                   1092:        thr_act = thread->top_act;
                   1093: #if    MACH_LDEBUG
                   1094:        thread->kthread = TRUE;
                   1095: #endif /* MACH_LDEBUG */
                   1096: 
                   1097:        if (start_running) {
                   1098:                policy = &sched_policy[thread->policy];
                   1099:                thread->state |= TH_RUN;
                   1100:                sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
                   1101:                if (sfr != SF_SUCCESS)
                   1102:                        panic("kernel_thread: sp_thread_unblock");
                   1103:        }
                   1104: 
                   1105:        thread_unlock(thread);
                   1106:        splx(s);
                   1107: 
                   1108:        act_deallocate(thr_act);
                   1109: 
                   1110:        if (start_running)
                   1111:                thread_resume(thr_act);
                   1112: 
                   1113:        return (thread);
                   1114: }
                   1115: 
                   1116: thread_t
                   1117: kernel_thread(
                   1118:        task_t                  task,
                   1119:        void                    (*start_at)(void))
                   1120: {
                   1121:        return kernel_thread_with_attributes(
                   1122:                                                task, SP_ATTRIBUTES_NULL, start_at, TRUE);
                   1123: }
                   1124: 
                   1125: unsigned int c_weird_pset_ref_exit = 0;        /* pset code raced us */
                   1126: 
                   1127: void
                   1128: thread_deallocate(
                   1129:        thread_t                        thread)
                   1130: {
                   1131:        task_t                          task;
                   1132:        processor_set_t         pset;
                   1133:        sched_policy_t          *policy;
                   1134:        sf_return_t                     sfr;
                   1135:        spl_t                           s;
                   1136: 
                   1137:        if (thread == THREAD_NULL)
                   1138:                return;
                   1139: 
                   1140:        /*
                   1141:         *      First, check for new count > 0 (the common case).
                   1142:         *      Only the thread needs to be locked.
                   1143:         */
                   1144:        s = splsched();
                   1145:        thread_lock(thread);
                   1146:        if (--thread->ref_count > 0) {
                   1147:                thread_unlock(thread);
                   1148:                splx(s);
                   1149:                return;
                   1150:        }
                   1151: 
                   1152:        /*
                   1153:         *      Count is zero.  However, the processor set's
                   1154:         *      thread list has an implicit reference to
                   1155:         *      the thread, and may make new ones.  Its lock also
                   1156:         *      dominate the thread lock.  To check for this, we
                   1157:         *      temporarily restore the one thread reference, unlock
                   1158:         *      the thread, and then lock the pset in the proper order.
                   1159:         */
                   1160:        assert(thread->ref_count == 0); /* Else this is an extra dealloc! */
                   1161:        thread->ref_count++;
                   1162:        thread_unlock(thread);
                   1163:        splx(s);
                   1164: 
                   1165: #if    MACH_HOST
                   1166:        thread_freeze(thread);
                   1167: #endif /* MACH_HOST */
                   1168: 
                   1169:        pset = thread->processor_set;
                   1170:        pset_lock(pset);
                   1171: 
                   1172:        s = splsched();
                   1173:        thread_lock(thread);
                   1174: 
                   1175:        if (--thread->ref_count > 0) {
                   1176: #if    MACH_HOST
                   1177:                boolean_t need_wakeup = FALSE;
                   1178:                /*
                   1179:                 *      processor_set made extra reference.
                   1180:                 */
                   1181:                /* Inline the unfreeze */
                   1182:                thread->may_assign = TRUE;
                   1183:                if (thread->assign_active) {
                   1184:                        need_wakeup = TRUE;
                   1185:                        thread->assign_active = FALSE;
                   1186:                }
                   1187: #endif /* MACH_HOST */
                   1188:                thread_unlock(thread);
                   1189:                splx(s);
                   1190:                pset_unlock(pset);
                   1191: #if    MACH_HOST
                   1192:                if (need_wakeup)
                   1193:                        thread_wakeup((event_t)&thread->assign_active);
                   1194: #endif /* MACH_HOST */
                   1195:                c_weird_pset_ref_exit++;
                   1196:                return;
                   1197:        }
                   1198: #if    MACH_HOST
                   1199:        assert(thread->assign_active == FALSE);
                   1200: #endif /* MACH_HOST */
                   1201: 
                   1202:        /*
                   1203:         *      Thread has no references - we can remove it.
                   1204:         */
                   1205: 
                   1206:        /*
                   1207:         *      A quick sanity check
                   1208:         */
                   1209:        if (thread == current_thread())
                   1210:            panic("thread deallocating itself");
                   1211: 
                   1212:        /* Detach thread (shuttle) from its sched policy */
                   1213:        policy = &sched_policy[thread->policy];
                   1214:        sfr = policy->sp_ops.sp_thread_detach(policy, thread);
                   1215:        if (sfr != SF_SUCCESS)
                   1216:                panic("thread_deallocate: sp_thread_detach");
                   1217: 
                   1218:        /* Release storage used for scheduling info and attributes */
                   1219:        assert(thread->pending_sched_attr != SP_ATTRIBUTES_NULL);
                   1220:        kfree((vm_offset_t) thread->pending_sched_attr,
                   1221:              (vm_size_t) max_sched_attributes_size);
                   1222:        assert(thread->sp_info != SP_INFO_NULL);
                   1223:        kfree((vm_offset_t) thread->sp_info,
                   1224:              (vm_size_t) max_sched_info_size);
                   1225: 
                   1226:        pset_remove_thread(pset, thread);
                   1227: 
                   1228:        thread_unlock(thread);          /* no more references - safe */
                   1229:        splx(s);
                   1230:        pset_unlock(pset);
                   1231: 
                   1232:        pset_deallocate(thread->processor_set);
                   1233: 
                   1234:        /* frees kernel stack & other MD resources */
                   1235:        thread->stack_privilege = 0;
                   1236:        thread_machine_destroy(thread);
                   1237: 
                   1238:        zfree(thread_shuttle_zone, (vm_offset_t) thread);
                   1239: }
                   1240: 
                   1241: void
                   1242: thread_reference(
                   1243:        thread_t        thread)
                   1244: {
                   1245:        spl_t           s;
                   1246: 
                   1247:        if (thread == THREAD_NULL)
                   1248:                return;
                   1249: 
                   1250:        s = splsched();
                   1251:        thread_lock(thread);
                   1252:        thread->ref_count++;
                   1253:        thread_unlock(thread);
                   1254:        splx(s);
                   1255: }
                   1256: 
                   1257: /*
                   1258:  * Called with "appropriate" thread-related locks held on
                   1259:  * thread and its top_act for synchrony with RPC (see
                   1260:  * act_lock_thread()).
                   1261:  */
                   1262: kern_return_t
                   1263: thread_info_shuttle(
                   1264:        register thread_act_t   thr_act,
                   1265:        thread_flavor_t                 flavor,
                   1266:        thread_info_t                   thread_info_out,        /* ptr to OUT array */
                   1267:        mach_msg_type_number_t  *thread_info_count)     /*IN/OUT*/
                   1268: {
                   1269:        register thread_t               thread = thr_act->thread;
                   1270:        int                                             state, flags;
                   1271:        spl_t                                   s;
                   1272: 
                   1273:        if (thread == THREAD_NULL)
                   1274:                return (KERN_INVALID_ARGUMENT);
                   1275: 
                   1276:        if (flavor == THREAD_BASIC_INFO) {
                   1277:            register thread_basic_info_t        basic_info;
                   1278: 
                   1279:            if (*thread_info_count < THREAD_BASIC_INFO_COUNT)
                   1280:                        return (KERN_INVALID_ARGUMENT);
                   1281: 
                   1282:            basic_info = (thread_basic_info_t) thread_info_out;
                   1283: 
                   1284:            s = splsched();
                   1285:            thread_lock(thread);
                   1286: 
                   1287:            /* fill in info */
                   1288: 
                   1289:            thread_read_times(thread, &basic_info->user_time,
                   1290:                                                                        &basic_info->system_time);
                   1291: 
                   1292:            /*** ??? fix me ***/
                   1293:            if (thread->policy & (POLICY_TIMESHARE|POLICY_RR|POLICY_FIFO)) {
                   1294:                        mk_sp_info_t    sp_info = (mk_sp_info_t)thread->sp_info;
                   1295: 
                   1296:                        /*
                   1297:                         *      Update lazy-evaluated scheduler info because someone wants it.
                   1298:                         */
                   1299:                    assert(sp_info != SP_INFO_NULL);
                   1300:                        if (sp_info->sched_stamp != sched_tick)
                   1301:                                update_priority(thread);
                   1302: 
                   1303:                        basic_info->sleep_time = 0;
                   1304: 
                   1305:                        /*
                   1306:                         *      To calculate cpu_usage, first correct for timer rate,
                   1307:                         *      then for 5/8 ageing.  The correction factor [3/5] is
                   1308:                         *      (1/(5/8) - 1).
                   1309:                         */
                   1310:                        basic_info->cpu_usage = sp_info->cpu_usage /
                   1311:                                                                                        (TIMER_RATE / TH_USAGE_SCALE);
                   1312:                        basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5;
                   1313: #if    SIMPLE_CLOCK
                   1314:                        /*
                   1315:                         *      Clock drift compensation.
                   1316:                         */
                   1317:                        basic_info->cpu_usage =
                   1318:                                        (basic_info->cpu_usage * 1000000) / sched_usec;
                   1319: #endif /* SIMPLE_CLOCK */
                   1320:            }
                   1321:                else
                   1322:                        basic_info->sleep_time = basic_info->cpu_usage = 0;
                   1323: 
                   1324:            basic_info->policy  = thread->policy;
                   1325: 
                   1326:            flags = 0;
                   1327:            if (thread->state & TH_SWAPPED_OUT)
                   1328:                        flags = TH_FLAGS_SWAPPED;
                   1329:            else
                   1330:                if (thread->state & TH_IDLE)
                   1331:                        flags = TH_FLAGS_IDLE;
                   1332: 
                   1333:            state = 0;
                   1334:            if (thread->state & TH_HALTED)
                   1335:                        state = TH_STATE_HALTED;
                   1336:            else
                   1337:                if (thread->state & TH_RUN)
                   1338:                        state = TH_STATE_RUNNING;
                   1339:            else
                   1340:                if (thread->state & TH_UNINT)
                   1341:                        state = TH_STATE_UNINTERRUPTIBLE;
                   1342:            else
                   1343:                if (thread->state & TH_SUSP)
                   1344:                        state = TH_STATE_STOPPED;
                   1345:            else
                   1346:                if (thread->state & TH_WAIT)
                   1347:                        state = TH_STATE_WAITING;
                   1348: 
                   1349:            basic_info->run_state = state;
                   1350:            basic_info->flags = flags;
                   1351: 
                   1352:            basic_info->suspend_count = thr_act->user_stop_count;
                   1353: 
                   1354:            thread_unlock(thread);
                   1355:            splx(s);
                   1356: 
                   1357:            *thread_info_count = THREAD_BASIC_INFO_COUNT;
                   1358: 
                   1359:            return (KERN_SUCCESS);
                   1360:        }
                   1361:        else
                   1362:        if (flavor == THREAD_SCHED_TIMESHARE_INFO) {
                   1363:                policy_timeshare_info_t         ts_info;
                   1364:                mk_sp_info_t                            sp_info = (mk_sp_info_t)thread->sp_info;
                   1365: 
                   1366:                if (*thread_info_count < POLICY_TIMESHARE_INFO_COUNT)
                   1367:                        return (KERN_INVALID_ARGUMENT);
                   1368: 
                   1369:                ts_info = (policy_timeshare_info_t)thread_info_out;
                   1370: 
                   1371:            s = splsched();
                   1372:                thread_lock(thread);
                   1373: 
                   1374:            if (thread->policy != POLICY_TIMESHARE) {
                   1375:                thread_unlock(thread);
                   1376:                        splx(s);
                   1377: 
                   1378:                        return (KERN_INVALID_POLICY);
                   1379:            }
                   1380: 
                   1381:            /*** ??? fix me ***/
                   1382:            assert(sp_info != SP_INFO_NULL);
                   1383:                ts_info->base_priority = sp_info->priority;
                   1384:                ts_info->max_priority = sp_info->max_priority;
                   1385:                ts_info->cur_priority = thread->sched_pri;
                   1386: 
                   1387:                ts_info->depressed = (sp_info->depress_priority >= 0);
                   1388:                ts_info->depress_priority = sp_info->depress_priority;
                   1389: 
                   1390:                thread_unlock(thread);
                   1391:            splx(s);
                   1392: 
                   1393:                *thread_info_count = POLICY_TIMESHARE_INFO_COUNT;
                   1394: 
                   1395:                return (KERN_SUCCESS);  
                   1396:        }
                   1397:        else
                   1398:        if (flavor == THREAD_SCHED_FIFO_INFO) {
                   1399:                policy_fifo_info_t                      fifo_info;
                   1400:                mk_sp_info_t                            sp_info = (mk_sp_info_t)thread->sp_info;
                   1401: 
                   1402:                if (*thread_info_count < POLICY_FIFO_INFO_COUNT)
                   1403:                        return (KERN_INVALID_ARGUMENT);
                   1404: 
                   1405:                fifo_info = (policy_fifo_info_t)thread_info_out;
                   1406: 
                   1407:            s = splsched();
                   1408:                thread_lock(thread);
                   1409: 
                   1410:            if (thread->policy != POLICY_FIFO) {
                   1411:                thread_unlock(thread);
                   1412:                        splx(s);
                   1413: 
                   1414:                        return (KERN_INVALID_POLICY);
                   1415:            }
                   1416: 
                   1417:            /*** ??? fix me ***/
                   1418:            assert(sp_info != SP_INFO_NULL);
                   1419:                fifo_info->base_priority = sp_info->priority;
                   1420:                fifo_info->max_priority = sp_info->max_priority;
                   1421: 
                   1422:                fifo_info->depressed = (sp_info->depress_priority >= 0);
                   1423:                fifo_info->depress_priority = sp_info->depress_priority;
                   1424: 
                   1425:                thread_unlock(thread);
                   1426:            splx(s);
                   1427: 
                   1428:                *thread_info_count = POLICY_FIFO_INFO_COUNT;
                   1429: 
                   1430:                return (KERN_SUCCESS);  
                   1431:        }
                   1432:        else
                   1433:        if (flavor == THREAD_SCHED_RR_INFO) {
                   1434:                policy_rr_info_t                        rr_info;
                   1435:                mk_sp_info_t                            sp_info = (mk_sp_info_t)thread->sp_info;
                   1436: 
                   1437:                if (*thread_info_count < POLICY_RR_INFO_COUNT)
                   1438:                        return (KERN_INVALID_ARGUMENT);
                   1439: 
                   1440:                rr_info = (policy_rr_info_t) thread_info_out;
                   1441: 
                   1442:            s = splsched();
                   1443:                thread_lock(thread);
                   1444: 
                   1445:            if (thread->policy != POLICY_RR) {
                   1446:                thread_unlock(thread);
                   1447:                        splx(s);
                   1448: 
                   1449:                        return (KERN_INVALID_POLICY);
                   1450:            }
                   1451: 
                   1452:            /*** ??? fix me ***/
                   1453:            assert(sp_info != SP_INFO_NULL);
                   1454:                rr_info->base_priority = sp_info->priority;
                   1455:                rr_info->max_priority = sp_info->max_priority;
                   1456: 
                   1457:            rr_info->quantum = (sp_info->sched_data * tick) / 1000;
                   1458: 
                   1459:                rr_info->depressed = (sp_info->depress_priority >= 0);
                   1460:                rr_info->depress_priority = sp_info->depress_priority;
                   1461: 
                   1462:                thread_unlock(thread);
                   1463:            splx(s);
                   1464: 
                   1465:                *thread_info_count = POLICY_RR_INFO_COUNT;
                   1466: 
                   1467:                return (KERN_SUCCESS);  
                   1468:        }
                   1469: 
                   1470:        return (KERN_INVALID_ARGUMENT);
                   1471: }
                   1472: 
                   1473: void
                   1474: thread_doreap(
                   1475:        register thread_t       thread)
                   1476: {
                   1477:        thread_act_t            thr_act;
                   1478:        struct ipc_port         *pool_port;
                   1479: 
                   1480: 
                   1481:        thr_act = thread_lock_act(thread);
                   1482:        assert(thr_act && thr_act->thread == thread);
                   1483: 
                   1484:        act_locked_act_reference(thr_act);
                   1485:        pool_port = thr_act->pool_port;
                   1486: 
                   1487:        /*
                   1488:         * Replace `act_unlock_thread()' with individual
                   1489:         * calls.  (`act_detach()' can change fields used
                   1490:         * to determine which locks are held, confusing
                   1491:         * `act_unlock_thread()'.)
                   1492:         */
                   1493:        rpc_unlock(thread);
                   1494:        if (pool_port != IP_NULL)
                   1495:                ip_unlock(pool_port);
                   1496:        act_unlock(thr_act);
                   1497: 
                   1498:        /* Remove the reference held by a rooted thread */
                   1499:        if (pool_port == IP_NULL)
                   1500:                act_deallocate(thr_act);
                   1501: 
                   1502:        /* Remove the reference held by the thread: */
                   1503:        act_deallocate(thr_act);
                   1504: }
                   1505: 
                   1506: static thread_call_data_t      thread_reaper_call_data;
                   1507: 
                   1508: /*
                   1509:  *     reaper_thread:
                   1510:  *
                   1511:  *     This kernel thread runs forever looking for threads to destroy
                   1512:  *     (when they request that they be destroyed, of course).
                   1513:  *
                   1514:  *     The reaper thread will disappear in the next revision of thread
                   1515:  *     control when it's function will be moved into thread_dispatch.
                   1516:  */
                   1517: void
                   1518: thread_reaper(void)
                   1519: {
                   1520:        register thread_t       thread;
                   1521:        spl_t                           s;
                   1522: 
                   1523:        s = splsched();
                   1524:        simple_lock(&reaper_lock);
                   1525: 
                   1526:        if (thread_reaper_call == NULL) {
                   1527:                thread_call_setup(&thread_reaper_call_data,     thread_reaper, NULL);
                   1528:                thread_reaper_call = &thread_reaper_call_data;
                   1529:        }
                   1530: 
                   1531:        while ((thread = (thread_t) dequeue_head(&reaper_queue)) != THREAD_NULL) {
                   1532:                simple_unlock(&reaper_lock);
                   1533: 
                   1534:                /*
                   1535:                 * wait for run bit to clear
                   1536:                 */
                   1537:                thread_lock(thread);
                   1538:                if (thread->state & TH_RUN)
                   1539:                        panic("thread reaper: TH_RUN");
                   1540:                thread_unlock(thread);
                   1541:                splx(s);
                   1542: 
                   1543:                thread_doreap(thread);
                   1544: 
                   1545:                s = splsched();
                   1546:                simple_lock(&reaper_lock);
                   1547:        }
                   1548: 
                   1549:        simple_unlock(&reaper_lock);
                   1550:        splx(s);
                   1551: }
                   1552: 
                   1553: #if    MACH_HOST
                   1554: /*
                   1555:  *     thread_assign:
                   1556:  *
                   1557:  *     Change processor set assignment.
                   1558:  *     Caller must hold an extra reference to the thread (if this is
                   1559:  *     called directly from the ipc interface, this is an operation
                   1560:  *     in progress reference).  Caller must hold no locks -- this may block.
                   1561:  */
                   1562: 
                   1563: kern_return_t
                   1564: thread_assign(
                   1565:        thread_act_t    thr_act,
                   1566:        processor_set_t new_pset)
                   1567: {
                   1568:        thread_t        thread;
                   1569: 
                   1570:        if (thr_act == THR_ACT_NULL || new_pset == PROCESSOR_SET_NULL)
                   1571:                return(KERN_INVALID_ARGUMENT);
                   1572:        thread = act_lock_thread(thr_act);
                   1573:        if (thread == THREAD_NULL) {
                   1574:                act_unlock_thread(thr_act);
                   1575:                return(KERN_INVALID_ARGUMENT);
                   1576:        }
                   1577: 
                   1578:        thread_freeze(thread);
                   1579:        thread_doassign(thread, new_pset, TRUE);
                   1580:        act_unlock_thread(thr_act);
                   1581:        return(KERN_SUCCESS);
                   1582: }
                   1583: 
                   1584: /*
                   1585:  *     thread_freeze:
                   1586:  *
                   1587:  *     Freeze thread's assignment.  Prelude to assigning thread.
                   1588:  *     Only one freeze may be held per thread.  
                   1589:  */
                   1590: void
                   1591: thread_freeze(
                   1592:        thread_t        thread)
                   1593: {
                   1594:        spl_t   s;
                   1595: 
                   1596:        /*
                   1597:         *      Freeze the assignment, deferring to a prior freeze.
                   1598:         */
                   1599: 
                   1600:        s = splsched();
                   1601:        thread_lock(thread);
                   1602:        while (thread->may_assign == FALSE) {
                   1603:                thread->assign_active = TRUE;
                   1604:                thread_sleep_simple_lock((event_t) &thread->assign_active,
                   1605:                                        simple_lock_addr(thread->lock), TRUE);
                   1606:                thread_lock(thread);
                   1607:        }
                   1608:        thread->may_assign = FALSE;
                   1609:        thread_unlock(thread);
                   1610:        splx(s);
                   1611: 
                   1612: }
                   1613: 
                   1614: /*
                   1615:  *     thread_unfreeze: release freeze on thread's assignment.
                   1616:  */
                   1617: void
                   1618: thread_unfreeze(
                   1619:        thread_t        thread)
                   1620: {
                   1621:        spl_t   s;
                   1622: 
                   1623:        s = splsched();
                   1624:        thread_lock(thread);
                   1625:        thread->may_assign = TRUE;
                   1626:        if (thread->assign_active) {
                   1627:                thread->assign_active = FALSE;
                   1628:                thread_unlock(thread);
                   1629:                splx(s);
                   1630:                thread_wakeup((event_t)&thread->assign_active);
                   1631:                return;
                   1632:        }
                   1633:        thread_unlock(thread);
                   1634:        splx(s);
                   1635: }
                   1636: 
                   1637: /*
                   1638:  *     thread_doassign:
                   1639:  *
                   1640:  *     Actually do thread assignment.  thread_will_assign must have been
                   1641:  *     called on the thread.  release_freeze argument indicates whether
                   1642:  *     to release freeze on thread.
                   1643:  *
                   1644:  *     Called with "appropriate" thread-related locks held on thread (see
                   1645:  *     act_lock_thread()).  Returns with thread unlocked.
                   1646:  */
                   1647: 
                   1648: void
                   1649: thread_doassign(
                   1650:        register thread_t               thread,
                   1651:        register processor_set_t        new_pset,
                   1652:        boolean_t                       release_freeze)
                   1653: {
                   1654:        register boolean_t              old_empty, new_empty;
                   1655:        register processor_set_t        pset;
                   1656:        boolean_t                       recompute_pri = FALSE;
                   1657:        int                             max_priority;
                   1658:        spl_t                           s;
                   1659:        thread_act_t                    thr_act = thread->top_act;
                   1660:        
                   1661:        /*
                   1662:         *      Check for silly no-op.
                   1663:         */
                   1664:        pset = thread->processor_set;
                   1665:        if (pset == new_pset) {
                   1666:                if (release_freeze)
                   1667:                        thread_unfreeze(thread);
                   1668:                return;
                   1669:        }
                   1670:        /*
                   1671:         *      Suspend the thread and stop it if it's not the current thread.
                   1672:         */
                   1673:        thread_hold(thr_act);
                   1674:        act_locked_act_reference(thr_act);
                   1675:        act_unlock_thread(thr_act);
                   1676:        if (thread != current_thread()) {
                   1677:                if (thread_stop_wait(thread) == FALSE ){
                   1678:                        (void)act_lock_thread(thr_act);
                   1679:                        thread_release(thr_act);
                   1680:                        act_locked_act_deallocate(thr_act);
                   1681:                        act_unlock_thread(thr_act);
                   1682:                        if (release_freeze )
                   1683:                                thread_unfreeze(thread);
                   1684:                        return;
                   1685:                }
                   1686:        }
                   1687:        /*
                   1688:         *      Had to release thread-related locks before acquiring pset
                   1689:         *      locks.
                   1690:         */
                   1691: 
                   1692:        /*
                   1693:         *      Lock both psets now, use ordering to avoid deadlocks.
                   1694:         */
                   1695: Restart:
                   1696:        if (pset < new_pset) {
                   1697:            pset_lock(pset);
                   1698:            pset_lock(new_pset);
                   1699:        } else {
                   1700:            pset_lock(new_pset);
                   1701:            pset_lock(pset);
                   1702:        }
                   1703: 
                   1704:        /*
                   1705:         *      Check if new_pset is ok to assign to.  If not, reassign
                   1706:         *      to default_pset.
                   1707:         */
                   1708:        if (!new_pset->active) {
                   1709:            pset_unlock(pset);
                   1710:            pset_unlock(new_pset);
                   1711:            new_pset = &default_pset;
                   1712:            goto Restart;
                   1713:        }
                   1714: 
                   1715:        /*
                   1716:         *      Grab the thread lock and move the thread.
                   1717:         *      Then drop the lock on the old pset and the thread's
                   1718:         *      reference to it.
                   1719:         */
                   1720: 
                   1721:        s = splsched();
                   1722:        thread_lock(thread);
                   1723: 
                   1724:        thread_change_psets(thread, pset, new_pset);
                   1725: 
                   1726:        old_empty = pset->empty;
                   1727:        new_empty = new_pset->empty;
                   1728: 
                   1729:        pset_unlock(pset);
                   1730:        pset_deallocate(pset);
                   1731: 
                   1732:         /*
                   1733:         *      Reset policy and priorities if needed. 
                   1734:         *
                   1735:         *      There are three rules for threads under assignment:
                   1736:         *
                   1737:          *      (1) If the new pset has the old policy enabled, keep the
                   1738:          *          old policy. Otherwise, use the default policy for the pset.
                   1739:          *      (2) The new limits will be the pset limits for the new policy.
                   1740:          *      (3) The new base will be the same as the old base unless either
                   1741:          *              (a) the new policy changed to the pset default policy;
                   1742:          *                  in this case, the new base is the default policy
                   1743:          *                  base,
                   1744:          *          or
                   1745:          *              (b) the new limits are different from the old limits;
                   1746:          *                  in this case, the new base is the new limits.
                   1747:          */
                   1748:        /*** ??? fix me to fit into MK Scheduling Framework ***/
                   1749:        max_priority = pset_max_priority(new_pset, thread->policy);
                   1750:        if ((thread->policy & new_pset->policies) == 0) {
                   1751:                thread->policy = new_pset->policy_default;
                   1752:                thread->sched_data =
                   1753:                        pset_sched_data(new_pset, thread->policy);
                   1754:                thread->unconsumed_quantum = thread->sched_data;
                   1755:                thread->priority =
                   1756:                        pset_base_priority(new_pset, thread->policy);
                   1757:                max_priority = pset_max_priority(new_pset, thread->policy);
                   1758:                recompute_pri = TRUE;
                   1759:        } 
                   1760:        else if (thread->max_priority != max_priority) {
                   1761:                thread->priority = max_priority;
                   1762:                 recompute_pri = TRUE;
                   1763:        }
                   1764: 
                   1765:        thread->max_priority = max_priority;
                   1766:        if ((thread->depress_priority >= 0) &&
                   1767:                (thread->depress_priority > thread->max_priority)) {
                   1768:                         thread->depress_priority = thread->max_priority;
                   1769:        }
                   1770: 
                   1771:        pset_unlock(new_pset);
                   1772: 
                   1773:        if (recompute_pri)
                   1774:                compute_priority(thread, TRUE);
                   1775: 
                   1776:        if (release_freeze) {
                   1777:                boolean_t need_wakeup = FALSE;
                   1778:                thread->may_assign = TRUE;
                   1779:                if (thread->assign_active) {
                   1780:                        thread->assign_active = FALSE;
                   1781:                        need_wakeup = TRUE;
                   1782:                }
                   1783:                thread_unlock(thread);
                   1784:                splx(s);
                   1785:                if (need_wakeup)
                   1786:                        thread_wakeup((event_t)&thread->assign_active);
                   1787:        } else {
                   1788:                thread_unlock(thread);
                   1789:                splx(s);
                   1790:        }
                   1791:        if (thread != current_thread())
                   1792:                thread_unstop(thread);
                   1793:        /*
                   1794:         *      Figure out hold status of thread.  Threads assigned to empty
                   1795:         *      psets must be held.  Therefore:
                   1796:         *              If old pset was empty release its hold.
                   1797:         *              Release our hold from above unless new pset is empty.
                   1798:         */
                   1799: 
                   1800:        (void)act_lock_thread(thr_act);
                   1801:        if (old_empty)
                   1802:                thread_release(thr_act);
                   1803:        if (!new_empty)
                   1804:                thread_release(thr_act);
                   1805:        act_locked_act_deallocate(thr_act);
                   1806:        act_unlock_thread(thr_act);
                   1807: 
                   1808:        /*
                   1809:         *      If current_thread is assigned, context switch to force
                   1810:         *      assignment to happen.  This also causes hold to take
                   1811:         *      effect if the new pset is empty.
                   1812:         */
                   1813:        if (thread == current_thread()) {
                   1814:                s = splsched();
                   1815:                mp_disable_preemption();
                   1816:                ast_on(AST_BLOCK);
                   1817:                mp_enable_preemption();
                   1818:                splx(s);
                   1819:        }
                   1820: }
                   1821: 
                   1822: #else  /* MACH_HOST */
                   1823: 
                   1824: kern_return_t
                   1825: thread_assign(
                   1826:        thread_act_t    thr_act,
                   1827:        processor_set_t new_pset)
                   1828: {
                   1829: #ifdef lint
                   1830:        thread++; new_pset++;
                   1831: #endif /* lint */
                   1832:        return(KERN_FAILURE);
                   1833: }
                   1834: #endif /* MACH_HOST */
                   1835: 
                   1836: /*
                   1837:  *     thread_assign_default:
                   1838:  *
                   1839:  *     Special version of thread_assign for assigning threads to default
                   1840:  *     processor set.
                   1841:  */
                   1842: kern_return_t
                   1843: thread_assign_default(
                   1844:        thread_act_t    thr_act)
                   1845: {
                   1846:        return (thread_assign(thr_act, &default_pset));
                   1847: }
                   1848: 
                   1849: /*
                   1850:  *     thread_get_assignment
                   1851:  *
                   1852:  *     Return current assignment for this thread.
                   1853:  */        
                   1854: kern_return_t
                   1855: thread_get_assignment(
                   1856:        thread_act_t    thr_act,
                   1857:        processor_set_t *pset)
                   1858: {
                   1859:        thread_t        thread;
                   1860: 
                   1861:        if (thr_act == THR_ACT_NULL)
                   1862:                return(KERN_INVALID_ARGUMENT);
                   1863:        thread = act_lock_thread(thr_act);
                   1864:        if (thread == THREAD_NULL) {
                   1865:                act_unlock_thread(thr_act);
                   1866:                return(KERN_INVALID_ARGUMENT);
                   1867:        }
                   1868:        *pset = thread->processor_set;
                   1869:        act_unlock_thread(thr_act);
                   1870:        pset_reference(*pset);
                   1871:        return(KERN_SUCCESS);
                   1872: }
                   1873: 
                   1874: /*
                   1875:  *     thread_wire:
                   1876:  *
                   1877:  *     Specify that the target thread must always be able
                   1878:  *     to run and to allocate memory.
                   1879:  */
                   1880: kern_return_t
                   1881: thread_wire(
                   1882:        host_t          host,
                   1883:        thread_act_t    thr_act,
                   1884:        boolean_t       wired)
                   1885: {
                   1886:        spl_t           s;
                   1887:        thread_t        thread;
                   1888:        extern void vm_page_free_reserve(int pages);
                   1889: 
                   1890:        if (thr_act == THR_ACT_NULL || host == HOST_NULL)
                   1891:                return (KERN_INVALID_ARGUMENT);
                   1892:        thread = act_lock_thread(thr_act);
                   1893:        if (thread ==THREAD_NULL) {
                   1894:                act_unlock_thread(thr_act);
                   1895:                return(KERN_INVALID_ARGUMENT);
                   1896:        }
                   1897: 
                   1898:        /*
                   1899:         * This implementation only works for the current thread.
                   1900:         * See stack_privilege.
                   1901:         */
                   1902:        if (thr_act != current_act())
                   1903:            return KERN_INVALID_ARGUMENT;
                   1904: 
                   1905:        s = splsched();
                   1906:        thread_lock(thread);
                   1907: 
                   1908:        if (wired) {
                   1909:            if (thread->vm_privilege == FALSE) 
                   1910:                    vm_page_free_reserve(1);    /* XXX */
                   1911:            thread->vm_privilege = TRUE;
                   1912:        } else {
                   1913:            if (thread->vm_privilege == TRUE) 
                   1914:                    vm_page_free_reserve(-1);   /* XXX */
                   1915:            thread->vm_privilege = FALSE;
                   1916:        }
                   1917: 
                   1918:        thread_unlock(thread);
                   1919:        splx(s);
                   1920:        act_unlock_thread(thr_act);
                   1921: 
                   1922:        /*
                   1923:         * Make the thread unswappable.
                   1924:         */
                   1925:        thread_swappable(thr_act, FALSE);
                   1926: 
                   1927:        return KERN_SUCCESS;
                   1928: }
                   1929: 
                   1930: /*
                   1931:  *     thread_collect_scan:
                   1932:  *
                   1933:  *     Attempt to free resources owned by threads.
                   1934:  */
                   1935: 
                   1936: void
                   1937: thread_collect_scan(void)
                   1938: {
                   1939:        /* This code runs very quickly! */
                   1940: }
                   1941: 
                   1942: boolean_t thread_collect_allowed = TRUE;
                   1943: unsigned thread_collect_last_tick = 0;
                   1944: unsigned thread_collect_max_rate = 0;          /* in ticks */
                   1945: 
                   1946: /*
                   1947:  *     consider_thread_collect:
                   1948:  *
                   1949:  *     Called by the pageout daemon when the system needs more free pages.
                   1950:  */
                   1951: 
                   1952: void
                   1953: consider_thread_collect(void)
                   1954: {
                   1955:        /*
                   1956:         *      By default, don't attempt thread collection more frequently
                   1957:         *      than once a second (one scheduler tick).
                   1958:         */
                   1959: 
                   1960:        if (thread_collect_max_rate == 0)
                   1961:                thread_collect_max_rate = 2;            /* sched_tick is a 1 second resolution 2 here insures at least 1 second interval */
                   1962: 
                   1963:        if (thread_collect_allowed &&
                   1964:            (sched_tick >
                   1965:             (thread_collect_last_tick + thread_collect_max_rate))) {
                   1966:                thread_collect_last_tick = sched_tick;
                   1967:                thread_collect_scan();
                   1968:        }
                   1969: }
                   1970: 
                   1971: #if    MACH_DEBUG
                   1972: #if    STACK_USAGE
                   1973: 
                   1974: vm_size_t
                   1975: stack_usage(
                   1976:        register vm_offset_t stack)
                   1977: {
                   1978:        int i;
                   1979: 
                   1980:        for (i = 0; i < KERNEL_STACK_SIZE/sizeof(unsigned int); i++)
                   1981:            if (((unsigned int *)stack)[i] != STACK_MARKER)
                   1982:                break;
                   1983: 
                   1984:        return KERNEL_STACK_SIZE - i * sizeof(unsigned int);
                   1985: }
                   1986: 
                   1987: /*
                   1988:  *     Machine-dependent code should call stack_init
                   1989:  *     before doing its own initialization of the stack.
                   1990:  */
                   1991: 
                   1992: static void
                   1993: stack_init(
                   1994:           register vm_offset_t stack,
                   1995:           unsigned int bytes)
                   1996: {
                   1997:        if (stack_check_usage) {
                   1998:            int i;
                   1999: 
                   2000:            for (i = 0; i < bytes / sizeof(unsigned int); i++)
                   2001:                ((unsigned int *)stack)[i] = STACK_MARKER;
                   2002:        }
                   2003: }
                   2004: 
                   2005: /*
                   2006:  *     Machine-dependent code should call stack_finalize
                   2007:  *     before releasing the stack memory.
                   2008:  */
                   2009: 
                   2010: void
                   2011: stack_finalize(
                   2012:        register vm_offset_t stack)
                   2013: {
                   2014:        if (stack_check_usage) {
                   2015:            vm_size_t used = stack_usage(stack);
                   2016: 
                   2017:            simple_lock(&stack_usage_lock);
                   2018:            if (used > stack_max_usage)
                   2019:                stack_max_usage = used;
                   2020:            simple_unlock(&stack_usage_lock);
                   2021:            if (used > stack_max_use) {
                   2022:                printf("stack usage = %x\n", used);
                   2023:                panic("stack overflow");
                   2024:            }
                   2025:        }
                   2026: }
                   2027: 
                   2028: #endif /*STACK_USAGE*/
                   2029: #endif /* MACH_DEBUG */
                   2030: 
                   2031: kern_return_t
                   2032: host_stack_usage(
                   2033:        host_t          host,
                   2034:        vm_size_t       *reservedp,
                   2035:        unsigned int    *totalp,
                   2036:        vm_size_t       *spacep,
                   2037:        vm_size_t       *residentp,
                   2038:        vm_size_t       *maxusagep,
                   2039:        vm_offset_t     *maxstackp)
                   2040: {
                   2041: #if !MACH_DEBUG
                   2042:         return KERN_NOT_SUPPORTED;
                   2043: #else
                   2044:        unsigned int total;
                   2045:        vm_size_t maxusage;
                   2046: 
                   2047:        if (host == HOST_NULL)
                   2048:                return KERN_INVALID_HOST;
                   2049: 
                   2050:        simple_lock(&stack_usage_lock);
                   2051:        maxusage = stack_max_usage;
                   2052:        simple_unlock(&stack_usage_lock);
                   2053: 
                   2054:        stack_statistics(&total, &maxusage);
                   2055: 
                   2056:        *reservedp = 0;
                   2057:        *totalp = total;
                   2058:        *spacep = *residentp = total * round_page(KERNEL_STACK_SIZE);
                   2059:        *maxusagep = maxusage;
                   2060:        *maxstackp = 0;
                   2061:        return KERN_SUCCESS;
                   2062: 
                   2063: #endif /* MACH_DEBUG */
                   2064: }
                   2065: 
                   2066: /*
                   2067:  * Return info on stack usage for threads in a specific processor set
                   2068:  */
                   2069: kern_return_t
                   2070: processor_set_stack_usage(
                   2071:        processor_set_t pset,
                   2072:        unsigned int    *totalp,
                   2073:        vm_size_t       *spacep,
                   2074:        vm_size_t       *residentp,
                   2075:        vm_size_t       *maxusagep,
                   2076:        vm_offset_t     *maxstackp)
                   2077: {
                   2078: #if !MACH_DEBUG
                   2079:         return KERN_NOT_SUPPORTED;
                   2080: #else
                   2081:        unsigned int total;
                   2082:        vm_size_t maxusage;
                   2083:        vm_offset_t maxstack;
                   2084: 
                   2085:        register thread_t *threads;
                   2086:        register thread_t thread;
                   2087: 
                   2088:        unsigned int actual;    /* this many things */
                   2089:        unsigned int i;
                   2090: 
                   2091:        vm_size_t size, size_needed;
                   2092:        vm_offset_t addr;
                   2093: 
                   2094:        if (pset == PROCESSOR_SET_NULL)
                   2095:                return KERN_INVALID_ARGUMENT;
                   2096: 
                   2097:        size = 0; addr = 0;
                   2098: 
                   2099:        for (;;) {
                   2100:                pset_lock(pset);
                   2101:                if (!pset->active) {
                   2102:                        pset_unlock(pset);
                   2103:                        return KERN_INVALID_ARGUMENT;
                   2104:                }
                   2105: 
                   2106:                actual = pset->thread_count;
                   2107: 
                   2108:                /* do we have the memory we need? */
                   2109: 
                   2110:                size_needed = actual * sizeof(thread_t);
                   2111:                if (size_needed <= size)
                   2112:                        break;
                   2113: 
                   2114:                /* unlock the pset and allocate more memory */
                   2115:                pset_unlock(pset);
                   2116: 
                   2117:                if (size != 0)
                   2118:                        kfree(addr, size);
                   2119: 
                   2120:                assert(size_needed > 0);
                   2121:                size = size_needed;
                   2122: 
                   2123:                addr = kalloc(size);
                   2124:                if (addr == 0)
                   2125:                        return KERN_RESOURCE_SHORTAGE;
                   2126:        }
                   2127: 
                   2128:        /* OK, have memory and the processor_set is locked & active */
                   2129: 
                   2130:        threads = (thread_t *) addr;
                   2131:        for (i = 0, thread = (thread_t) queue_first(&pset->threads);
                   2132:             i < actual;
                   2133:             i++,
                   2134:             thread = (thread_t) queue_next(&thread->pset_threads)) {
                   2135:                thread_reference(thread);
                   2136:                threads[i] = thread;
                   2137:        }
                   2138:        assert(queue_end(&pset->threads, (queue_entry_t) thread));
                   2139: 
                   2140:        /* can unlock processor set now that we have the thread refs */
                   2141:        pset_unlock(pset);
                   2142: 
                   2143:        /* calculate maxusage and free thread references */
                   2144: 
                   2145:        total = 0;
                   2146:        maxusage = 0;
                   2147:        maxstack = 0;
                   2148:        for (i = 0; i < actual; i++) {
                   2149:                int cpu;
                   2150:                thread_t thread = threads[i];
                   2151:                vm_offset_t stack = 0;
                   2152: 
                   2153:                /*
                   2154:                 *      thread->kernel_stack is only accurate if the
                   2155:                 *      thread isn't swapped and is not executing.
                   2156:                 *
                   2157:                 *      Of course, we don't have the appropriate locks
                   2158:                 *      for these shenanigans.
                   2159:                 */
                   2160: 
                   2161:                stack = thread->kernel_stack;
                   2162: 
                   2163:                for (cpu = 0; cpu < NCPUS; cpu++)
                   2164:                        if (cpu_data[cpu].active_thread == thread) {
                   2165:                                stack = active_stacks[cpu];
                   2166:                                break;
                   2167:                        }
                   2168: 
                   2169:                if (stack != 0) {
                   2170:                        total++;
                   2171: 
                   2172:                        if (stack_check_usage) {
                   2173:                                vm_size_t usage = stack_usage(stack);
                   2174: 
                   2175:                                if (usage > maxusage) {
                   2176:                                        maxusage = usage;
                   2177:                                        maxstack = (vm_offset_t) thread;
                   2178:                                }
                   2179:                        }
                   2180:                }
                   2181: 
                   2182:                thread_deallocate(thread);
                   2183:        }
                   2184: 
                   2185:        if (size != 0)
                   2186:                kfree(addr, size);
                   2187: 
                   2188:        *totalp = total;
                   2189:        *residentp = *spacep = total * round_page(KERNEL_STACK_SIZE);
                   2190:        *maxusagep = maxusage;
                   2191:        *maxstackp = maxstack;
                   2192:        return KERN_SUCCESS;
                   2193: 
                   2194: #endif /* MACH_DEBUG */
                   2195: }
                   2196: 
                   2197: 
                   2198: /*
                   2199:  * We consider a thread not preemptable if it is marked as either
                   2200:  * suspended or waiting.
                   2201:  */
                   2202: 
                   2203: boolean_t thread_not_preemptable(
                   2204:        thread_t        thread)
                   2205: {
                   2206: 
                   2207:        /* XXX - when scheduling framework and such is done, the
                   2208:           thread state check can be eliminated */
                   2209: 
                   2210:        if ((thread->state & (TH_WAIT|TH_SUSP)) || thread->preempt)
                   2211:                return (TRUE);
                   2212:        else
                   2213:                return (FALSE);
                   2214: }
                   2215: 
                   2216: 
                   2217: /*
                   2218:  *     thread_set_sched
                   2219:  *
                   2220:  *      Set scheduling policy and parameters for the given thread.
                   2221:  *      Policy must be a policy which is enabled for the
                   2222:  *      processor set.
                   2223:  *      (This should replace `thread_set_policy()' with the addition
                   2224:  *      of the MK Scheduling Framework to the kernel.)
                   2225:  */
                   2226: kern_return_t
                   2227: thread_set_sched(
                   2228:        thread_act_t                    thr_act,
                   2229:        policy_t                                policy_id,
                   2230:        sched_attr_t                    sched_attr,
                   2231:        mach_msg_type_number_t  sched_attrCnt)
                   2232: {
                   2233:        thread_t                                thread;
                   2234:        processor_set_t                 pset;
                   2235:        kern_return_t                   result = KERN_SUCCESS;
                   2236:        sched_policy_t                  *policy;
                   2237:        sf_return_t                             sfr;
                   2238:        boolean_t                               do_dispatch = FALSE;
                   2239:        spl_t                                   s;
                   2240: 
                   2241:        if (thr_act == THR_ACT_NULL)
                   2242:                return (KERN_INVALID_ARGUMENT);
                   2243: 
                   2244:        thread = act_lock_thread(thr_act);
                   2245:        if (    thread == THREAD_NULL                                                           ||
                   2246:                        (sched_attrCnt * sizeof(int)) !=
                   2247:                                sched_policy[policy_id].sched_attributes_size           ) {
                   2248:                act_unlock_thread(thr_act);
                   2249:                return(KERN_INVALID_ARGUMENT);
                   2250:        }
                   2251: 
                   2252:        if (invalid_policy(policy_id)) {
                   2253:                act_unlock_thread(thr_act);
                   2254:                return(KERN_INVALID_POLICY);
                   2255:        }
                   2256: 
                   2257:        /* coordinate changes to thread scheduling state with others */
                   2258:        s = splsched();
                   2259:        thread_lock(thread);
                   2260: 
                   2261:        /* see if thread's policy is to be changed */
                   2262:        if (thread->policy != policy_id) {
                   2263:                /* it is; see if the target is executing */
                   2264:                if (thread != current_thread()) {       /*** fix for SMP ***/
                   2265:                        /* it is not; detach from old policy */
                   2266:                        policy = &sched_policy[thread->policy];
                   2267:                        sfr = policy->sp_ops.sp_thread_detach(policy, thread);
                   2268:                        if (sfr != SF_SUCCESS)
                   2269:                                panic("thread_set_sched: sp_thread_detach");
                   2270: 
                   2271:                        /* attach to this policy */
                   2272:                        policy = &sched_policy[policy_id];
                   2273:                        sfr = policy->sp_ops.sp_thread_attach(policy, thread);
                   2274:                        if (sfr != SF_SUCCESS) {
                   2275:                                thread_unlock(thread);
                   2276:                                splx(s);
                   2277:                                act_unlock_thread(thr_act);
                   2278:                                return(KERN_FAILURE);
                   2279:                        }
                   2280: 
                   2281:                        /* remember to dispatch thread after setting parms */
                   2282:                        do_dispatch = TRUE;
                   2283:                }
                   2284:                else {
                   2285:                        /* target is currently executing */
                   2286:                        /* defer policy change until thread leaves processor */
                   2287:                        thread->pending_policy = policy_id;
                   2288:                        bcopy((char *)sched_attr,
                   2289:                              (char *)thread->pending_sched_attr,
                   2290:                              (sched_attrCnt * sizeof(int)));
                   2291: 
                   2292:                        /* try to get off processor to effect change */
                   2293:                        thread_unlock(thread);
                   2294:                        splx(s);
                   2295:                        act_unlock_thread(thr_act);
                   2296:                        thread_block((void (*)(void)) 0);
                   2297: 
                   2298:                        /* by now, new attributes have been installed */
                   2299:                        act_lock_thread(thr_act);
                   2300:                        /*** check to see it's same thread? ***/
                   2301: 
                   2302:                        s = splsched();
                   2303:                        thread_lock(thread);
                   2304:                        result = (thread->change_sfr == SF_SUCCESS)?
                   2305:                                                KERN_SUCCESS : KERN_FAILURE;
                   2306:                        thread_unlock(thread);
                   2307:                        splx(s);
                   2308:                        act_unlock_thread(thr_act);
                   2309:                        return(result);
                   2310:                }
                   2311: 
                   2312:        }
                   2313: 
                   2314:        /* call policy-specific routine to install new scheduling parameters */
                   2315:        policy = &sched_policy[policy_id];
                   2316:        sfr = policy->sp_ops.sp_thread_set(
                   2317:                                                policy, thread, (sp_attributes_t)sched_attr);
                   2318: 
                   2319:        /* dispatch thread under new policy, if appropriate */
                   2320:        if (do_dispatch == TRUE && sfr == SF_SUCCESS) {
                   2321:                sfr = policy->sp_ops.sp_thread_dispatch(policy, thread);
                   2322:        }
                   2323: 
                   2324:        thread_unlock(thread);
                   2325:        splx(s);
                   2326: 
                   2327:        if (sfr != SF_SUCCESS)
                   2328:                result = KERN_FAILURE;
                   2329: 
                   2330:        act_unlock_thread(thr_act);
                   2331:        return(result);
                   2332: }
                   2333: 
                   2334: 
                   2335: /*
                   2336:  *     thread_get_sched
                   2337:  *
                   2338:  *      Get scheduling policy and parameters for the given thread.
                   2339:  *      (This was added as part of the MK Scheduling Framework.)
                   2340:  */
                   2341: kern_return_t
                   2342: thread_get_sched(
                   2343:        thread_act_t                    thr_act,
                   2344:        policy_t                                *policy_id_out,
                   2345:        sched_attr_t                    sched_attr,
                   2346:        mach_msg_type_number_t  *sched_attrCnt)
                   2347: {
                   2348:        thread_t                                thread;
                   2349:        kern_return_t                   result = KERN_SUCCESS;
                   2350:        policy_t                                policy_id;
                   2351:        sched_policy_t                  *policy;
                   2352:        sf_return_t                             sfr;
                   2353:        int                                             size;
                   2354:        spl_t                                   s;
                   2355: 
                   2356:        if (thr_act == THR_ACT_NULL)
                   2357:                return (KERN_INVALID_ARGUMENT);
                   2358: 
                   2359:        thread = act_lock_thread(thr_act);
                   2360:        if (thread == THREAD_NULL) {
                   2361:                act_unlock_thread(thr_act);
                   2362:                *policy_id_out = POLICY_NULL;
                   2363:                return(KERN_INVALID_ARGUMENT);
                   2364:        }
                   2365: 
                   2366:        size = *sched_attrCnt * sizeof(int);
                   2367: 
                   2368:        /* coordinate changes to thread scheduling state with others */
                   2369:        s = splsched();
                   2370:        thread_lock(thread);
                   2371: 
                   2372:        policy_id = thread->policy;
                   2373:        if (size < sched_policy[policy_id].sched_attributes_size) {
                   2374:                thread_unlock(thread);
                   2375:                splx(s);
                   2376:                act_unlock_thread(thr_act);
                   2377:                *policy_id_out = policy_id;
                   2378:                return(KERN_INVALID_ARGUMENT);
                   2379:        }
                   2380: 
                   2381:        /* note policy for caller */
                   2382:        *policy_id_out = policy_id;
                   2383: 
                   2384:        /* call policy-specific routine */
                   2385:        policy = &sched_policy[policy_id];
                   2386:        sfr = policy->sp_ops.sp_thread_get(
                   2387:                                                policy, thread, (sp_attributes_t)sched_attr, size);
                   2388: 
                   2389:        if (sfr != SF_SUCCESS)
                   2390:                result = KERN_FAILURE;
                   2391: 
                   2392:        *sched_attrCnt = policy->sched_attributes_size / sizeof(int);
                   2393: 
                   2394:        thread_unlock(thread);
                   2395:        splx(s);
                   2396:        act_unlock_thread(thr_act);
                   2397:        return(result);
                   2398: }
                   2399: 
                   2400: boolean_t
                   2401: thread_get_funneled(
                   2402:        void)
                   2403: {
                   2404:        return((current_thread()->funnel_state & TH_FN_OWNED) == TH_FN_OWNED);
                   2405: }
                   2406: 
                   2407: boolean_t
                   2408: thread_set_funneled(
                   2409:        boolean_t       funneled)
                   2410: {
                   2411:        thread_t        cur_thread;
                   2412:        boolean_t       funnel_state_prev;
                   2413: 
                   2414:        cur_thread = current_thread();
                   2415:        funnel_state_prev = ((cur_thread->funnel_state & TH_FN_OWNED) == TH_FN_OWNED);
                   2416: 
                   2417:        if (funnel_state_prev != funneled) {
                   2418:                if (funneled == TRUE) {
                   2419:                        mutex_lock(&funnel_lock);
                   2420:                        cur_thread->funnel_state |= TH_FN_OWNED;
                   2421:                } else {
                   2422:                        cur_thread->funnel_state &= ~TH_FN_OWNED;
                   2423:                        mutex_unlock(&funnel_lock);
                   2424:                }
                   2425:        }
                   2426:        return(funnel_state_prev);
                   2427: }
                   2428: 
                   2429: void
                   2430: thread_set_cont_arg(int arg)
                   2431: {
                   2432:   thread_t th = current_thread();
                   2433:   th->cont_arg = arg; 
                   2434: }
                   2435: 
                   2436: int
                   2437: thread_get_cont_arg(void)
                   2438: {
                   2439:   thread_t th = current_thread();
                   2440:   return(th->cont_arg); 
                   2441: }
                   2442: 
                   2443: /*
                   2444:  * Export routines to other components for things that are done as macros
                   2445:  * within the osfmk component.
                   2446:  */
                   2447: #undef thread_should_halt
                   2448: boolean_t
                   2449: thread_should_halt(
                   2450:        thread_shuttle_t th)
                   2451: {
                   2452:        return(thread_should_halt_fast(th));
                   2453: }

unix.superglobalmegacorp.com

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