Annotation of XNU/osfmk/kern/thread_act.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:  * Copyright (c) 1993 The University of Utah and
                     27:  * the Center for Software Science (CSS).  All rights reserved.
                     28:  *
                     29:  * Permission to use, copy, modify and distribute this software and its
                     30:  * documentation is hereby granted, provided that both the copyright
                     31:  * notice and this permission notice appear in all copies of the
                     32:  * software, derivative works or modified versions, and any portions
                     33:  * thereof, and that both notices appear in supporting documentation.
                     34:  *
                     35:  * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
                     36:  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
                     37:  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     38:  *
                     39:  * CSS requests users of this software to return to [email protected] any
                     40:  * improvements that they make and grant CSS redistribution rights.
                     41:  *
                     42:  *     Author: Bryan Ford, University of Utah CSS
                     43:  *
                     44:  *     Thread_Activation management routines
                     45:  */
                     46: 
                     47: #include <cpus.h>
                     48: #include <task_swapper.h>
                     49: #include <mach/kern_return.h>
                     50: #include <mach/alert.h>
                     51: #include <kern/etap_macros.h>
                     52: #include <kern/mach_param.h>
                     53: #include <kern/zalloc.h>
                     54: #include <kern/thread.h>
                     55: #include <kern/thread_swap.h>
                     56: #include <kern/task.h>
                     57: #include <kern/task_swap.h>
                     58: #include <kern/thread_act.h>
                     59: #include <kern/thread_pool.h>
                     60: #include <kern/sched_prim.h>
                     61: #include <kern/misc_protos.h>
                     62: #include <kern/assert.h>
                     63: #include <kern/exception.h>
                     64: #include <kern/ipc_mig.h>
                     65: #include <kern/ipc_tt.h>
                     66: #include <kern/profile.h>
                     67: #include <kern/machine.h>
                     68: #include <kern/spl.h>
                     69: #include <kern/syscall_subr.h>
                     70: #include <kern/sync_lock.h>
                     71: #include <kern/sf.h>
                     72: #include <kern/mk_sp.h>        /*** ??? fix so this can be removed ***/
                     73: #include <mach_prof.h>
                     74: #include <mach/rpc.h>
                     75: 
                     76: /*
                     77:  * Debugging printf control
                     78:  */
                     79: #if    MACH_ASSERT
                     80: unsigned int   watchacts =       0 /* WA_ALL */
                     81:                                    ;   /* Do-it-yourself & patchable */
                     82: #endif
                     83: 
                     84: /*
                     85:  * Track the number of times we need to swapin a thread to deallocate it.
                     86:  */
                     87: int act_free_swapin = 0;
                     88: extern boolean_t thread_swap_unwire_stack;
                     89: 
                     90: #if    THREAD_SWAP_UNWIRE_USER_STACK
                     91: extern boolean_t thread_swap_unwire_user_stack;
                     92: #else  /* THREAD_SWAP_UNWIRE_USER_STACK */
                     93: #define thread_swap_unwire_user_stack  FALSE
                     94: #endif /* THREAD_SWAP_UNWIRE_USER_STACK */
                     95: 
                     96: /*
                     97:  * Forward declarations for functions local to this file.
                     98:  */
                     99: kern_return_t  act_abort( thread_act_t, int);
                    100: void           special_handler(ReturnHandler *, thread_act_t);
                    101: void           nudge(thread_act_t);
                    102: kern_return_t  act_set_state_locked(thread_act_t, int,
                    103:                                        thread_state_t,
                    104:                                        mach_msg_type_number_t);
                    105: kern_return_t  act_get_state_locked(thread_act_t, int,
                    106:                                        thread_state_t,
                    107:                                        mach_msg_type_number_t *);
                    108: void           act_set_apc(thread_act_t);
                    109: void           act_clr_apc(thread_act_t);
                    110: void           act_user_to_kernel(thread_act_t);
                    111: void           act_ulock_release_all(thread_act_t thr_act);
                    112: 
                    113: kern_return_t  terminate_empty_act(thread_act_t);
                    114: void           install_special_handler_locked(thread_act_t);
                    115: 
                    116: static zone_t  thr_act_zone;
                    117: 
                    118: /*
                    119:  * Thread interfaces accessed via a thread_activation:
                    120:  */
                    121: 
                    122: /*
                    123:  * Terminate a thread.  Called with nothing locked.
                    124:  * Returns same way.
                    125:  */
                    126: kern_return_t
                    127: thread_terminate(
                    128:        register thread_act_t   thr_act)
                    129: {
                    130:        thread_t        thread;
                    131:        task_t          task;
                    132:        struct ipc_port *iplock;
                    133:        kern_return_t   ret = KERN_INVALID_ARGUMENT;
                    134: #if    NCPUS > 1
                    135:        boolean_t       held;
                    136: #endif /* NCPUS > 1 */
                    137: 
                    138:        if (thr_act == THR_ACT_NULL)
                    139:                return(ret);
                    140: 
                    141:        if (((thr_act->task == kernel_task) || (thr_act->kernel_loaded == TRUE))
                    142:            && (current_act() != thr_act)) {
                    143:                return(KERN_FAILURE);
                    144:         }
                    145: 
                    146: #if    THREAD_SWAPPER
                    147:        thread_swap_disable(thr_act);
                    148: #endif /* THREAD_SWAPPER */
                    149: 
                    150:        /*
                    151:         * Lock task containing target thread before (really)
                    152:         * getting thread locks.
                    153:         */
                    154:        act_lock(thr_act);
                    155:        task = thr_act->task;
                    156:        act_unlock(thr_act);
                    157:        task_lock(task);
                    158: 
                    159:        thread = act_lock_thread(thr_act);
                    160:        if (!thr_act->active) {
                    161:                act_unlock_thread(thr_act);
                    162:                task_unlock(task);
                    163:                return(KERN_TERMINATED);
                    164:        }
                    165: 
                    166:        /*
                    167:         *      Break IPC control over the thread.
                    168:         */
                    169:        ipc_thr_act_disable_act_locked(thr_act);
                    170: 
                    171: #if    NCPUS > 1
                    172:        /* 
                    173:         * Make sure this thread enters the kernel
                    174:         */
                    175:        if (thread != THREAD_NULL && thread != current_thread()) {
                    176:                thread_hold(thr_act);
                    177:                act_unlock_thread(thr_act);
                    178: #if 1 /* Grenoble */
                    179:                if (!thread_stop_wait(thread)) {
                    180:                        ret = KERN_ABORTED;
                    181:                        (void)act_lock_thread(thr_act);
                    182:                        thread_release(thr_act);
                    183:                        act_unlock_thread(thr_act);
                    184:                        task_unlock(task);
                    185:                        return (ret);
                    186:                }
                    187: #else
                    188:                thread_stop_wait(thread);
                    189: #endif
                    190:                held = TRUE;
                    191:                (void)act_lock_thread(thr_act);
                    192:        } else {
                    193:                held = FALSE;
                    194:        }
                    195: #endif /* NCPUS > 1 */
                    196: 
                    197: #if 0 /* Grenoble */
                    198:        /*
                    199:         * Lock task containing target.
                    200:         * Use mutex_try to respect lock ordering.
                    201:         */
                    202: 
                    203:        task = thr_act->task;
                    204:        if (!mutex_try(&task->lock)) {
                    205:                act_unlock_thread(thr_act);
                    206:                task_lock(task);
                    207:                thread = act_lock_thread(thr_act);
                    208:        }
                    209:                
                    210: 
                    211:        if (!thr_act->active) {
                    212:                act_unlock_thread(thr_act);
                    213:                task_unlock(task);
                    214:                ret = KERN_TERMINATED;
                    215:                goto out;
                    216:        }
                    217: 
                    218:        /*
                    219:         *      Break IPC control over the thread.
                    220:         */
                    221:        ipc_thr_act_disable_act_locked(thr_act);
                    222: 
                    223: #endif
                    224:        /*
                    225:         * Check for terminating an empty thread_act -- detach it from
                    226:         * its task, then deallocate its remaining refs here.
                    227:         */
                    228:        if (thr_act->thread == THREAD_NULL) {
                    229:                iplock = thr_act->pool_port;    /* remember for unlock call */
                    230:                ret = terminate_empty_act( thr_act );
                    231: 
                    232:                /*
                    233:                 * Release locks individually. (`act_unlock_thread()'
                    234:                 * will not work since `pool_port' field has changed.)
                    235:                 */
                    236:                ip_unlock(iplock);
                    237:                act_unlock(thr_act);
                    238:        }
                    239:        else {
                    240:                assert(thr_act->active);
                    241:                act_disable_task_locked(thr_act);
                    242:                ret = act_abort(thr_act,FALSE);
                    243:                act_unlock_thread(thr_act);
                    244:        }
                    245: 
                    246:        task_unlock(task);
                    247: 
                    248:        if (((thr_act->task == kernel_task) || (thr_act->kernel_loaded == TRUE))
                    249:            && (current_act() == thr_act)) {
                    250:                ast_taken(FALSE, AST_APC, 0);
                    251:                panic("thread_terminate(): returning from ast_taken() for %x kernel activation\n", thr_act);
                    252:         }
                    253: 
                    254: #if 0 /* Grenoble */
                    255: out:
                    256: #endif
                    257: 
                    258: #if    NCPUS > 1
                    259:        if (held) {
                    260:                thread_unstop(thread);
                    261:                (void)act_lock_thread(thr_act);
                    262:                thread_release(thr_act);
                    263:                act_unlock_thread(thr_act);
                    264:        }
                    265: #endif /* NCPUS > 1 */
                    266:        return(ret);
                    267: }
                    268: 
                    269: /*
                    270:  * Called with empty thread activation and its pool port locked.
                    271:  * Activation is currently "active."
                    272:  * Task containing activation is also locked.
                    273:  * Returns the same way.
                    274:  */
                    275: kern_return_t
                    276: terminate_empty_act( thread_act_t thr_act ) {
                    277:        /*
                    278:         * remove the activation from the pool port
                    279:         * (this prevents it from being used)
                    280:         */
                    281:        if (thr_act->pool_port) {
                    282:                act_locked_act_set_thread_pool(thr_act, IP_NULL);
                    283:        }
                    284: 
                    285:        /*
                    286:         * disassociate the thread from the task
                    287:         */
                    288:        assert(thr_act->active);
                    289:        act_disable_task_locked( thr_act );
                    290: 
                    291:        return KERN_SUCCESS;
                    292: }
                    293: 
                    294: /*
                    295:  *     thread_hold:
                    296:  *
                    297:  *     Suspend execution of the specified thread.
                    298:  *     This is a recursive-style suspension of the thread, a count of
                    299:  *     suspends is maintained.
                    300:  *
                    301:  *     Called with thr_act locked "appropriately" for synchrony with
                    302:  *     RPC (see act_lock_thread()).  Returns same way.
                    303:  */
                    304: void
                    305: thread_hold(
                    306:        register thread_act_t   thr_act)
                    307: {
                    308:        if (thr_act->suspend_count++ == 0) {
                    309:                install_special_handler(thr_act);
                    310:                nudge(thr_act);
                    311:        }
                    312: }
                    313: 
                    314: /*
                    315:  * Decrement internal suspension count for thr_act, setting thread
                    316:  * runnable when count falls to zero.
                    317:  *
                    318:  * Called with thr_act locked "appropriately" for synchrony
                    319:  * with RPC (see act_lock_thread()).
                    320:  */
                    321: void
                    322: thread_release(
                    323:        register thread_act_t   thr_act)
                    324: {
                    325:        if( thr_act->suspend_count &&
                    326:                (--thr_act->suspend_count == 0) )
                    327:                nudge( thr_act );
                    328: }
                    329: 
                    330: kern_return_t
                    331: thread_suspend(
                    332:        register thread_act_t   thr_act)
                    333: {
                    334:        thread_t                thread;
                    335: 
                    336:        if (thr_act == THR_ACT_NULL) {
                    337:                return(KERN_INVALID_ARGUMENT);
                    338:        }
                    339:        thread = act_lock_thread(thr_act);
                    340:        if (!thr_act->active) {
                    341:                act_unlock_thread(thr_act);
                    342:                return(KERN_TERMINATED);
                    343:        }
                    344:        if (thr_act->user_stop_count++ == 0 &&
                    345:                thr_act->suspend_count++ == 0 ) {
                    346:                install_special_handler(thr_act);
                    347:                if (thread &&
                    348:                        thr_act == thread->top_act && thread != current_thread()) {
                    349:                        nudge(thr_act);
                    350:                        act_unlock_thread(thr_act);
                    351:                        (void)thread_wait(thread);
                    352:                }
                    353:                else {
                    354:                        /*
                    355:                         * No need to wait for target thread
                    356:                         */
                    357:                        act_unlock_thread(thr_act);
                    358:                }
                    359:        }
                    360:        else {
                    361:                /*
                    362:                 * Thread is already suspended
                    363:                 */
                    364:                act_unlock_thread(thr_act);
                    365:        }
                    366:        return(KERN_SUCCESS);
                    367: }
                    368: 
                    369: kern_return_t
                    370: thread_resume(
                    371:        register thread_act_t   thr_act)
                    372: {
                    373:        register kern_return_t  ret;
                    374:        spl_t                   s;
                    375:        thread_t                thread;
                    376: 
                    377:        if (thr_act == THR_ACT_NULL)
                    378:                return(KERN_INVALID_ARGUMENT);
                    379:        thread = act_lock_thread(thr_act);
                    380:        ret = KERN_SUCCESS;
                    381: 
                    382:        if (thr_act->active) {
                    383:                if (thr_act->user_stop_count > 0) {
                    384:                        if( --thr_act->user_stop_count == 0 ) {
                    385:                                --thr_act->suspend_count;
                    386:                                nudge( thr_act );
                    387:                        }
                    388:                }
                    389:                else
                    390:                        ret = KERN_FAILURE;
                    391:        }
                    392:        else
                    393:                ret = KERN_TERMINATED;
                    394:        act_unlock_thread( thr_act );
                    395:        return ret;
                    396: }
                    397: 
                    398: /* 
                    399:  * This routine walks toward the head of an RPC chain starting at
                    400:  * a specified thread activation. An alert bit is set and a special 
                    401:  * handler is installed for each thread it encounters.
                    402:  *
                    403:  * The target thread act and thread shuttle are already locked.
                    404:  */
                    405: kern_return_t
                    406: post_alert( 
                    407:        register thread_act_t   thr_act,
                    408:        unsigned                alert_bits )
                    409: {
                    410:        thread_act_t    next;
                    411:        thread_t        thread;
                    412: 
                    413:        /* 
                    414:         * Chase the chain, setting alert bits and installing
                    415:         * special handlers for each thread act.
                    416:         */
                    417:        /*** Not yet SMP safe ***/
                    418:        /*** Worse, where's the activation locking as the chain is walked? ***/
                    419:        for (next = thr_act; next != THR_ACT_NULL; next = next->higher) {
                    420:                next->alerts |= alert_bits;
                    421:                install_special_handler_locked(next);
                    422:        }
                    423: 
                    424:        return(KERN_SUCCESS);
                    425: }
                    426: 
                    427: /*
                    428:  *     thread_depress_abort:
                    429:  *
                    430:  *     Prematurely abort priority depression if there is one.
                    431:  */
                    432: kern_return_t
                    433: thread_depress_abort(
                    434:        register thread_act_t   thr_act)
                    435: {
                    436:     register thread_t          thread;
                    437:        kern_return_t                   result;
                    438:     sched_policy_t                     *policy;
                    439:     spl_t                                      s;
                    440: 
                    441:     if (thr_act == THR_ACT_NULL)
                    442:                return (KERN_INVALID_ARGUMENT);
                    443: 
                    444:     thread = act_lock_thread(thr_act);
                    445:     /* if activation is terminating, this operation is not meaningful */
                    446:     if (!thr_act->active) {
                    447:                act_unlock_thread(thr_act);
                    448: 
                    449:                return (KERN_TERMINATED);
                    450:     }
                    451: 
                    452:     if (thread == THREAD_NULL) {
                    453:                act_unlock_thread(thr_act);
                    454: 
                    455:                return (KERN_INVALID_ARGUMENT);
                    456:     }
                    457: 
                    458:     s = splsched();
                    459:     thread_lock(thread);
                    460:     policy = &sched_policy[thread->policy];
                    461:     thread_unlock(thread);
                    462:     splx(s);
                    463: 
                    464:     result = policy->sp_ops.sp_thread_depress_abort(policy, thread);
                    465: 
                    466:     act_unlock_thread(thr_act);
                    467: 
                    468:        return (result);
                    469: }
                    470: 
                    471: 
                    472: /*
                    473:  * Already locked: all RPC-related locks for thr_act (see
                    474:  * act_lock_thread()).
                    475:  */
                    476: kern_return_t
                    477: act_abort( thread_act_t thr_act, int chain_break )
                    478: {
                    479:        spl_t                   spl;
                    480:        thread_t                thread;
                    481:        struct ipc_port         *iplock = thr_act->pool_port;
                    482:        thread_act_t            orphan;
                    483:        kern_return_t           kr;
                    484:        etap_data_t             probe_data;
                    485: 
                    486:        /*
                    487:         * mark the activation for abort,
                    488:         * update the suspend count,
                    489:         * always install the special handler
                    490:         */
                    491:        install_special_handler(thr_act);
                    492: 
                    493:        ETAP_DATA_LOAD(probe_data[0], thr_act);
                    494:        ETAP_DATA_LOAD(probe_data[1], thr_act->thread);
                    495:        ETAP_PROBE_DATA(ETAP_P_ACT_ABORT,
                    496:                        0,
                    497:                        current_thread(),
                    498:                        &probe_data,
                    499:                        ETAP_DATA_ENTRY*2);
                    500: 
                    501:        spl = splsched();
                    502:        thread_lock( thr_act->thread );
                    503: 
                    504:        /*
                    505:         *  If the target thread activation is not the head... 
                    506:         */
                    507:        if ( thr_act->thread->top_act != thr_act ) {
                    508: #ifdef AGRESSIVE_ABORT
                    509:                /* release state buffer for target's outstanding invocation */
                    510:                if (unwind_invoke_state(thr_act) != KERN_SUCCESS) {
                    511:                        panic("unwind_invoke_state failure");
                    512:                }
                    513: 
                    514:                /* release state buffer for target's incoming invocation */
                    515:                if (thr_act->lower != THR_ACT_NULL) {
                    516:                        if (unwind_invoke_state(thr_act->lower)
                    517:                            != KERN_SUCCESS) {
                    518:                                panic("unwind_invoke_state failure");
                    519:                        }
                    520:                }
                    521: 
                    522:                /* unlink target thread activation from shuttle chain */
                    523:                if ( thr_act->lower == THR_ACT_NULL ) {
                    524:                        /*
                    525:                         * This is the root thread activation of the chain.
                    526:                         * Unlink the root thread act from the bottom of
                    527:                         * the chain.
                    528:                         */
                    529:                        thr_act->higher->lower = THR_ACT_NULL;
                    530:                } else {
                    531:                        /*
                    532:                         * This thread act is in the middle of the chain.
                    533:                         * Unlink the thread act from the middle of the chain.
                    534:                         */
                    535:                        thr_act->higher->lower = thr_act->lower;
                    536:                        thr_act->lower->higher = thr_act->higher;
                    537: 
                    538:                        /* set the terminated bit for RPC return processing */
                    539:                        thr_act->lower->alerts |= SERVER_TERMINATED;
                    540:                }
                    541: 
                    542:                orphan = thr_act->higher;
                    543: 
                    544:                /* remove the activation from its thread pool */
                    545:                /* (note: this is okay for "rooted threads," too) */
                    546:                act_locked_act_set_thread_pool(thr_act, IP_NULL);
                    547: 
                    548:                /* (just to be thorough) release the IP lock */
                    549:                if (iplock != IP_NULL) ip_unlock(iplock);
                    550: 
                    551:                /* release one more reference for a rooted thread */
                    552:                if (iplock == IP_NULL) act_locked_act_deallocate(thr_act);
                    553: 
                    554:                /* Presumably, the only reference to this activation is
                    555:                 * now held by the caller of this routine. */
                    556:                assert(thr_act->ref_count == 1);
                    557: #else /*AGRESSIVE_ABORT*/
                    558:                /* If there is a lower activation in the RPC chain... */
                    559:                if (thr_act->lower != THR_ACT_NULL) {
                    560:                        /* ...indicate the server activation was terminated */
                    561:                        thr_act->lower->alerts |= SERVER_TERMINATED;
                    562:                }
                    563:                /* Mark (and process) any orphaned activations */
                    564:                orphan = thr_act->higher;
                    565: #endif /*AGRESSIVE_ABORT*/
                    566: 
                    567:                /* indicate client of orphaned chain has been terminated */
                    568:                orphan->alerts |= CLIENT_TERMINATED;
                    569: 
                    570:                /* 
                    571:                 * Set up posting of alert to headward portion of
                    572:                 * the RPC chain.
                    573:                 */
                    574:                /*** fix me -- orphan act is not locked ***/
                    575:                post_alert(orphan, ORPHANED);
                    576: 
                    577:                /*
                    578:                 * Get attention of head of RPC chain.
                    579:                 */
                    580:                thread_unlock(thr_act->thread);
                    581:                nudge(thr_act->thread->top_act);
                    582:                splx(spl);
                    583:                return (KERN_SUCCESS);
                    584:        }
                    585: 
                    586:        /*
                    587:         * If the target thread is the end of the chain, the thread
                    588:         * has to be marked for abort and rip it out of any wait.
                    589:         */
                    590:        if (thr_act->thread->top_act == thr_act) {
                    591:            thr_act->thread->state |= TH_ABORT;
                    592:            thread_unlock(thr_act->thread);
                    593:            install_special_handler(thr_act);
                    594:            nudge( thr_act );
                    595: 
                    596:            /*
                    597:             * if it's waiting, clear it.
                    598:             */
                    599:            if( thr_act->thread->state & TH_WAIT ){
                    600:                clear_wait(thr_act->thread, THREAD_INTERRUPTED, TRUE);
                    601:                splx(spl);
                    602:                return KERN_SUCCESS;
                    603:            }
                    604:        }
                    605:        else {
                    606:                thread_unlock(thr_act->thread);
                    607:        }
                    608:        splx(spl);
                    609:        return KERN_SUCCESS;
                    610: }
                    611:        
                    612: kern_return_t
                    613: thread_abort(
                    614:        register thread_act_t   thr_act)
                    615: {
                    616:        int             ret;
                    617:        thread_t                thread;
                    618: 
                    619:        if (thr_act == THR_ACT_NULL || thr_act == current_act())
                    620:                return (KERN_INVALID_ARGUMENT);
                    621:        /*
                    622:         *      Lock the target thread and the current thread now,
                    623:         *      in case thread_halt() ends up being called below.
                    624:         */
                    625:        thread = act_lock_thread(thr_act);
                    626:        if (!thr_act->active) {
                    627:                act_unlock_thread(thr_act);
                    628:                return(KERN_TERMINATED);
                    629:        }
                    630: 
                    631:        if( thread == THREAD_NULL ) {
                    632:                act_unlock_thread(thr_act);
                    633:                return KERN_NO_THREAD;
                    634:        }
                    635: 
                    636:        ret = act_abort( thr_act, FALSE );
                    637:        act_unlock_thread( thr_act );
                    638:        return ret;
                    639: }
                    640: 
                    641: kern_return_t
                    642: thread_abort_safely(
                    643:        register thread_act_t   thr_act)
                    644: {
                    645:        boolean_t               r;
                    646:        thread_t                cur_thr = current_thread();
                    647:        thread_t                thread, othread;
                    648:        thread_act_t            cur_thr_act = current_act();
                    649:        spl_t                   spl;
                    650: 
                    651:        if (thr_act == THR_ACT_NULL || thr_act == current_act())
                    652:                return(KERN_INVALID_ARGUMENT);
                    653: 
                    654:        othread = act_lock_thread(thr_act);
                    655:        if (othread == THREAD_NULL) {
                    656:                act_unlock_thread(thr_act);
                    657:                return(KERN_INVALID_ARGUMENT);
                    658:        }
                    659:        if (!thr_act->active) {
                    660:                act_unlock_thread(thr_act);
                    661:                return(KERN_TERMINATED);
                    662:        }
                    663:        if (othread->top_act != thr_act) {
                    664:                act_unlock_thread(thr_act);
                    665:                return(KERN_FAILURE);
                    666:        }
                    667: 
                    668:        /*
                    669:         * This is the head of the chain.  Stop it and check to see if
                    670:         * it's in a condition which can be interrupted and restarted and,
                    671:         * if so, clear the wait.
                    672:         */
                    673:        thread_hold(thr_act);
                    674:        act_unlock_thread(thr_act);
                    675:        r = thread_stop_wait(othread);
                    676:        if ((thread = act_lock_thread(thr_act)) != othread || !r) {
                    677:                thread_release(thr_act);
                    678:                act_unlock_thread(thr_act);
                    679:                if (r) {
                    680:                        thread_unstop(othread);
                    681:                        return (KERN_FAILURE);
                    682:                }
                    683:                else
                    684:                    return(KERN_ABORTED);
                    685:        }
                    686: 
                    687:        assert(thread == thr_act->thread);
                    688: 
                    689:        spl = splsched();
                    690:        thread_lock(thread);
                    691:        
                    692:        if( (thread->state&(TH_RUN|TH_UNINT|TH_WAIT)) == TH_WAIT ){
                    693:            if ( thread->at_safe_point ) {
                    694:                        /*
                    695:                         * It's an interruptible wait, clear it, then
                    696:                         * let the thread go and return successfully.
                    697:                         */
                    698:                        thread_unlock(thread);
                    699:                        splx(spl);
                    700:                        clear_wait(thread, THREAD_INTERRUPTED, TRUE);
                    701:                        thread_unstop(thread);
                    702:                        thread_release(thr_act);
                    703:                        act_unlock_thread(thr_act);
                    704:                        return KERN_SUCCESS;
                    705:            }
                    706:        }
                    707:        /*
                    708:         * if not stopped at a safepoint, just let it go and return failure.
                    709:         */
                    710:        thread_unlock(thread);
                    711:        splx(spl);
                    712:        thread_unstop(thread);
                    713:        thread_release(thr_act);
                    714:        act_unlock_thread(thr_act);
                    715:        return KERN_FAILURE;
                    716: }
                    717: 
                    718: /*** backward compatibility hacks ***/
                    719: #include <mach/thread_info.h>
                    720: #include <mach/thread_special_ports.h>
                    721: #include <ipc/ipc_port.h>
                    722: #include <mach/thread_act_server.h>
                    723: 
                    724: kern_return_t
                    725: thread_info(
                    726:        thread_act_t                    thr_act,
                    727:        thread_flavor_t                 flavor,
                    728:        thread_info_t                   thread_info_out,
                    729:        mach_msg_type_number_t  *thread_info_count)
                    730: {
                    731:        register thread_t               thread;
                    732:        kern_return_t                   result;
                    733: 
                    734:        if (thr_act == THR_ACT_NULL)
                    735:                return (KERN_INVALID_ARGUMENT);
                    736: 
                    737:        thread = act_lock_thread(thr_act);
                    738:        if (!thr_act->active) {
                    739:                act_unlock_thread(thr_act);
                    740: 
                    741:                return (KERN_TERMINATED);
                    742:        }
                    743: 
                    744:        if (thread == THREAD_NULL) {
                    745:                act_unlock_thread(thr_act);
                    746: 
                    747:                return (KERN_NO_THREAD);
                    748:        }
                    749: 
                    750:        result = thread_info_shuttle(thr_act, flavor,
                    751:                                        thread_info_out, thread_info_count);
                    752: 
                    753:        act_unlock_thread(thr_act);
                    754: 
                    755:        return (result);
                    756: }
                    757: 
                    758: /*
                    759:  *     Routine:        thread_get_special_port [kernel call]
                    760:  *     Purpose:
                    761:  *             Clones a send right for one of the thread's
                    762:  *             special ports.
                    763:  *     Conditions:
                    764:  *             Nothing locked.
                    765:  *     Returns:
                    766:  *             KERN_SUCCESS            Extracted a send right.
                    767:  *             KERN_INVALID_ARGUMENT   The thread is null.
                    768:  *             KERN_FAILURE            The thread is dead.
                    769:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    770:  */
                    771: 
                    772: kern_return_t
                    773: thread_get_special_port(
                    774:        thread_act_t    thr_act,
                    775:        int             which,
                    776:        ipc_port_t      *portp)
                    777: {
                    778:        ipc_port_t      *whichp;
                    779:        ipc_port_t      port;
                    780:        thread_t        thread;
                    781: 
                    782: #if    MACH_ASSERT
                    783:        if (watchacts & WA_PORT)
                    784:            printf("thread_get_special_port(thr_act=%x, which=%x port@%x=%x\n",
                    785:                thr_act, which, portp, (portp ? *portp : 0));
                    786: #endif /* MACH_ASSERT */
                    787: 
                    788:        if (!thr_act)
                    789:                return KERN_INVALID_ARGUMENT;
                    790:        thread = act_lock_thread(thr_act);
                    791:        switch (which) {
                    792:                case THREAD_KERNEL_PORT:
                    793:                        whichp = &thr_act->ith_sself;
                    794:                        break;
                    795: 
                    796:                default:
                    797:                        act_unlock_thread(thr_act);
                    798:                        return KERN_INVALID_ARGUMENT;
                    799:        }
                    800: 
                    801:        if (!thr_act->active) {
                    802:                act_unlock_thread(thr_act);
                    803:                return KERN_FAILURE;
                    804:        }
                    805: 
                    806:        port = ipc_port_copy_send(*whichp);
                    807:        act_unlock_thread(thr_act);
                    808: 
                    809:        *portp = port;
                    810:        return KERN_SUCCESS;
                    811: }
                    812: 
                    813: /*
                    814:  *     Routine:        thread_set_special_port [kernel call]
                    815:  *     Purpose:
                    816:  *             Changes one of the thread's special ports,
                    817:  *             setting it to the supplied send right.
                    818:  *     Conditions:
                    819:  *             Nothing locked.  If successful, consumes
                    820:  *             the supplied send right.
                    821:  *     Returns:
                    822:  *             KERN_SUCCESS            Changed the special port.
                    823:  *             KERN_INVALID_ARGUMENT   The thread is null.
                    824:  *             KERN_FAILURE            The thread is dead.
                    825:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    826:  */
                    827: 
                    828: kern_return_t
                    829: thread_set_special_port(
                    830:        thread_act_t    thr_act,
                    831:        int             which,
                    832:        ipc_port_t      port)
                    833: {
                    834:        ipc_port_t      *whichp;
                    835:        ipc_port_t      old;
                    836:        thread_t        thread;
                    837: 
                    838: #if    MACH_ASSERT
                    839:        if (watchacts & WA_PORT)
                    840:                printf("thread_set_special_port(thr_act=%x,which=%x,port=%x\n",
                    841:                        thr_act, which, port);
                    842: #endif /* MACH_ASSERT */
                    843: 
                    844:        if (thr_act == 0)
                    845:                return KERN_INVALID_ARGUMENT;
                    846: 
                    847:        thread = act_lock_thread(thr_act);
                    848:        switch (which) {
                    849:                case THREAD_KERNEL_PORT:
                    850:                        whichp = &thr_act->ith_self;
                    851:                        break;
                    852: 
                    853:                default:
                    854:                        act_unlock_thread(thr_act);
                    855:                        return KERN_INVALID_ARGUMENT;
                    856:        }
                    857: 
                    858:        if (!thr_act->active) {
                    859:                act_unlock_thread(thr_act);
                    860:                return KERN_FAILURE;
                    861:        }
                    862: 
                    863:        old = *whichp;
                    864:        *whichp = port;
                    865:        act_unlock_thread(thr_act);
                    866: 
                    867:        if (IP_VALID(old))
                    868:                ipc_port_release_send(old);
                    869:        return KERN_SUCCESS;
                    870: }
                    871: 
                    872: /*
                    873:  *  thread state should always be accessible by locking the thread
                    874:  *  and copying it.  The activation messes things up so for right
                    875:  *  now if it's not the top of the chain, use a special handler to
                    876:  *  get the information when the shuttle returns to the activation.
                    877:  */
                    878: kern_return_t
                    879: thread_get_state(
                    880:        register thread_act_t   thr_act,
                    881:        int                     flavor,
                    882:        thread_state_t          state,  /* pointer to OUT array */
                    883:        mach_msg_type_number_t  *state_count)   /*IN/OUT*/
                    884: {
                    885:        kern_return_t           ret;
                    886:        thread_t                thread, nthread;
                    887: 
                    888: #if 0 /* Grenoble - why?? */
                    889:        if (thr_act == THR_ACT_NULL || thr_act == current_act())
                    890: #else
                    891:        if (thr_act == THR_ACT_NULL)
                    892: #endif
                    893:                return (KERN_INVALID_ARGUMENT);
                    894: 
                    895:        thread = act_lock_thread(thr_act);
                    896:        if (!thr_act->active) {
                    897:                act_unlock_thread(thr_act);
                    898:                return(KERN_TERMINATED);
                    899:        }
                    900: 
                    901:        thread_hold(thr_act);
                    902:        while (1) {
                    903:                if (!thread || thr_act != thread->top_act)
                    904:                        break;
                    905:                act_unlock_thread(thr_act);
                    906:                (void)thread_stop_wait(thread);
                    907:                nthread = act_lock_thread(thr_act);
                    908:                if (nthread == thread)
                    909:                        break;
                    910:                thread_unstop(thread);
                    911:                thread = nthread;
                    912:        }
                    913:        ret = act_machine_get_state(thr_act, flavor,
                    914:                                        state, state_count);
                    915:        if (thread && thr_act == thread->top_act)
                    916:            thread_unstop(thread);
                    917:        thread_release(thr_act);
                    918:        act_unlock_thread(thr_act);
                    919: 
                    920:        return(ret);
                    921: }
                    922: 
                    923: /*
                    924:  *     Change thread's machine-dependent state.  Called with nothing
                    925:  *     locked.  Returns same way.
                    926:  */
                    927: kern_return_t
                    928: thread_set_state(
                    929:        register thread_act_t   thr_act,
                    930:        int                     flavor,
                    931:        thread_state_t          state,
                    932:        mach_msg_type_number_t  state_count)
                    933: {
                    934:        kern_return_t           ret;
                    935:        thread_t                thread, nthread;
                    936: 
                    937: #if 0 /* Grenoble - why?? */
                    938:        if (thr_act == THR_ACT_NULL || thr_act == current_act())
                    939: #else
                    940:        if (thr_act == THR_ACT_NULL)
                    941: #endif
                    942:                return (KERN_INVALID_ARGUMENT);
                    943:        /*
                    944:         * We have no kernel activations, so Utah's MO fails for signals etc.
                    945:         *
                    946:         * If we're blocked in the kernel, use non-blocking method, else
                    947:         * pass locked thr_act+thread in to "normal" act_[gs]et_state().
                    948:         */
                    949: 
                    950:        thread = act_lock_thread(thr_act);
                    951:        if (!thr_act->active) {
                    952:                act_unlock_thread(thr_act);
                    953:                return(KERN_TERMINATED);
                    954:        }
                    955: 
                    956:        thread_hold(thr_act);
                    957:        while (1) {
                    958:                if (!thread || thr_act != thread->top_act)
                    959:                        break;
                    960:                act_unlock_thread(thr_act);
                    961:                (void)thread_stop_wait(thread);
                    962:                nthread = act_lock_thread(thr_act);
                    963:                if (nthread == thread)
                    964:                        break;
                    965:                thread_unstop(thread);
                    966:                thread = nthread;
                    967:        }
                    968:        ret = act_machine_set_state(thr_act, flavor,
                    969:                                        state, state_count);
                    970:        if (thread && thr_act == thread->top_act)
                    971:            thread_unstop(thread);
                    972:        thread_release(thr_act);
                    973:        act_unlock_thread(thr_act);
                    974: 
                    975:        return(ret);
                    976: }
                    977: 
                    978: /*
                    979:  * Kernel-internal "thread" interfaces used outside this file:
                    980:  */
                    981: 
                    982: kern_return_t
                    983: thread_dup(
                    984:        thread_act_t source_thr_act, 
                    985:        thread_act_t target_thr_act)
                    986: {
                    987:        kern_return_t           ret;
                    988:        thread_t                thread, nthread;
                    989: 
                    990:        if (target_thr_act == THR_ACT_NULL || target_thr_act == current_act())
                    991:                return (KERN_INVALID_ARGUMENT);
                    992: 
                    993:        thread = act_lock_thread(target_thr_act);
                    994:        if (!target_thr_act->active) {
                    995:                act_unlock_thread(target_thr_act);
                    996:                return(KERN_TERMINATED);
                    997:        }
                    998: 
                    999:        thread_hold(target_thr_act);
                   1000:        while (1) {
                   1001:                if (!thread || target_thr_act != thread->top_act)
                   1002:                        break;
                   1003:                act_unlock_thread(target_thr_act);
                   1004:                (void)thread_stop_wait(thread);
                   1005:                nthread = act_lock_thread(target_thr_act);
                   1006:                if (nthread == thread)
                   1007:                        break;
                   1008:                thread_unstop(thread);
                   1009:                thread = nthread;
                   1010:        }
                   1011:        ret = act_thread_dup(source_thr_act, target_thr_act);
                   1012:        if (thread && target_thr_act == thread->top_act)
                   1013:            thread_unstop(thread);
                   1014:        thread_release(target_thr_act);
                   1015:        act_unlock_thread(target_thr_act);
                   1016: 
                   1017:        return(ret);
                   1018: }
                   1019: 
                   1020: 
                   1021: /*
                   1022:  *     thread_setstatus:
                   1023:  *
                   1024:  *     Set the status of the specified thread.
                   1025:  *     Called with (and returns with) no locks held.
                   1026:  */
                   1027: kern_return_t
                   1028: thread_setstatus(
                   1029:        thread_act_t            thr_act,
                   1030:        int                     flavor,
                   1031:        thread_state_t          tstate,
                   1032:        mach_msg_type_number_t  count)
                   1033: {
                   1034:        kern_return_t           kr;
                   1035:        thread_t                thread;
                   1036: 
                   1037:        thread = act_lock_thread(thr_act);
                   1038:        assert(thread);
                   1039:        assert(thread->top_act == thr_act);
                   1040:        kr = act_machine_set_state(thr_act, flavor, tstate, count);
                   1041:        act_unlock_thread(thr_act);
                   1042:        return(kr);
                   1043: }
                   1044: 
                   1045: /*
                   1046:  *     thread_getstatus:
                   1047:  *
                   1048:  *     Get the status of the specified thread.
                   1049:  */
                   1050: kern_return_t
                   1051: thread_getstatus(
                   1052:        thread_act_t            thr_act,
                   1053:        int                     flavor,
                   1054:        thread_state_t          tstate,
                   1055:        mach_msg_type_number_t  *count)
                   1056: {
                   1057:        kern_return_t           kr;
                   1058:        thread_t                thread;
                   1059: 
                   1060:        thread = act_lock_thread(thr_act);
                   1061:        assert(thread);
                   1062:        assert(thread->top_act == thr_act);
                   1063:        kr = act_machine_get_state(thr_act, flavor, tstate, count);
                   1064:        act_unlock_thread(thr_act);
                   1065:        return(kr);
                   1066: }
                   1067: 
                   1068: /*
                   1069:  * Kernel-internal thread_activation interfaces used outside this file:
                   1070:  */
                   1071: 
                   1072: /*
                   1073:  * act_init()  - Initialize activation handling code
                   1074:  */
                   1075: void
                   1076: act_init()
                   1077: {
                   1078:        thr_act_zone = zinit(
                   1079:                        sizeof(struct thread_activation),
                   1080:                        ACT_MAX * sizeof(struct thread_activation), /* XXX */
                   1081:                        ACT_CHUNK * sizeof(struct thread_activation),
                   1082:                        "activations");
                   1083:        act_machine_init();
                   1084: }
                   1085: 
                   1086: 
                   1087: /*
                   1088:  * act_create  - Create a new activation in a specific task.
                   1089:  */
                   1090: kern_return_t
                   1091: act_create(task_t task,
                   1092:            thread_act_params_t params,
                   1093:            thread_act_t *new_act)
                   1094: {
                   1095:        thread_act_t thr_act;
                   1096:        int rc;
                   1097:        vm_map_t map;
                   1098: 
                   1099:        thr_act = (thread_act_t)zalloc(thr_act_zone);
                   1100:        if (thr_act == 0)
                   1101:                return(KERN_RESOURCE_SHORTAGE);
                   1102: 
                   1103: #if    MACH_ASSERT
                   1104:        if (watchacts & WA_ACT_LNK)
                   1105:                printf("act_create(task=%x,stk=%x,thr_act@%x=%x)\n",
                   1106:                        task, params ? params->stack : 0, new_act, thr_act);
                   1107: #endif /* MACH_ASSERT */
                   1108: 
                   1109:        /* Start by zeroing everything; then init non-zero items only */
                   1110:        bzero((char *)thr_act, sizeof(*thr_act));
                   1111: 
                   1112:        /* Start with one reference for being active, another for the caller */
                   1113:        act_lock_init(thr_act);
                   1114:        thr_act->ref_count = 2;
                   1115: 
                   1116:        /* Latch onto the task.  */
                   1117:        thr_act->task = task;
                   1118:        task_reference(task);
                   1119:        thr_act->active = 1;
                   1120: 
                   1121:        /* Initialize sigbufp for High-Watermark buffer allocation */
                   1122:         thr_act->r_sigbufp = (routine_descriptor_t) &thr_act->r_sigbuf;
                   1123:         thr_act->r_sigbuf_size = sizeof(thr_act->r_sigbuf);
                   1124: 
                   1125:        /* Initialize thread stack */
                   1126:         if (params)
                   1127:         {
                   1128:                 thr_act->user_stack = params->stack;
                   1129:                 thr_act->user_stack_size = params->stack_size;
                   1130:                 thr_act->user_entry = params->entry_func;
                   1131:         }
                   1132:         else
                   1133:         {
                   1134:                 thr_act->user_stack = 0;
                   1135:                 thr_act->user_stack_size = 0;
                   1136:                 thr_act->user_entry = 0;
                   1137:         }
                   1138: 
                   1139: #if    THREAD_SWAPPER
                   1140:        thr_act->swap_state = TH_SW_IN;
                   1141: #if    MACH_ASSERT
                   1142:        thr_act->kernel_stack_swapped_in = TRUE;
                   1143: #if    THREAD_SWAP_UNWIRE_USER_STACK
                   1144:        thr_act->user_stack_swapped_in = TRUE;
                   1145: #endif /* THREAD_SWAP_UNWIRE_USER_STACK */
                   1146: #endif /* MACH_ASSERT */
                   1147: #endif /* THREAD_SWAPPER */
                   1148: 
                   1149:        /* special_handler will always be last on the returnhandlers list.  */
                   1150:        thr_act->special_handler.next = 0;
                   1151:        thr_act->special_handler.handler = special_handler;
                   1152: 
                   1153: #if    MACH_PROF
                   1154:        thr_act->act_profiled = FALSE;
                   1155:        thr_act->act_profiled_own = FALSE;
                   1156:        thr_act->profil_buffer = NULLPROFDATA;
                   1157: #endif
                   1158: 
                   1159:        /* Initialize the held_ulocks queue as empty */
                   1160:        queue_init(&thr_act->held_ulocks);
                   1161: 
                   1162:        /* Inherit the profiling status of the parent task */
                   1163:        act_prof_init(thr_act, task);
                   1164: 
                   1165:        ipc_thr_act_init(task, thr_act);
                   1166:        act_machine_create(task, thr_act);
                   1167: 
                   1168:        /*
                   1169:         * If thr_act created in kernel-loaded task, alter its saved
                   1170:         * state to so indicate
                   1171:         */
                   1172:        if (task->kernel_loaded) {
                   1173:                act_user_to_kernel(thr_act);
                   1174:                /*
                   1175:                 * If a user_stack was given, assume this is not a "base"
                   1176:                 * activation -- assert that it's fully kernel-loaded
                   1177:                 * already.
                   1178:                 */
                   1179:                if (thr_act->user_stack != 0) {
                   1180:                        thr_act->kernel_loading = FALSE;
                   1181:                        thr_act->kernel_loaded = TRUE;
                   1182:                }
                   1183:        }
                   1184: 
                   1185:        task_lock(task);
                   1186: 
                   1187:        /* Chain the thr_act onto the task's list */
                   1188:        mutex_lock(&task->act_list_lock);
                   1189:        queue_enter(&task->thr_acts, thr_act, thread_act_t, thr_acts);
                   1190:        task->thr_act_count++;
                   1191:        /* no need to check for transition from 0 -> 1 here */
                   1192:        task->res_act_count++;
                   1193:        mutex_unlock(&task->act_list_lock);
                   1194: 
                   1195:        task_unlock(task);
                   1196: 
                   1197:        /* Cache the task's map and take a reference to it */
                   1198:        thr_act->map = task->map;
                   1199: 
                   1200:        /* Inline vm_map_reference cause we don't want to increment res_count */
                   1201:        map = task->map;
                   1202:        mutex_lock(&map->s_lock);
                   1203: #if    TASK_SWAPPER
                   1204:        assert(map->res_count > 0);
                   1205:        assert(map->ref_count >= map->res_count);
                   1206: #endif /* TASK_SWAPPER */
                   1207:        map->ref_count++;
                   1208:        mutex_unlock(&map->s_lock);
                   1209: 
                   1210:        *new_act = thr_act;
                   1211:        return KERN_SUCCESS;
                   1212: }
                   1213: 
                   1214: /*
                   1215:  * act_free    - called when an thr_act's ref_count drops to zero.
                   1216:  *
                   1217:  * This can only happen when thread is zero (not in use),
                   1218:  * thread_pool is zero (not attached to any thread_pool),
                   1219:  * and active is false (terminated).  Called with act locked,
                   1220:  * so that its shuttle pointer can be zeroed atomically.
                   1221:  */
                   1222: #if    MACH_ASSERT
                   1223: int    dangerous_bzero = 1;    /* paranoia & safety */
                   1224: #endif
                   1225: 
                   1226: void
                   1227: act_free(thread_act_t thr_act)
                   1228: {
                   1229:        thread_t        thr;
                   1230:        vm_map_t        map;
                   1231:        unsigned int    ref;
                   1232: 
                   1233: #if    MACH_ASSERT
                   1234:        if (watchacts & WA_EXIT)
                   1235:                printf("act_free(%x(%d)) thr=%x tsk=%x(%d) pport=%x%sactive\n",
                   1236:                        thr_act, thr_act->ref_count, thr_act->thread,
                   1237:                        thr_act->task,
                   1238:                        thr_act->task ? thr_act->task->ref_count : 0,
                   1239:                        thr_act->pool_port,
                   1240:                        thr_act->active ? " " : " !");
                   1241: #endif /* MACH_ASSERT */
                   1242: 
                   1243:        /* Drop final ref to shuttle (not really ours, but we're
                   1244:         * allowed to handle it). */
                   1245:        if (thr = thr_act->thread) {
                   1246:                thr_act->thread = 0;
                   1247:                act_unlock(thr_act);
                   1248:                thread_deallocate(thr);
                   1249:        }
                   1250:        else
                   1251:                act_unlock(thr_act);
                   1252: 
                   1253: #if    THREAD_SWAPPER
                   1254:        thread_swap_disable(thr_act);
                   1255:        assert(thr_act->kernel_stack_swapped_in);
                   1256: #endif /* THREAD_SWAPPER */
                   1257: 
                   1258:        assert(!thr_act->active);
                   1259:        assert(!thr_act->pool_port);
                   1260: 
                   1261:        act_machine_destroy(thr_act);
                   1262:        ipc_thr_act_disable(thr_act);
                   1263:        ipc_thr_act_terminate(thr_act);
                   1264: 
                   1265:        act_prof_deallocate(thr_act);
                   1266: 
                   1267:        /*
                   1268:         * Drop the cached map reference.
                   1269:         * Inline version of vm_map_deallocate() because we
                   1270:         * don't want to decrement the map's residence count here.
                   1271:         */
                   1272:        map = thr_act->map;
                   1273:        mutex_lock(&map->s_lock);
                   1274: #if    TASK_SWAPPER
                   1275:        assert(map->res_count >= 0);
                   1276:        assert(map->ref_count > map->res_count);
                   1277: #endif /* TASK_SWAPPER */
                   1278:        ref = --map->ref_count;
                   1279:        mutex_unlock(&map->s_lock);
                   1280: 
                   1281:        /*
                   1282:         * The task must still have a reference on the map.  Also, if
                   1283:         * the reference count drops to two (one remaining act and the
                   1284:         * task itself), then someone may be waiting in task_halt_wait.
                   1285:         * Wake them up, if needed.
                   1286:         */
                   1287:        if (ref == 0)
                   1288:                panic("thread_deallocate: released last reference on map");
                   1289:        else if (ref == 2)
                   1290:                thread_wakeup(&map->ref_count);
                   1291:                
                   1292:        /* Drop the task reference.  */
                   1293:        task_deallocate(thr_act->task);
                   1294: 
                   1295: #if    MACH_ASSERT
                   1296:        if (dangerous_bzero)    /* dangerous if we're still using it! */
                   1297:                bzero((char *)thr_act, sizeof(*thr_act));
                   1298: #endif /* MACH_ASSERT */
                   1299:        /* Put the thr_act back on the thr_act zone */
                   1300:        zfree(thr_act_zone, (vm_offset_t)thr_act);
                   1301: }
                   1302: 
                   1303: 
                   1304: /*
                   1305:  * act_attach  - Attach an thr_act to the top of a thread ("push the stack").
                   1306:  *
                   1307:  * The thread_shuttle must be either the current one or a brand-new one.
                   1308:  * Assumes the thr_act is active but not in use, also, that if it is
                   1309:  * attached to an thread_pool (i.e. the thread_pool pointer is nonzero),
                   1310:  * the thr_act has already been taken off the thread_pool's list.
                   1311:  *
                   1312:  * Already locked: thr_act plus "appropriate" thread-related locks
                   1313:  * (see act_lock_thread()).
                   1314:  */
                   1315: void 
                   1316: act_attach(
                   1317:        thread_act_t    thr_act,
                   1318:        thread_t        thread,
                   1319:        unsigned        init_alert_mask)
                   1320: {
                   1321:         thread_act_t    lower;
                   1322: 
                   1323: #if    MACH_ASSERT
                   1324:        assert(thread == current_thread() || thread->top_act == THR_ACT_NULL);
                   1325:        if (watchacts & WA_ACT_LNK)
                   1326:                printf("act_attach(thr_act %x(%d) thread %x(%d) mask %d)\n",
                   1327:                       thr_act, thr_act->ref_count, thread, thread->ref_count,
                   1328:                       init_alert_mask);
                   1329: #endif /* MACH_ASSERT */
                   1330: 
                   1331:        /* 
                   1332:         *      Chain the thr_act onto the thread's thr_act stack.  
                   1333:         *      Set mask and auto-propagate alerts from below.
                   1334:         */
                   1335:        thr_act->thread = thread;
                   1336:        thr_act->higher = THR_ACT_NULL;  /*safety*/
                   1337:        thr_act->alerts = 0;
                   1338:        thr_act->alert_mask = init_alert_mask;
                   1339:        lower = thr_act->lower = thread->top_act;
                   1340: 
                   1341:         if (lower != THR_ACT_NULL) {
                   1342:                 lower->higher = thr_act;
                   1343:                 thr_act->alerts = (lower->alerts & init_alert_mask);
                   1344:         }
                   1345: 
                   1346:        thread->top_act = thr_act;
                   1347: }
                   1348: 
                   1349: /*
                   1350:  *     act_detach      
                   1351:  *
                   1352:  *     Remove the current thr_act from the top of the current thread, i.e.
                   1353:  *     "pop the stack". Assumes already locked: thr_act plus "appropriate"
                   1354:  *     thread-related locks (see act_lock_thread).
                   1355:  */
                   1356: void 
                   1357: act_detach(
                   1358:        thread_act_t    cur_act)
                   1359: {
                   1360:        thread_t        cur_thread = cur_act->thread;
                   1361: 
                   1362: #if    MACH_ASSERT
                   1363:        if (watchacts & (WA_EXIT|WA_ACT_LNK))
                   1364:                printf("act_detach: thr_act %x(%d), thrd %x(%d) task=%x(%d)\n",
                   1365:                       cur_act, cur_act->ref_count,
                   1366:                       cur_thread, cur_thread->ref_count,
                   1367:                       cur_act->task,
                   1368:                       cur_act->task ? cur_act->task->ref_count : 0);
                   1369: #endif /* MACH_ASSERT */
                   1370: 
                   1371:        /* Unlink the thr_act from the thread's thr_act stack */
                   1372:        cur_thread->top_act = cur_act->lower;
                   1373:        cur_act->thread = 0;
                   1374: 
                   1375:        thread_pool_put_act(cur_act);
                   1376: 
                   1377: #if    MACH_ASSERT
                   1378:        cur_act->lower = cur_act->higher = THR_ACT_NULL; 
                   1379:        if (cur_thread->top_act)
                   1380:                cur_thread->top_act->higher = THR_ACT_NULL;
                   1381: #endif /* MACH_ASSERT */
                   1382: 
                   1383:        return;
                   1384: }
                   1385: 
                   1386: 
                   1387: /*
                   1388:  * Synchronize a thread operation with RPC.  Called with nothing
                   1389:  * locked.   Returns with thr_act locked, plus one of four
                   1390:  * combinations of other locks held:
                   1391:  *     none - for new activation not yet associated with thread_pool
                   1392:  *             or shuttle
                   1393:  *     rpc_lock(thr_act->thread) only - for base activation (one
                   1394:  *             without pool_port)
                   1395:  *     ip_lock(thr_act->pool_port) only - for empty activation (one
                   1396:  *             with no associated shuttle)
                   1397:  *     both locks - for "active" activation (has shuttle, lives
                   1398:  *             on thread_pool)
                   1399:  * If thr_act has an associated shuttle, this function returns
                   1400:  * its address.  Otherwise it returns zero.
                   1401:  */
                   1402: thread_t
                   1403: act_lock_thread(
                   1404:        thread_act_t thr_act)
                   1405: {
                   1406:        ipc_port_t pport;
                   1407: 
                   1408:        /*
                   1409:         * Allow the shuttle cloning code (q.v., when it
                   1410:         * exists :-}) to obtain ip_lock()'s while holding
                   1411:         * an rpc_lock().
                   1412:         */
                   1413:        while (1) {
                   1414:                act_lock(thr_act);
                   1415:                pport = thr_act->pool_port;
                   1416:                if (!pport || ip_lock_try(pport)) {
                   1417:                        if (!thr_act->thread)
                   1418:                                break;
                   1419:                        if (rpc_lock_try(thr_act->thread))
                   1420:                                break;
                   1421:                        if (pport)
                   1422:                                ip_unlock(pport);
                   1423:                }
                   1424:                act_unlock(thr_act);
                   1425:                mutex_pause();
                   1426:        }
                   1427:        return (thr_act->thread);
                   1428: }
                   1429: 
                   1430: /*
                   1431:  * Unsynchronize with RPC (i.e., undo an act_lock_thread() call).
                   1432:  * Called with thr_act locked, plus thread locks held that are
                   1433:  * "correct" for thr_act's state.  Returns with nothing locked.
                   1434:  */
                   1435: void
                   1436: act_unlock_thread(thread_act_t thr_act)
                   1437: {
                   1438:        if (thr_act->thread)
                   1439:                rpc_unlock(thr_act->thread);
                   1440:        if (thr_act->pool_port)
                   1441:                ip_unlock(thr_act->pool_port);
                   1442:        act_unlock(thr_act);
                   1443: }
                   1444: 
                   1445: /*
                   1446:  * Synchronize with RPC given a pointer to a shuttle (instead of an
                   1447:  * activation).  Called with nothing locked; returns with all
                   1448:  * "appropriate" thread-related locks held (see act_lock_thread()).
                   1449:  */
                   1450: thread_act_t
                   1451: thread_lock_act(
                   1452:        thread_t        thread)
                   1453: {
                   1454:        thread_act_t    thr_act;
                   1455: 
                   1456:        while (1) {
                   1457:                rpc_lock(thread);
                   1458:                thr_act = thread->top_act;
                   1459:                if (!thr_act)
                   1460:                        break;
                   1461:                if (!act_lock_try(thr_act)) {
                   1462:                        rpc_unlock(thread);
                   1463:                        mutex_pause();
                   1464:                        continue;
                   1465:                }
                   1466:                if (thr_act->pool_port &&
                   1467:                        !ip_lock_try(thr_act->pool_port)) {
                   1468:                        rpc_unlock(thread);
                   1469:                        act_unlock(thr_act);
                   1470:                        mutex_pause();
                   1471:                        continue;
                   1472:                }
                   1473:                break;
                   1474:        }
                   1475:        return (thr_act);
                   1476: }
                   1477: 
                   1478: /*
                   1479:  * Unsynchronize with RPC starting from a pointer to a shuttle.
                   1480:  * Called with RPC-related locks held that are appropriate to
                   1481:  * shuttle's state; any activation is also locked.
                   1482:  */
                   1483: void
                   1484: thread_unlock_act(
                   1485:        thread_t        thread)
                   1486: {
                   1487:        thread_act_t    thr_act;
                   1488: 
                   1489:        if (thr_act = thread->top_act) {
                   1490:                if (thr_act->pool_port)
                   1491:                        ip_unlock(thr_act->pool_port);
                   1492:                act_unlock(thr_act);
                   1493:        }
                   1494:        rpc_unlock(thread);
                   1495: }
                   1496: 
                   1497: /*
                   1498:  * switch_act
                   1499:  *
                   1500:  * If a new activation is given, switch to it. If not,
                   1501:  * switch to the lower activation (pop). Returns the old
                   1502:  * activation. This is for RPC support.
                   1503:  */
                   1504: thread_act_t
                   1505: switch_act( 
                   1506:        thread_act_t act)
                   1507: {
                   1508:        thread_t        thread;
                   1509:        thread_act_t    old, new;
                   1510:        unsigned        cpu;
                   1511:        spl_t           spl;
                   1512: 
                   1513: 
                   1514:        disable_preemption();
                   1515: 
                   1516:        cpu = cpu_number();
                   1517:        thread  = current_thread();
                   1518: 
                   1519:        /*
                   1520:         *      Find the old and new activation for switch.
                   1521:         */
                   1522:        old = thread->top_act;
                   1523: 
                   1524:        if (act) {
                   1525:                new = act;
                   1526:                 new->thread = thread;
                   1527:        }
                   1528:        else {
                   1529:                new = old->lower;
                   1530:        }
                   1531: 
                   1532:        assert(new != THR_ACT_NULL);
                   1533: #if    THREAD_SWAPPER
                   1534:        assert(new->swap_state != TH_SW_OUT &&
                   1535:               new->swap_state != TH_SW_COMING_IN);
                   1536: #endif /* THREAD_SWAPPER */
                   1537: 
                   1538:         assert(cpu_data[cpu].active_thread == thread);
                   1539:        active_kloaded[cpu] = (new->kernel_loaded) ? new : 0;
                   1540: 
                   1541:        /* This is where all the work happens */
                   1542:        machine_switch_act(thread, old, new, cpu);
                   1543: 
                   1544:        /*
                   1545:         *      Push or pop an activation on the chain.
                   1546:         */
                   1547:        if (act) {
                   1548:                act_attach(new, thread, 0);
                   1549:        }
                   1550:        else {
                   1551:                act_detach(old);
                   1552:        }
                   1553: 
                   1554:         enable_preemption();
                   1555: 
                   1556:        return(old);
                   1557: }
                   1558: 
                   1559: /*
                   1560:  * install_special_handler
                   1561:  *     Install the special returnhandler that handles suspension and
                   1562:  *     termination, if it hasn't been installed already.
                   1563:  *
                   1564:  * Already locked: RPC-related locks for thr_act, but not
                   1565:  * scheduling lock (thread_lock()) of the associated thread.
                   1566:  */
                   1567: void
                   1568: install_special_handler(
                   1569:        thread_act_t    thr_act)
                   1570: {
                   1571:        spl_t           spl;
                   1572:        thread_t        thread = thr_act->thread;
                   1573: 
                   1574: #if    MACH_ASSERT
                   1575:        if (watchacts & WA_ACT_HDLR)
                   1576:            printf("act_%x: install_special_hdlr(%x)\n",current_act(),thr_act);
                   1577: #endif /* MACH_ASSERT */
                   1578: 
                   1579:        spl = splsched();
                   1580:        if (thread)
                   1581:                thread_lock(thread);
                   1582:        install_special_handler_locked(thr_act);
                   1583:        act_set_apc(thr_act);
                   1584:        if (thread)
                   1585:                thread_unlock(thread);
                   1586:        splx(spl);
                   1587: }
                   1588: 
                   1589: /*
                   1590:  * install_special_handler_locked
                   1591:  *     Do the work of installing the special_handler.
                   1592:  *
                   1593:  * Already locked: RPC-related locks for thr_act, plus the
                   1594:  * scheduling lock (thread_lock()) of the associated thread.
                   1595:  */
                   1596: void
                   1597: install_special_handler_locked(
                   1598:        thread_act_t    thr_act)
                   1599: {
                   1600:        ReturnHandler   **rh;
                   1601:        thread_t        thread = thr_act->thread;
                   1602: 
                   1603:        /* The work handler must always be the last ReturnHandler on the list,
                   1604:           because it can do tricky things like detach the thr_act.  */
                   1605:        for (rh = &thr_act->handlers; *rh; rh = &(*rh)->next)
                   1606:                /* */ ;
                   1607:        if (rh != &thr_act->special_handler.next) {
                   1608:                *rh = &thr_act->special_handler;
                   1609:        }
                   1610:        if (thread && thr_act == thread->top_act) {
                   1611:                /*
                   1612:                 * Temporarily undepress, so target has
                   1613:                 * a chance to do locking required to
                   1614:                 * block itself in special_handler().
                   1615:                 */
                   1616:                /*** ??? fix me ***/
                   1617:                assert(thread->sp_info != SP_INFO_NULL);
                   1618:                if (((thread->policy == POLICY_TIMESHARE) ||
                   1619:                     (thread->policy == POLICY_RR) ||
                   1620:                     (thread->policy == POLICY_FIFO)) &&
                   1621:                    ((mk_sp_info_t)thread->sp_info)->depress_priority >= 0) {
                   1622:                        ((mk_sp_info_t)thread->sp_info)->priority = ((mk_sp_info_t)thread->sp_info)->depress_priority;
                   1623:                        /* Use special value -2 to indicate need
                   1624:                         * to redepress priority in special_handler
                   1625:                         * as thread blocks
                   1626:                         */
                   1627:                        ((mk_sp_info_t)thread->sp_info)->depress_priority = -2;
                   1628:                        compute_priority(thread, FALSE);
                   1629:                }       
                   1630:        }
                   1631:        act_set_apc(thr_act);
                   1632: }
                   1633: 
                   1634: /*
                   1635:  * JMM -
                   1636:  * These two routines will be enhanced over time to call the general handler registration
                   1637:  * mechanism used by special handlers and alerts.  They are hack in for now to avoid
                   1638:  * having to export the gory details of ASTs to the BSD code right now.
                   1639:  */
                   1640: extern thread_apc_handler_t bsd_ast;
                   1641: 
                   1642: kern_return_t
                   1643: thread_apc_set(
                   1644:        thread_act_t thr_act,
                   1645:        thread_apc_handler_t apc)
                   1646: {
                   1647:        assert(apc == bsd_ast);
                   1648:        thread_ast_set(thr_act, AST_BSD);
                   1649:        if (thr_act == current_act())
                   1650:                ast_propagate(thr_act->ast);
                   1651:        return KERN_SUCCESS;
                   1652: }
                   1653: 
                   1654: kern_return_t
                   1655: thread_apc_clear(
                   1656:        thread_act_t thr_act,
                   1657:        thread_apc_handler_t apc)
                   1658: {
                   1659:        assert(apc == bsd_ast);
                   1660:        thread_ast_clear(thr_act, AST_BSD);
                   1661:        if (thr_act == current_act())
                   1662:                ast_off(AST_BSD);
                   1663:        return KERN_SUCCESS;
                   1664: }
                   1665: 
                   1666: /*
                   1667:  * act_set_thread_pool - Assign an activation to a specific thread_pool.
                   1668:  * Fails if the activation is already assigned to another pool.
                   1669:  * If thread_pool == 0, we remove the thr_act from its thread_pool.
                   1670:  *
                   1671:  * Called the port containing thread_pool already locked.
                   1672:  * Returns the same way.
                   1673:  */
                   1674: kern_return_t act_set_thread_pool(
                   1675:        thread_act_t    thr_act,
                   1676:        ipc_port_t      pool_port)
                   1677: {
                   1678:        thread_pool_t   thread_pool;
                   1679: 
                   1680: #if    MACH_ASSERT
                   1681:        if (watchacts & WA_ACT_LNK)
                   1682:                printf("act_set_thread_pool: %x(%d) -> %x\n",
                   1683:                        thr_act, thr_act->ref_count, thread_pool);
                   1684: #endif /* MACH_ASSERT */
                   1685: 
                   1686:        if (pool_port == 0) {
                   1687:                thread_act_t *lact;
                   1688: 
                   1689:                if (thr_act->pool_port == 0)
                   1690:                        return KERN_SUCCESS;
                   1691:                thread_pool = &thr_act->pool_port->ip_thread_pool;
                   1692: 
                   1693:                for (lact = &thread_pool->thr_acts; *lact;
                   1694:                                        lact = &((*lact)->thread_pool_next)) {
                   1695:                        if (thr_act == *lact) {
                   1696:                                *lact = thr_act->thread_pool_next;
                   1697:                                break;
                   1698:                        }
                   1699:                }
                   1700:                act_lock(thr_act);
                   1701:                thr_act->pool_port = 0;
                   1702:                thr_act->thread_pool_next = 0;
                   1703:                act_unlock(thr_act);
                   1704:                act_deallocate(thr_act);
                   1705:                return KERN_SUCCESS;
                   1706:        }
                   1707:        if (thr_act->pool_port != pool_port) {
                   1708:                thread_pool = &pool_port->ip_thread_pool;
                   1709:                if (thr_act->pool_port != 0) {
                   1710: #if    MACH_ASSERT
                   1711:                        if (watchacts & WA_ACT_LNK)
                   1712:                            printf("act_set_thread_pool found %x!\n",
                   1713:                                                        thr_act->pool_port);
                   1714: #endif /* MACH_ASSERT */
                   1715:                        return(KERN_FAILURE);
                   1716:                }
                   1717:                act_lock(thr_act);
                   1718:                thr_act->pool_port = pool_port;
                   1719: 
                   1720:                /* The pool gets a ref to the activation -- have
                   1721:                 * to inline operation because thr_act is already
                   1722:                 * locked.
                   1723:                 */
                   1724:                act_locked_act_reference(thr_act);
                   1725: 
                   1726:                /* If it is available,
                   1727:                 * add it to the thread_pool's available-activation list.
                   1728:                 */
                   1729:                if ((thr_act->thread == 0) && (thr_act->suspend_count == 0)) {
                   1730:                        thr_act->thread_pool_next = thread_pool->thr_acts;
                   1731:                        pool_port->ip_thread_pool.thr_acts = thr_act;
                   1732:                        if (thread_pool->waiting)
                   1733:                                thread_pool_wakeup(thread_pool);
                   1734:                }
                   1735:                act_unlock(thr_act);
                   1736:        }
                   1737: 
                   1738:        return KERN_SUCCESS;
                   1739: }
                   1740: 
                   1741: /*
                   1742:  * act_locked_act_set_thread_pool- Assign activation to a specific thread_pool.
                   1743:  * Fails if the activation is already assigned to another pool.
                   1744:  * If thread_pool == 0, we remove the thr_act from its thread_pool.
                   1745:  *
                   1746:  * Called the port containing thread_pool already locked.
                   1747:  * Also called with the thread activation locked.
                   1748:  * Returns the same way.
                   1749:  *
                   1750:  * This routine is the same as `act_set_thread_pool()' except that it does
                   1751:  * not call `act_deallocate(),' which unconditionally tries to obtain the
                   1752:  * thread activation lock.
                   1753:  */
                   1754: kern_return_t act_locked_act_set_thread_pool(
                   1755:        thread_act_t    thr_act,
                   1756:        ipc_port_t      pool_port)
                   1757: {
                   1758:        thread_pool_t   thread_pool;
                   1759: 
                   1760: #if    MACH_ASSERT
                   1761:        if (watchacts & WA_ACT_LNK)
                   1762:                printf("act_set_thread_pool: %x(%d) -> %x\n",
                   1763:                        thr_act, thr_act->ref_count, thread_pool);
                   1764: #endif /* MACH_ASSERT */
                   1765: 
                   1766:        if (pool_port == 0) {
                   1767:                thread_act_t *lact;
                   1768: 
                   1769:                if (thr_act->pool_port == 0)
                   1770:                        return KERN_SUCCESS;
                   1771:                thread_pool = &thr_act->pool_port->ip_thread_pool;
                   1772: 
                   1773:                for (lact = &thread_pool->thr_acts; *lact;
                   1774:                                        lact = &((*lact)->thread_pool_next)) {
                   1775:                        if (thr_act == *lact) {
                   1776:                                *lact = thr_act->thread_pool_next;
                   1777:                                break;
                   1778:                        }
                   1779:                }
                   1780: 
                   1781:                thr_act->pool_port = 0;
                   1782:                thr_act->thread_pool_next = 0;
                   1783:                act_locked_act_deallocate(thr_act);
                   1784:                return KERN_SUCCESS;
                   1785:        }
                   1786:        if (thr_act->pool_port != pool_port) {
                   1787:                thread_pool = &pool_port->ip_thread_pool;
                   1788:                if (thr_act->pool_port != 0) {
                   1789: #if    MACH_ASSERT
                   1790:                        if (watchacts & WA_ACT_LNK)
                   1791:                            printf("act_set_thread_pool found %x!\n",
                   1792:                                                        thr_act->pool_port);
                   1793: #endif /* MACH_ASSERT */
                   1794:                        return(KERN_FAILURE);
                   1795:                }
                   1796:                thr_act->pool_port = pool_port;
                   1797: 
                   1798:                /* The pool gets a ref to the activation -- have
                   1799:                 * to inline operation because thr_act is already
                   1800:                 * locked.
                   1801:                 */
                   1802:                act_locked_act_reference(thr_act);
                   1803: 
                   1804:                /* If it is available,
                   1805:                 * add it to the thread_pool's available-activation list.
                   1806:                 */
                   1807:                if ((thr_act->thread == 0) && (thr_act->suspend_count == 0)) {
                   1808:                        thr_act->thread_pool_next = thread_pool->thr_acts;
                   1809:                        pool_port->ip_thread_pool.thr_acts = thr_act;
                   1810:                        if (thread_pool->waiting)
                   1811:                                thread_pool_wakeup(thread_pool);
                   1812:                }
                   1813:        }
                   1814: 
                   1815:        return KERN_SUCCESS;
                   1816: }
                   1817: 
                   1818: /*
                   1819:  * Activation control support routines internal to this file:
                   1820:  */
                   1821: 
                   1822: /*
                   1823:  * act_execute_returnhandlers()        - does just what the name says
                   1824:  *
                   1825:  * This is called by system-dependent code when it detects that
                   1826:  * thr_act->handlers is non-null while returning into user mode.
                   1827:  * Activations linked onto an thread_pool always have null thr_act->handlers,
                   1828:  * so RPC entry paths need not check it.
                   1829:  */
                   1830: void act_execute_returnhandlers(
                   1831:        void)
                   1832: {
                   1833:        spl_t           s;
                   1834:        thread_t        thread;
                   1835:        thread_act_t    thr_act = current_act();
                   1836: 
                   1837: #if    MACH_ASSERT
                   1838:        if (watchacts & WA_ACT_HDLR)
                   1839:                printf("execute_rtn_hdlrs: thr_act=%x\n", thr_act);
                   1840: #endif /* MACH_ASSERT */
                   1841: 
                   1842:        s = splsched();
                   1843:        act_clr_apc(thr_act);
                   1844:        spllo();
                   1845:        while (1) {
                   1846:                ReturnHandler *rh;
                   1847: 
                   1848:                /* Grab the next returnhandler */
                   1849:                thread = act_lock_thread(thr_act);
                   1850:                (void)splsched();
                   1851:                thread_lock(thread);
                   1852:                rh = thr_act->handlers;
                   1853:                if (!rh) {
                   1854:                        thread_unlock(thread);
                   1855:                        splx(s);
                   1856:                        act_unlock_thread(thr_act);
                   1857:                        return;
                   1858:                }
                   1859:                thr_act->handlers = rh->next;
                   1860:                thread_unlock(thread);
                   1861:                spllo();
                   1862:                act_unlock_thread(thr_act);
                   1863: 
                   1864: #if    MACH_ASSERT
                   1865:                if (watchacts & WA_ACT_HDLR)
                   1866:                    printf( (rh == &thr_act->special_handler) ?
                   1867:                        "\tspecial_handler\n" : "\thandler=%x\n",
                   1868:                                    rh->handler);
                   1869: #endif /* MACH_ASSERT */
                   1870: 
                   1871:                /* Execute it */
                   1872:                (*rh->handler)(rh, thr_act);
                   1873:        }
                   1874: }
                   1875: 
                   1876: /*
                   1877:  * special_handler     - handles suspension, termination.  Called
                   1878:  * with nothing locked.  Returns (if it returns) the same way.
                   1879:  */
                   1880: void
                   1881: special_handler(
                   1882:        ReturnHandler   *rh,
                   1883:        thread_act_t    cur_act)
                   1884: {
                   1885:        spl_t           s;
                   1886:        thread_t        lthread;
                   1887:        thread_t        thread = act_lock_thread(cur_act);
                   1888:        unsigned        alert_bits;
                   1889:        exception_data_type_t
                   1890:                        codes[EXCEPTION_CODE_MAX];
                   1891:        kern_return_t   kr;
                   1892:        kern_return_t   exc_kr;
                   1893: 
                   1894:        assert(thread != THREAD_NULL);
                   1895: #if    MACH_ASSERT
                   1896:        if (watchacts & WA_ACT_HDLR)
                   1897:            printf("\t\tspecial_handler(thr_act=%x(%d))\n", cur_act,
                   1898:                                (cur_act ? cur_act->ref_count : 0));
                   1899: #endif /* MACH_ASSERT */
                   1900: 
                   1901:        s = splsched();
                   1902: 
                   1903:        thread_lock(thread);
                   1904:        thread->state &= ~TH_ABORT;     /* clear any aborts */
                   1905:        thread_unlock(thread);
                   1906: 
                   1907:        /*
                   1908:         * If someone has killed this invocation,
                   1909:         * invoke the return path with a terminated exception.
                   1910:         */
                   1911:        if (!cur_act->active) {
                   1912:                splx(s);
                   1913:                act_unlock_thread(cur_act);
                   1914:                act_machine_return(KERN_TERMINATED);
                   1915:        }
                   1916: 
                   1917:        splx(s);
                   1918: 
                   1919:        /* strip server terminated bit */
                   1920:        alert_bits = cur_act->alerts & (~SERVER_TERMINATED);
                   1921: 
                   1922:        /* clear server terminated bit */
                   1923:        cur_act->alerts &= ~SERVER_TERMINATED;
                   1924: 
                   1925:        if ( alert_bits ) {
                   1926:                /*
                   1927:                 * currently necessary to coordinate with the exception 
                   1928:                 * code -fdr
                   1929:                 */
                   1930:                act_unlock_thread(cur_act);
                   1931: 
                   1932:                /* upcall exception/alert port */
                   1933:                codes[0] = alert_bits;
                   1934: 
                   1935:                /*
                   1936:                 * Exception makes a lot of assumptions. If there is no
                   1937:                 * exception handler or the exception reply is broken, the 
                   1938:                 * thread will be terminated and exception will not return. If
                   1939:                 * we decide we don't like that behavior, we need to check
                   1940:                 * for the existence of an exception port before we call 
                   1941:                 * exception.
                   1942:                 */
                   1943:                exc_kr = alert_exception( EXC_RPC_ALERT, codes, 1 );
                   1944: 
                   1945:                /* clear the orphaned and time constraint indications */
                   1946:                cur_act->alerts &= ~(ORPHANED | TIME_CONSTRAINT_UNSATISFIED);
                   1947: 
                   1948:                /* if this orphaned activation should be terminated... */
                   1949:                if (exc_kr == KERN_RPC_TERMINATE_ORPHAN) {
                   1950:                        /*
                   1951:                         * ... terminate the activation
                   1952:                         *
                   1953:                         * This is done in two steps.  First, the activation is
                   1954:                         * disabled (prepared for termination); second, the
                   1955:                         * `special_handler()' is executed again -- this time
                   1956:                         * to terminate the activation.
                   1957:                         * (`act_disable_task_locked()' arranges for the
                   1958:                         * additional execution of the `special_handler().')
                   1959:                         */
                   1960: 
                   1961: #if    THREAD_SWAPPER
                   1962:                        thread_swap_disable(cur_act);
                   1963: #endif /* THREAD_SWAPPER */
                   1964: 
                   1965:                        /* acquire appropriate locks */
                   1966:                        task_lock(cur_act->task);
                   1967:                        act_lock_thread(cur_act);
                   1968: 
                   1969:                        /* detach the activation from its task */
                   1970:                        kr = act_disable_task_locked(cur_act);
                   1971:                        assert( kr == KERN_SUCCESS );
                   1972: 
                   1973:                        /* release locks */
                   1974:                        task_unlock(cur_act->task);
                   1975:                }
                   1976:                else {
                   1977:                        /* acquire activation lock again (released below) */
                   1978:                        act_lock_thread(cur_act);
                   1979:                        s = splsched();
                   1980:                        thread_lock(thread);
                   1981:                        /*** ??? fix me ***/
                   1982:                        assert(thread->sp_info != SP_INFO_NULL);
                   1983:                        if (((thread->policy == POLICY_TIMESHARE) ||
                   1984:                             (thread->policy == POLICY_RR) ||
                   1985:                             (thread->policy == POLICY_FIFO)) &&
                   1986:                            ((mk_sp_info_t)thread->sp_info)->depress_priority == -2) {
                   1987:                                /* We were temporarily undepressed by
                   1988:                                 * install_special_handler; restore priority
                   1989:                                 * depression.
                   1990:                                 */
                   1991:                                ((mk_sp_info_t)thread->sp_info)->depress_priority = ((mk_sp_info_t)thread->sp_info)->priority;
                   1992:                                ((mk_sp_info_t)thread->sp_info)->priority = DEPRESSPRI;
                   1993:                                thread->sched_pri = DEPRESSPRI;
                   1994:                        }
                   1995:                        thread_unlock(thread);
                   1996:                        splx(s);
                   1997:                }
                   1998:        }
                   1999: 
                   2000:        /*
                   2001:         * If we're suspended, go to sleep and wait for someone to wake us up.
                   2002:         */
                   2003:        if (cur_act->suspend_count) {
                   2004:                if( cur_act->handlers == NULL ) {
                   2005:                        assert_wait((event_t)&cur_act->suspend_count,
                   2006:                                    THREAD_ABORTSAFE);
                   2007:                        act_unlock_thread(cur_act);
                   2008:                        thread_block((void (*)(void))0);
                   2009:                        act_lock_thread(cur_act);
                   2010:                }
                   2011: 
                   2012:                /*
                   2013:                 * If we're still (or again) suspended, go to sleep again
                   2014:                 * after executing any new handlers that may have appeared.
                   2015:                 */
                   2016:                if (cur_act->suspend_count)
                   2017:                        install_special_handler(cur_act);
                   2018:                else {
                   2019:                        s = splsched();
                   2020:                        thread_lock(thread);
                   2021:                        /*** ??? fix me ***/
                   2022:                        assert(thread->sp_info != SP_INFO_NULL);
                   2023:                        if (((thread->policy == POLICY_TIMESHARE) ||
                   2024:                             (thread->policy == POLICY_RR) ||
                   2025:                             (thread->policy == POLICY_FIFO)) &&
                   2026:                            ((mk_sp_info_t)thread->sp_info)->depress_priority == -2) {
                   2027:                                /* We were temporarily undepressed by
                   2028:                                 * install_special_handler; restore priority
                   2029:                                 * depression.
                   2030:                                 */
                   2031:                                ((mk_sp_info_t)thread->sp_info)->depress_priority = ((mk_sp_info_t)thread->sp_info)->priority;
                   2032:                                ((mk_sp_info_t)thread->sp_info)->priority = DEPRESSPRI;
                   2033:                                thread->sched_pri = DEPRESSPRI;
                   2034:                        }
                   2035:                        thread_unlock(thread);
                   2036:                        splx(s);
                   2037:                }
                   2038:        }
                   2039: 
                   2040:        act_unlock_thread(cur_act);
                   2041: }
                   2042: 
                   2043: /*
                   2044:  * Try to nudge a thr_act into executing its returnhandler chain.
                   2045:  * Ensures that the activation will execute its returnhandlers
                   2046:  * before it next executes any of its user-level code.
                   2047:  *
                   2048:  * Called with thr_act's act_lock() and "appropriate" thread-related
                   2049:  * locks held.  (See act_lock_thread().)  Returns same way.
                   2050:  */
                   2051: void
                   2052: nudge(thread_act_t     thr_act)
                   2053: {
                   2054: #if    MACH_ASSERT
                   2055:        if (watchacts & WA_ACT_HDLR)
                   2056:            printf("\tact_%x: nudge(%x)\n", current_act(), thr_act);
                   2057: #endif /* MACH_ASSERT */
                   2058: 
                   2059:        /*
                   2060:         * Don't need to do anything at all if this thr_act isn't the topmost.
                   2061:         */
                   2062:        if (thr_act->thread && thr_act->thread->top_act == thr_act) {
                   2063:                /*
                   2064:                 * If it's suspended, wake it up. 
                   2065:                 * This should nudge it even on another CPU.
                   2066:                 */
                   2067:                thread_wakeup((event_t)&thr_act->suspend_count);
                   2068:        }
                   2069: }
                   2070: 
                   2071: /*
                   2072:  * Update activation that belongs to a task created via kernel_task_create().
                   2073:  */
                   2074: void
                   2075: act_user_to_kernel(
                   2076:        thread_act_t    thr_act)
                   2077: {
                   2078:        pcb_user_to_kernel(thr_act);
                   2079:        thr_act->kernel_loading = TRUE;
                   2080: }
                   2081: 
                   2082: /*
                   2083:  * Already locked: thr_act->task, RPC-related locks for thr_act
                   2084:  *
                   2085:  * Detach an activation from its task, and prepare it to terminate
                   2086:  * itself.
                   2087:  */
                   2088: kern_return_t
                   2089: act_disable_task_locked(
                   2090:        thread_act_t    thr_act)
                   2091: {
                   2092:        thread_t        thread = thr_act->thread;
                   2093:        task_t          task = thr_act->task;
                   2094: 
                   2095: #if    MACH_ASSERT
                   2096:        if (watchacts & WA_EXIT) {
                   2097:                printf("act_%x: act_disable_tl(thr_act=%x(%d))%sactive task=%x(%d)",
                   2098:                               current_act(), thr_act, thr_act->ref_count,
                   2099:                               (thr_act->active ? " " : " !"),
                   2100:                               thr_act->task, thr_act->task? thr_act->task->ref_count : 0);
                   2101:                if (thr_act->pool_port)
                   2102:                        printf(", pool_port %x", thr_act->pool_port);
                   2103:                printf("\n");
                   2104:                (void) dump_act(thr_act);
                   2105:        }
                   2106: #endif /* MACH_ASSERT */
                   2107:        if (thr_act->thr_acts.next) {
                   2108:                /* Unlink the thr_act from the task's thr_act list,
                   2109:                 * so it doesn't appear in calls to task_threads and such.
                   2110:                 * The thr_act still keeps its ref on the task, however.
                   2111:                 */
                   2112: #ifdef NOTEVER
                   2113:                mutex_lock(&task->act_list_lock);
                   2114: #if 1
                   2115:                queue_remove(&task->thr_acts, thr_act, thread_act_t, thr_acts);
                   2116: #else
                   2117:                thr_act->thr_acts.next->prev = thr_act->thr_acts.prev;
                   2118:                thr_act->thr_acts.prev->next = thr_act->thr_acts.next;
                   2119: #endif /* 1 */
                   2120:                thr_act->thr_acts.next = 0;
                   2121:                task->thr_act_count--;
                   2122: #if    THREAD_SWAPPER
                   2123:                /*
                   2124:                 * Thread is supposed to be unswappable by now...
                   2125:                 */
                   2126:                assert(thr_act->swap_state == TH_SW_UNSWAPPABLE ||
                   2127:                       !(thread_swap_unwire_stack ||
                   2128:                         thread_swap_unwire_user_stack));
                   2129: #endif /* THREAD_SWAPPER */
                   2130:                task->res_act_count--;
                   2131:                mutex_unlock(&task->act_list_lock);
                   2132: #endif /* NOTEVER */
                   2133: 
                   2134:                /* This will allow no more control ops on this thr_act. */
                   2135:                thr_act->active = 0;
                   2136: 
                   2137:                /* Clean-up any ulocks that are still owned by the thread
                   2138:                 * activation (acquired but not released or handed-off).
                   2139:                 */
                   2140:                act_ulock_release_all(thr_act);
                   2141: 
                   2142:                /* If not an empty activation, install special handler */
                   2143:                if (thr_act->thread != THREAD_NULL) {
                   2144: 
                   2145:                        /* When the special_handler gets executed,
                   2146:                         * it will see the terminated condition and exit
                   2147:                         * immediately.
                   2148:                         */
                   2149:                        install_special_handler(thr_act);
                   2150:                }
                   2151: 
                   2152:                /* If the target happens to be suspended,
                   2153:                 * give it a nudge so it can exit.
                   2154:                 */
                   2155:                if (thr_act->suspend_count)
                   2156:                        nudge(thr_act);
                   2157:                /* Drop the thr_act reference taken for being active.
                   2158:                 * (There is still at least one reference left:
                   2159:                 * the one we were passed.)
                   2160:                 * Inline the deallocate because thr_act is locked.
                   2161:                 */
                   2162:                act_locked_act_deallocate(thr_act);
                   2163:        }
                   2164: 
                   2165:        return(KERN_SUCCESS);
                   2166: }
                   2167: 
                   2168: /*
                   2169:  * act_alert   - Register an alert from this activation.
                   2170:  *
                   2171:  * Each set bit is propagated upward from (but not including) this activation,
                   2172:  * until the top of the chain is reached or the bit is masked.
                   2173:  */
                   2174: kern_return_t
                   2175: act_alert(thread_act_t thr_act, unsigned alerts)
                   2176: {
                   2177:        thread_t thread = act_lock_thread(thr_act);
                   2178: 
                   2179: #if    MACH_ASSERT
                   2180:        if (watchacts & WA_ACT_LNK)
                   2181:                printf("act_alert %x: %x\n", thr_act, alerts);
                   2182: #endif /* MACH_ASSERT */
                   2183: 
                   2184:        if (thread) {
                   2185:                thread_act_t act_up = thr_act;
                   2186:                while ((alerts) && (act_up != thread->top_act)) {
                   2187:                        act_up = act_up->higher;
                   2188:                        alerts &= act_up->alert_mask;
                   2189:                        act_up->alerts |= alerts;
                   2190:                }
                   2191:                /*
                   2192:                 * XXXX If we reach the top, and it is blocked in glue
                   2193:                 * code, do something to kick it.  XXXX
                   2194:                 */
                   2195:        }
                   2196:        act_unlock_thread(thr_act);
                   2197: 
                   2198:        return KERN_SUCCESS;
                   2199: }
                   2200: 
                   2201: kern_return_t act_alert_mask(thread_act_t thr_act, unsigned alert_mask)
                   2202: {
                   2203:        panic("act_alert_mask NOT YET IMPLEMENTED\n");
                   2204:        return KERN_SUCCESS;
                   2205: }
                   2206: 
                   2207: typedef struct GetSetState {
                   2208:        struct ReturnHandler rh;
                   2209:        int flavor;
                   2210:        void *state;
                   2211:        int *pcount;
                   2212:        int result;
                   2213: } GetSetState;
                   2214: 
                   2215: /* Local Forward decls */
                   2216: kern_return_t get_set_state(
                   2217:                        thread_act_t thr_act, int flavor,
                   2218:                        thread_state_t state, int *pcount,
                   2219:                        void (*handler)(ReturnHandler *rh, thread_act_t thr_act));
                   2220: void get_state_handler(ReturnHandler *rh, thread_act_t thr_act);
                   2221: void set_state_handler(ReturnHandler *rh, thread_act_t thr_act);
                   2222: 
                   2223: /*
                   2224:  * get_set_state(thr_act ...)
                   2225:  *
                   2226:  * General code to install g/set_state handler.
                   2227:  * Called with thr_act's act_lock() and "appropriate"
                   2228:  * thread-related locks held.  (See act_lock_thread().)
                   2229:  */
                   2230: kern_return_t
                   2231: get_set_state(thread_act_t thr_act, int flavor, thread_state_t state, int *pcount,
                   2232:                        void (*handler)(ReturnHandler *rh, thread_act_t thr_act))
                   2233: {
                   2234:        GetSetState gss;
                   2235:        spl_t s;
                   2236: 
                   2237:        /* Initialize a small parameter structure */
                   2238:        gss.rh.handler = handler;
                   2239:        gss.flavor = flavor;
                   2240:        gss.state = state;
                   2241:        gss.pcount = pcount;
                   2242:        gss.result = KERN_ABORTED;      /* iff wait below is interrupted */
                   2243: 
                   2244:        /* Add it to the thr_act's return handler list */
                   2245:        gss.rh.next = thr_act->handlers;
                   2246:        thr_act->handlers = &gss.rh;
                   2247: 
                   2248:        s = splsched();
                   2249:        act_set_apc(thr_act);
                   2250:        splx(s);
                   2251: 
                   2252: #if    MACH_ASSERT
                   2253:        if (watchacts & WA_ACT_HDLR) {
                   2254:            printf("act_%x: get_set_state(thr_act=%x flv=%x state=%x ptr@%x=%x)",
                   2255:                    current_act(), thr_act, flavor, state,
                   2256:                    pcount, (pcount ? *pcount : 0));
                   2257:            printf((handler == get_state_handler ? "get_state_hdlr\n" :
                   2258:                    (handler == set_state_handler ? "set_state_hdlr\n" :
                   2259:                        "hndler=%x\n")), handler); 
                   2260:        }
                   2261: #endif /* MACH_ASSERT */
                   2262: 
                   2263:        assert(thr_act->thread);        /* Callers must ensure these */
                   2264:        assert(thr_act != current_act());
                   2265:        for (;;) {
                   2266:                nudge(thr_act);
                   2267:                /*
                   2268:                 * Wait must be interruptible to avoid deadlock (e.g.) with
                   2269:                 * task_suspend() when caller and target of get_set_state()
                   2270:                 * are in same task.
                   2271:                 */
                   2272:                assert_wait((event_t)&gss, THREAD_ABORTSAFE);
                   2273:                act_unlock_thread(thr_act);
                   2274:                thread_block((void (*)(void))0);
                   2275:                if (gss.result != KERN_ABORTED)
                   2276:                        break;
                   2277:                if (current_act()->handlers)
                   2278:                        act_execute_returnhandlers();
                   2279:                act_lock_thread(thr_act);
                   2280:        }
                   2281: 
                   2282: #if    MACH_ASSERT
                   2283:        if (watchacts & WA_ACT_HDLR)
                   2284:            printf("act_%x: get_set_state returns %x\n",
                   2285:                            current_act(), gss.result);
                   2286: #endif /* MACH_ASSERT */
                   2287: 
                   2288:        return gss.result;
                   2289: }
                   2290: 
                   2291: void
                   2292: set_state_handler(ReturnHandler *rh, thread_act_t thr_act)
                   2293: {
                   2294:        GetSetState *gss = (GetSetState*)rh;
                   2295: 
                   2296: #if    MACH_ASSERT
                   2297:        if (watchacts & WA_ACT_HDLR)
                   2298:                printf("act_%x: set_state_handler(rh=%x,thr_act=%x)\n",
                   2299:                        current_act(), rh, thr_act);
                   2300: #endif /* MACH_ASSERT */
                   2301: 
                   2302:        gss->result = act_machine_set_state(thr_act, gss->flavor,
                   2303:                                                gss->state, *gss->pcount);
                   2304:        thread_wakeup((event_t)gss);
                   2305: }
                   2306: 
                   2307: void
                   2308: get_state_handler(ReturnHandler *rh, thread_act_t thr_act)
                   2309: {
                   2310:        GetSetState *gss = (GetSetState*)rh;
                   2311: 
                   2312: #if    MACH_ASSERT
                   2313:        if (watchacts & WA_ACT_HDLR)
                   2314:                printf("act_%x: get_state_handler(rh=%x,thr_act=%x)\n",
                   2315:                        current_act(), rh, thr_act);
                   2316: #endif /* MACH_ASSERT */
                   2317: 
                   2318:        gss->result = act_machine_get_state(thr_act, gss->flavor,
                   2319:                        gss->state, 
                   2320:                        (mach_msg_type_number_t *) gss->pcount);
                   2321:        thread_wakeup((event_t)gss);
                   2322: }
                   2323: 
                   2324: kern_return_t
                   2325: act_get_state_locked(thread_act_t thr_act, int flavor, thread_state_t state,
                   2326:                                        mach_msg_type_number_t *pcount)
                   2327: {
                   2328: #if    MACH_ASSERT
                   2329:     if (watchacts & WA_ACT_HDLR)
                   2330:        printf("act_%x: act_get_state_L(thr_act=%x,flav=%x,st=%x,pcnt@%x=%x)\n",
                   2331:                current_act(), thr_act, flavor, state, pcount,
                   2332:                (pcount? *pcount : 0));
                   2333: #endif /* MACH_ASSERT */
                   2334: 
                   2335:     return(get_set_state(thr_act, flavor, state, (int*)pcount, get_state_handler));
                   2336: }
                   2337: 
                   2338: kern_return_t
                   2339: act_set_state_locked(thread_act_t thr_act, int flavor, thread_state_t state,
                   2340:                                        mach_msg_type_number_t count)
                   2341: {
                   2342: #if    MACH_ASSERT
                   2343:     if (watchacts & WA_ACT_HDLR)
                   2344:        printf("act_%x: act_set_state_L(thr_act=%x,flav=%x,st=%x,pcnt@%x=%x)\n",
                   2345:                current_act(), thr_act, flavor, state, count, count);
                   2346: #endif /* MACH_ASSERT */
                   2347: 
                   2348:     return(get_set_state(thr_act, flavor, state, (int*)&count, set_state_handler));
                   2349: }
                   2350: 
                   2351: kern_return_t
                   2352: act_set_state(thread_act_t thr_act, int flavor, thread_state_t state,
                   2353:                                        mach_msg_type_number_t count)
                   2354: {
                   2355:     if (thr_act == THR_ACT_NULL || thr_act == current_act())
                   2356:            return(KERN_INVALID_ARGUMENT);
                   2357: 
                   2358:     if (act_lock_thread(thr_act) == THREAD_NULL) {
                   2359:            act_unlock(thr_act);
                   2360:            return(KERN_INVALID_ARGUMENT);
                   2361:     }
                   2362:     return(act_set_state_locked(thr_act, flavor, state, count));
                   2363:     
                   2364: }
                   2365: 
                   2366: kern_return_t
                   2367: act_get_state(thread_act_t thr_act, int flavor, thread_state_t state,
                   2368:                                        mach_msg_type_number_t *pcount)
                   2369: {
                   2370:     if (thr_act == THR_ACT_NULL || thr_act == current_act())
                   2371:            return(KERN_INVALID_ARGUMENT);
                   2372: 
                   2373:     if (act_lock_thread(thr_act) == THREAD_NULL) {
                   2374:            act_unlock(thr_act);
                   2375:            return(KERN_INVALID_ARGUMENT);
                   2376:     }
                   2377:     return(act_get_state_locked(thr_act, flavor, state, pcount));
                   2378: }
                   2379: 
                   2380: /*
                   2381:  * These two should be called at splsched()
                   2382:  * Set/clear indicator to run APC (layered on ASTs)
                   2383:  */
                   2384: void
                   2385: act_set_apc(thread_act_t thr_act)
                   2386: {
                   2387:        thread_ast_set(thr_act, AST_APC);
                   2388:        if (thr_act == current_act()) {
                   2389:                mp_disable_preemption();
                   2390:                ast_propagate(thr_act->ast);
                   2391:                mp_enable_preemption();
                   2392:        }
                   2393: }
                   2394: 
                   2395: void
                   2396: act_clr_apc(thread_act_t thr_act)
                   2397: {
                   2398:        thread_ast_clear(thr_act, AST_APC);
                   2399: }
                   2400: 
                   2401: void
                   2402: act_ulock_release_all(thread_act_t thr_act)
                   2403: {
                   2404:        ulock_t ulock;
                   2405: 
                   2406:        while (!queue_empty(&thr_act->held_ulocks)) {
                   2407:                ulock = (ulock_t) queue_first(&thr_act->held_ulocks);
                   2408:                (void) lock_make_unstable(ulock, thr_act);
                   2409:                (void) lock_release_internal(ulock, thr_act);
                   2410:        }
                   2411: }
                   2412: 
                   2413: /*
                   2414:  * Provide routines (for export to other components) of things that
                   2415:  * are implemented as macros insternally.
                   2416:  */
                   2417: #undef current_act
                   2418: thread_act_t
                   2419: current_act(void)
                   2420: {
                   2421:        return(current_act_fast());
                   2422: }

unix.superglobalmegacorp.com

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