Annotation of XNU/osfmk/kern/exception.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_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: 
                     53: #include <mach_kdb.h>
                     54: 
                     55: #include <mach/boolean.h>
                     56: #include <mach/kern_return.h>
                     57: #include <mach/message.h>
                     58: #include <mach/port.h>
                     59: #include <mach/mig_errors.h>
                     60: #include <mach/thread_status.h>
                     61: #include <mach/exception_types.h>
                     62: #include <ipc/port.h>
                     63: #include <ipc/ipc_entry.h>
                     64: #include <ipc/ipc_object.h>
                     65: #include <ipc/ipc_notify.h>
                     66: #include <ipc/ipc_space.h>
                     67: #include <ipc/ipc_pset.h>
                     68: #include <ipc/ipc_machdep.h>
                     69: #include <kern/etap_macros.h>
                     70: #include <kern/counters.h>
                     71: #include <kern/ipc_tt.h>
                     72: #include <kern/task.h>
                     73: #include <kern/thread.h>
                     74: #include <kern/thread_swap.h>
                     75: #include <kern/processor.h>
                     76: #include <kern/sched.h>
                     77: #include <kern/sched_prim.h>
                     78: #include <kern/host.h>
                     79: #include <kern/misc_protos.h>
                     80: #include <string.h>
                     81: #include <mach/exc.h>            /* JMM - will become exception.h */
                     82: #include <machine/machine_rpc.h>
                     83: 
                     84: #if    MACH_KDB
                     85: #include <ddb/db_trap.h>
                     86: #endif /* MACH_KDB */
                     87: 
                     88: /*
                     89:  * Forward declarations
                     90:  */
                     91: void exception_try_task(
                     92:        exception_type_t        exception,
                     93:        exception_data_t        code,
                     94:        mach_msg_type_number_t  codeCnt);
                     95: 
                     96: void exception_no_server(void);
                     97: 
                     98: kern_return_t alert_exception_try_task(
                     99:        exception_type_t        exception,
                    100:        exception_data_t        code,
                    101:        int                     codeCnt);
                    102: 
                    103: #if    MACH_KDB
                    104: 
                    105: #include <ddb/db_output.h>
                    106: 
                    107: #if iPSC386 || iPSC860
                    108: boolean_t debug_user_with_kdb = TRUE;
                    109: #else
                    110: boolean_t debug_user_with_kdb = FALSE;
                    111: #endif
                    112: 
                    113: #endif /* MACH_KDB */
                    114: 
                    115: unsigned long c_thr_exc_raise = 0;
                    116: unsigned long c_thr_exc_raise_state = 0;
                    117: unsigned long c_thr_exc_raise_state_id = 0;
                    118: unsigned long c_tsk_exc_raise = 0;
                    119: unsigned long c_tsk_exc_raise_state = 0;
                    120: unsigned long c_tsk_exc_raise_state_id = 0;
                    121: 
                    122: 
                    123: #ifdef MACHINE_FAST_EXCEPTION  /* from <machine/thread.h> if at all */
                    124: /*
                    125:  * This is the fast, MD code, with lots of stuff in-lined.
                    126:  */
                    127: 
                    128: extern int switch_act_swapins;
                    129: 
                    130: #ifdef i386
                    131: /*
                    132:  * Temporary: controls the syscall copyin optimization.
                    133:  * If TRUE, the exception function will copy in the first n
                    134:  * words from the stack of the user thread and store it in
                    135:  * the saved state, so that the server doesn't have to do
                    136:  * this.
                    137:  */
                    138: boolean_t syscall_exc_copyin = TRUE;
                    139: #endif
                    140: 
                    141: /*
                    142:  *     Routine:        exception
                    143:  *     Purpose:
                    144:  *             The current thread caught an exception.
                    145:  *             We make an up-call to the thread's exception server.
                    146:  *     Conditions:
                    147:  *             Nothing locked and no resources held.
                    148:  *             Called from an exception context, so
                    149:  *             thread_exception_return and thread_kdb_return
                    150:  *             are possible.
                    151:  *     Returns:
                    152:  *             Doesn't return.
                    153:  */
                    154: 
                    155: void
                    156: exception(
                    157:        exception_type_t        exception,
                    158:        exception_data_t        code,
                    159:        mach_msg_type_number_t  codeCnt )
                    160: {
                    161:        thread_t                self = current_thread();
                    162:        thread_act_t            a_self = self->top_act;
                    163:        thread_act_t            cln_act;
                    164:        ipc_port_t              exc_port;
                    165:        int                     i;
                    166:        struct exception_action *excp = &a_self->exc_actions[exception];
                    167:        int                     flavor;
                    168:        kern_return_t           kr;
                    169: 
                    170:        assert(exception != EXC_RPC_ALERT);
                    171: 
                    172:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    173: 
                    174:        /*
                    175:         *      Optimized version of retrieve_thread_exception.
                    176:         */
                    177: 
                    178:        act_lock(a_self);
                    179:        assert(a_self->ith_self != IP_NULL);
                    180:        exc_port = excp->port;
                    181:        if (!IP_VALID(exc_port)) {
                    182:                act_unlock(a_self);
                    183:                exception_try_task(exception, code, codeCnt);
                    184:                /*NOTREACHED*/
                    185:                return;
                    186:        }
                    187:        flavor = excp->flavor;
                    188: 
                    189: #ifdef i386
                    190:        /* For this flavor, we must copy in the first few procedure call
                    191:         * args from the user's stack, since that is part of the important
                    192:         * state in a syscall exception (this is for performance -- we
                    193:         * can do the copyin much faster than the server, even if it is
                    194:         * kernel-loaded):
                    195:         */
                    196:        if (flavor == i386_SAVED_STATE) {
                    197:                struct i386_saved_state *statep = (struct i386_saved_state *)
                    198:                                        act_machine_state_ptr(self->top_act);
                    199:                statep->argv_status = FALSE;
                    200:                if (syscall_exc_copyin && copyin((char *)statep->uesp,
                    201:                           (char *)statep->argv,
                    202:                           i386_SAVED_ARGV_COUNT * sizeof(int)) == 0) {
                    203:                        /* Indicate success for the server: */
                    204:                        statep->argv_status = TRUE;
                    205:                }
                    206:        }
                    207: #endif
                    208: 
                    209:        ETAP_EXCEPTION_PROBE(EVENT_BEGIN, self, exception, code);
                    210: 
                    211:        ip_lock(exc_port);
                    212:        act_unlock(a_self);
                    213:        if (!ip_active(exc_port)) {
                    214:                ip_unlock(exc_port);
                    215:                exception_try_task(exception, code, codeCnt);
                    216:                /*NOTREACHED*/
                    217:                return;
                    218:        }
                    219: 
                    220:        /*
                    221:         * Hold a reference to the port over the exception_raise_* calls
                    222:         * so it can't be destroyed.  This seems like overkill, but keeps
                    223:         * the port from disappearing between now and when
                    224:         * ipc_object_copyin_from_kernel is finally called.
                    225:         */
                    226:        ip_reference(exc_port); 
                    227:        exc_port->ip_srights++;
                    228:        ip_unlock(exc_port);
                    229: 
                    230:        switch (excp->behavior) {
                    231:        case EXCEPTION_STATE: {
                    232:            mach_msg_type_number_t state_cnt;
                    233:            {
                    234:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    235: 
                    236:                state_cnt = state_count[flavor];
                    237:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                    238:                if (kr == KERN_SUCCESS) {
                    239:                    kr = exception_raise_state(exc_port, exception,
                    240:                                code, codeCnt,
                    241:                                &flavor,
                    242:                                state, state_cnt,
                    243:                                state, &state_cnt);
                    244:                    if (kr == MACH_MSG_SUCCESS)
                    245:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                    246:                }
                    247:            }
                    248: 
                    249:            if (kr == KERN_SUCCESS ||
                    250:                kr == MACH_RCV_PORT_DIED) {
                    251:                    ETAP_EXCEPTION_PROBE(EVENT_END, self, exception, code);
                    252:                     thread_exception_return();
                    253:                    /* NOTREACHED*/
                    254:                    return;
                    255:            }
                    256:            } break;
                    257: 
                    258:        case EXCEPTION_DEFAULT:
                    259:                c_thr_exc_raise++;
                    260:                kr = exception_raise(exc_port,
                    261:                                retrieve_act_self_fast(a_self),
                    262:                                retrieve_task_self_fast(a_self->task),
                    263:                                exception,
                    264:                                code, codeCnt);
                    265: 
                    266:                if (kr == KERN_SUCCESS ||
                    267:                    kr == MACH_RCV_PORT_DIED) {
                    268:                        ETAP_EXCEPTION_PROBE(EVENT_END, self, exception, code);
                    269:                         thread_exception_return();
                    270:                        /* NOTREACHED*/
                    271:                        return;
                    272:                }
                    273:                break;
                    274: 
                    275:        case EXCEPTION_STATE_IDENTITY: {
                    276:                mach_msg_type_number_t state_cnt;
                    277:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    278: 
                    279:                c_thr_exc_raise_state_id++;
                    280:                state_cnt = state_count[flavor];
                    281:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                    282:                if (kr == KERN_SUCCESS) {
                    283:                    kr = exception_raise_state_identity(exc_port,
                    284:                                retrieve_act_self_fast(a_self),
                    285:                                retrieve_task_self_fast(a_self->task),
                    286:                                exception,
                    287:                                code, codeCnt,
                    288:                                &flavor,
                    289:                                state, state_cnt,
                    290:                                state, &state_cnt);
                    291:                    if (kr == MACH_MSG_SUCCESS)
                    292:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                    293:                }
                    294: 
                    295:                if (kr == KERN_SUCCESS ||
                    296:                    kr == MACH_RCV_PORT_DIED) {
                    297:                         ETAP_EXCEPTION_PROBE(EVENT_END, self, exception, code);
                    298:                         thread_exception_return();
                    299:                        /* NOTREACHED*/
                    300:                        return;
                    301:                }
                    302:                } break;
                    303:        default:
                    304:                panic ("bad behavior!");
                    305:        }/* switch */
                    306: 
                    307:        /*
                    308:         * When a task is being terminated, it's no longer ripped
                    309:         * directly out of the rcv from its "kill me" message, and
                    310:         * so returns here.  The following causes it to return out
                    311:         * to the glue code and clean itself up.
                    312:         */
                    313:        if ((self->top_act && !self->top_act->active) ||
                    314:            (self->state & TH_ABORT)) {
                    315:                 ETAP_EXCEPTION_PROBE(EVENT_END, self, exception, code);
                    316:                thread_exception_return();
                    317:        }
                    318: 
                    319:        exception_try_task(exception, code, codeCnt);
                    320:        /* NOTREACHED */
                    321: }
                    322: 
                    323: /*
                    324:  * We only use the machine-independent exception() routine
                    325:  * if a faster MD version isn't available.
                    326:  */
                    327: #else  /* MACHINE_FAST_EXCEPTION */
                    328: /*
                    329:  *     If continuations are not used/supported, the NOTREACHED comments
                    330:  *     below are incorrect.  The exception function is expected to return.
                    331:  *     So the return statements along the slow paths are important.
                    332:  */
                    333: 
                    334: /*
                    335:  *     Routine:        exception
                    336:  *     Purpose:
                    337:  *             The current thread caught an exception.
                    338:  *             We make an up-call to the thread's exception server.
                    339:  *     Conditions:
                    340:  *             Nothing locked and no resources held.
                    341:  *             Called from an exception context, so
                    342:  *             thread_exception_return and thread_kdb_return
                    343:  *             are possible.
                    344:  *     Returns:
                    345:  *             Doesn't return.
                    346:  */
                    347: 
                    348: void
                    349: exception(
                    350:        exception_type_t        exception,
                    351:        exception_data_t        code,
                    352:        mach_msg_type_number_t  codeCnt)
                    353: {
                    354:        thread_t                self = current_thread();
                    355:        thread_act_t            a_self = self->top_act;
                    356:        ipc_port_t              exc_port;
                    357:        int                     i;
                    358:        struct exception_action *excp = &a_self->exc_actions[exception];
                    359:        int                     flavor;
                    360:        kern_return_t           kr;
                    361: 
                    362:        assert(exception != EXC_RPC_ALERT);
                    363: 
                    364:        if (exception == KERN_SUCCESS)
                    365:                panic("exception");
                    366: 
                    367:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    368: 
                    369:        /*
                    370:         *      Optimized version of retrieve_thread_exception.
                    371:         */
                    372: 
                    373:        act_lock(a_self);
                    374:        assert(a_self->ith_self != IP_NULL);
                    375:        exc_port = excp->port;
                    376:        if (!IP_VALID(exc_port)) {
                    377:                act_unlock(a_self);
                    378:                exception_try_task(exception, code, codeCnt);
                    379:                /*NOTREACHED*/
                    380:                return;
                    381:        }
                    382:        flavor = excp->flavor;
                    383: 
                    384:        ip_lock(exc_port);
                    385:        act_unlock(a_self);
                    386:        if (!ip_active(exc_port)) {
                    387:                ip_unlock(exc_port);
                    388:                exception_try_task(exception, code, codeCnt);
                    389:                /*NOTREACHED*/
                    390:                return;
                    391:        }
                    392: 
                    393:        /*
                    394:         * Hold a reference to the port over the exception_raise_* calls
                    395:         * so it can't be destroyed.  This seems like overkill, but keeps
                    396:         * the port from disappearing between now and when
                    397:         * ipc_object_copyin_from_kernel is finally called.
                    398:         */
                    399:        ip_reference(exc_port); 
                    400:        exc_port->ip_srights++;
                    401:        ip_unlock(exc_port);
                    402: 
                    403:        switch (excp->behavior) {
                    404:        case EXCEPTION_STATE: {
                    405:                mach_msg_type_number_t state_cnt;
                    406: 
                    407:                c_thr_exc_raise_state++;
                    408:                {
                    409:                        natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    410: 
                    411:                        state_cnt = state_count[flavor];
                    412:                        kr = thread_getstatus(a_self, flavor, 
                    413:                                              (thread_state_t)state,
                    414:                                              &state_cnt);
                    415:                        if (kr == KERN_SUCCESS) {
                    416:                            kr = exception_raise_state(exc_port, exception,
                    417:                                        code, codeCnt,
                    418:                                        &flavor,
                    419:                                        state, state_cnt,
                    420:                                        state, &state_cnt);
                    421:                            if (kr == MACH_MSG_SUCCESS)
                    422:                                kr = thread_setstatus(a_self, flavor, 
                    423:                                                      (thread_state_t)state,
                    424:                                                      state_cnt);
                    425:                        }
                    426:                }
                    427: 
                    428:                if (kr == KERN_SUCCESS ||
                    429:                    kr == MACH_RCV_PORT_DIED) {
                    430:                        thread_exception_return();
                    431:                        /*NOTREACHED*/
                    432:                        return;
                    433:                }
                    434:                } break;
                    435: 
                    436:        case EXCEPTION_DEFAULT:
                    437:                c_thr_exc_raise++;
                    438:                kr = exception_raise(exc_port,
                    439:                                retrieve_act_self_fast(a_self),
                    440:                                retrieve_task_self_fast(a_self->task),
                    441:                                exception,
                    442:                                code, codeCnt);
                    443: 
                    444:                if (kr == KERN_SUCCESS ||
                    445:                    kr == MACH_RCV_PORT_DIED) {
                    446:                        thread_exception_return();
                    447:                        /*NOTREACHED*/
                    448:                        return;
                    449:                }
                    450:                break;
                    451: 
                    452:        case EXCEPTION_STATE_IDENTITY: {
                    453:                mach_msg_type_number_t state_cnt;
                    454:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    455: 
                    456:                c_thr_exc_raise_state_id++;
                    457:                state_cnt = state_count[flavor];
                    458:                kr = thread_getstatus(a_self, flavor,
                    459:                                      (thread_state_t)state,
                    460:                                      &state_cnt);
                    461:                if (kr == KERN_SUCCESS) {
                    462:                    kr = exception_raise_state_identity(exc_port,
                    463:                                retrieve_act_self_fast(a_self),
                    464:                                retrieve_task_self_fast(a_self->task),
                    465:                                exception,
                    466:                                code, codeCnt,
                    467:                                &flavor,
                    468:                                state, state_cnt,
                    469:                                state, &state_cnt);
                    470:                    if (kr == MACH_MSG_SUCCESS)
                    471:                        kr = thread_setstatus(a_self, flavor,
                    472:                                              (thread_state_t)state,
                    473:                                              state_cnt);
                    474:                }
                    475: 
                    476:                if (kr == KERN_SUCCESS ||
                    477:                    kr == MACH_RCV_PORT_DIED) {
                    478:                        thread_exception_return();
                    479:                        /*NOTREACHED*/
                    480:                        return;
                    481:                }
                    482:                } break;
                    483:        default:
                    484:                panic ("bad behavior!");
                    485:        }/* switch */
                    486: 
                    487:        /*
                    488:         * When a task is being terminated, it's no longer ripped
                    489:         * directly out of the rcv from its "kill me" message, and
                    490:         * so returns here.  The following causes it to return out
                    491:         * to the glue code and clean itself up.
                    492:         */
                    493:        if ((self->top_act && !self->top_act->active) ||
                    494:            (self->state & TH_ABORT)) {
                    495:                thread_exception_return();
                    496:                /*NOTREACHED*/
                    497:        }
                    498: 
                    499:        exception_try_task(exception, code, codeCnt);
                    500:        /* NOTREACHED */
                    501:        return;
                    502: }
                    503: #endif /* defined MACHINE_FAST_EXCEPTION */
                    504: 
                    505: /*
                    506:  *     Routine:        exception_try_task
                    507:  *     Purpose:
                    508:  *             The current thread caught an exception.
                    509:  *             We make an up-call to the task's exception server.
                    510:  *     Conditions:
                    511:  *             Nothing locked and no resources held.
                    512:  *             Called from an exception context, so
                    513:  *             thread_exception_return and thread_kdb_return
                    514:  *             are possible.
                    515:  *     Returns:
                    516:  *             Doesn't return.
                    517:  */
                    518: 
                    519: void
                    520: exception_try_task(
                    521:        exception_type_t        exception,
                    522:        exception_data_t        code,
                    523:        mach_msg_type_number_t  codeCnt)
                    524: {
                    525:        thread_act_t    a_self = current_act();
                    526:        thread_t        self = a_self->thread;
                    527:        register task_t task = a_self->task;
                    528:        register        ipc_port_t exc_port;
                    529:        int             flavor, i;
                    530:        kern_return_t   kr;
                    531: 
                    532:        assert(exception != EXC_RPC_ALERT);
                    533: 
                    534:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    535: 
                    536:        /*
                    537:         *      Optimized version of retrieve_task_exception.
                    538:         */
                    539: 
                    540:        itk_lock(task);
                    541:        assert(task->itk_self != IP_NULL);
                    542:        exc_port = task->exc_actions[exception].port;
                    543:        if (exception == EXC_MACH_SYSCALL && exc_port == realhost.host_self) {
                    544:                itk_unlock(task);
                    545:                restart_mach_syscall();         /* magic ! */
                    546:                /* NOTREACHED */
                    547:        }
                    548:        if (!IP_VALID(exc_port)) {
                    549:                itk_unlock(task);
                    550:                exception_no_server();
                    551:                /*NOTREACHED*/
                    552:                return;
                    553:        }
                    554:        flavor = task->exc_actions[exception].flavor;
                    555: 
                    556:        ip_lock(exc_port);
                    557:        itk_unlock(task);
                    558:        if (!ip_active(exc_port)) {
                    559:                ip_unlock(exc_port);
                    560:                exception_no_server();
                    561:                /*NOTREACHED*/
                    562:                return;
                    563:        }
                    564: 
                    565:        /*
                    566:         * Hold a reference to the port over the exception_raise_* calls
                    567:         * (see longer comment in exception())
                    568:         */
                    569:        ip_reference(exc_port);
                    570:        exc_port->ip_srights++;
                    571:        ip_unlock(exc_port);
                    572: 
                    573:        switch (task->exc_actions[exception].behavior) {
                    574:        case EXCEPTION_STATE: {
                    575:            mach_msg_type_number_t state_cnt;
                    576:            {
                    577:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    578: 
                    579:                c_tsk_exc_raise_state++;
                    580:                state_cnt = state_count[flavor];
                    581:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                    582:                if (kr == KERN_SUCCESS) {
                    583:                    kr = exception_raise_state(exc_port, exception,
                    584:                                code, codeCnt,
                    585:                                &flavor,
                    586:                                state, state_cnt,
                    587:                                state, &state_cnt);
                    588:                    if (kr == MACH_MSG_SUCCESS)
                    589:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                    590:                }
                    591:            }
                    592: 
                    593:            if (kr == KERN_SUCCESS ||
                    594:                kr == MACH_RCV_PORT_DIED) {
                    595:                    ETAP_EXCEPTION_PROBE(EVENT_END, self, exception, code);
                    596:                     thread_exception_return();
                    597:                    /* NOTREACHED*/
                    598:                    return;
                    599:            }
                    600:            } break;
                    601: 
                    602:        case EXCEPTION_DEFAULT:
                    603:                c_tsk_exc_raise++;
                    604:                kr = exception_raise(exc_port,
                    605:                                retrieve_act_self_fast(a_self),
                    606:                                retrieve_task_self_fast(a_self->task),
                    607:                                exception, code, codeCnt);
                    608: 
                    609:                if (kr == KERN_SUCCESS ||
                    610:                    kr == MACH_RCV_PORT_DIED) {
                    611:                        thread_exception_return();
                    612:                        /*NOTREACHED*/
                    613:                        return;
                    614:                }
                    615:                break;
                    616: 
                    617:        case EXCEPTION_STATE_IDENTITY: {
                    618:                mach_msg_type_number_t state_cnt;
                    619:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    620: 
                    621:                c_tsk_exc_raise_state_id++;
                    622:                state_cnt = state_count[flavor];
                    623:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                    624:                if (kr == KERN_SUCCESS) {
                    625:                    kr = exception_raise_state_identity(exc_port,
                    626:                                retrieve_act_self_fast(a_self),
                    627:                                retrieve_task_self_fast(a_self->task),
                    628:                                exception,
                    629:                                code, codeCnt,
                    630:                                &flavor,
                    631:                                state, state_cnt,
                    632:                                state, &state_cnt);
                    633:                    if (kr == KERN_SUCCESS)
                    634:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                    635:                }
                    636: 
                    637:                if (kr == MACH_MSG_SUCCESS || kr == MACH_RCV_PORT_DIED) {
                    638:                    thread_exception_return();
                    639:                    /*NOTREACHED*/
                    640:                    return;
                    641:                }
                    642:                } break;
                    643: 
                    644:        default:
                    645:                panic ("bad behavior!");
                    646:        }/* switch */
                    647: 
                    648:        exception_no_server();
                    649:        /*NOTREACHED*/
                    650: }
                    651: 
                    652: /*
                    653:  *     Routine:        exception_no_server
                    654:  *     Purpose:
                    655:  *             The current thread took an exception,
                    656:  *             and no exception server took responsibility
                    657:  *             for the exception.  So good bye, charlie.
                    658:  *     Conditions:
                    659:  *             Nothing locked and no resources held.
                    660:  *             Called from an exception context, so
                    661:  *             thread_kdb_return is possible.
                    662:  *     Returns:
                    663:  *             Doesn't return.
                    664:  */
                    665: 
                    666: void
                    667: exception_no_server(void)
                    668: {
                    669:        register thread_t self = current_thread();
                    670: 
                    671:        /*
                    672:         *      If this thread is being terminated, cooperate.
                    673:         *
                    674:         * When a task is dying, it's no longer ripped
                    675:         * directly out of the rcv from its "kill me" message, and
                    676:         * so returns here.  The following causes it to return out
                    677:         * to the glue code and clean itself up.
                    678:         */
                    679:        if ((thread_should_halt(self)) || (self->state & TH_ABORT)) {
                    680:                thread_exception_return();
                    681:                panic("exception_no_server - 1");
                    682:        }
                    683: 
                    684: 
                    685:        if (self->top_act->task == kernel_task)
                    686:                panic("kernel task terminating\n");
                    687: 
                    688: #if    MACH_KDB
                    689:        if (debug_user_with_kdb) {
                    690:                /*
                    691:                 *      Debug the exception with kdb.
                    692:                 *      If kdb handles the exception,
                    693:                 *      then thread_kdb_return won't return.
                    694:                 */
                    695:                db_printf("No exception server, calling kdb...\n");
                    696: #if    iPSC860
                    697:                db_printf("Dropping into ddb, avoiding thread_kdb_return\n");
                    698:                gimmeabreak();
                    699: #endif
                    700:                thread_kdb_return();
                    701:        }
                    702: #endif /* MACH_KDB */
                    703: 
                    704:        /*
                    705:         *      All else failed; terminate task.
                    706:         */
                    707: 
                    708:        (void) task_terminate(self->top_act->task);
                    709:        thread_terminate_self();
                    710:        /*NOTREACHED*/
                    711:        panic("exception_no_server: returning!");
                    712: }
                    713: 
                    714: #ifdef MACHINE_FAST_EXCEPTION  /* from <machine/thread.h> if at all */
                    715: /*
                    716:  *     Routine:        alert_exception
                    717:  *     Purpose:
                    718:  *             The current thread caught an exception.
                    719:  *             We make an up-call to the thread's exception server.
                    720:  *     Conditions:
                    721:  *             Nothing locked and no resources held.
                    722:  *     Returns:
                    723:  *             KERN_RPC_TERMINATE_ORPHAN - if orphan should be terminated
                    724:  *             KERN_RPC_CONTINUE_ORPHAN - if orphan should be allowed to
                    725:  *                     continue execution
                    726:  */
                    727: 
                    728: kern_return_t
                    729: alert_exception(
                    730:        exception_type_t        exception,
                    731:        exception_data_t        code,
                    732:        int                     codeCnt )
                    733: {
                    734:        thread_t                self = current_thread();
                    735:        thread_act_t            a_self = self->top_act;
                    736:        thread_act_t            cln_act;
                    737:        ipc_port_t              exc_port;
                    738:        int                     i;
                    739:        struct exception_action *excp = &a_self->exc_actions[exception];
                    740:        int                     flavor;
                    741:        kern_return_t           kr;
                    742: 
                    743:        assert(exception == EXC_RPC_ALERT);
                    744: 
                    745:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    746: 
                    747:        /*
                    748:         *      Optimized version of retrieve_thread_exception.
                    749:         */
                    750: 
                    751:        act_lock(a_self);
                    752:        assert(a_self->ith_self != IP_NULL);
                    753:        exc_port = excp->port;
                    754:        if (!IP_VALID(exc_port)) {
                    755:                act_unlock(a_self);
                    756:                return(alert_exception_try_task(exception, code, codeCnt));
                    757:        }
                    758:        flavor = excp->flavor;
                    759: 
                    760: #ifdef i386
                    761:        /* For this flavor, we must copy in the first few procedure call
                    762:         * args from the user's stack, since that is part of the important
                    763:         * state in a syscall exception (this is for performance -- we
                    764:         * can do the copyin much faster than the server, even if it is
                    765:         * kernel-loaded):
                    766:         */
                    767:        if (flavor == i386_SAVED_STATE) {
                    768:                struct i386_saved_state *statep = (struct i386_saved_state *)
                    769:                                        act_machine_state_ptr(self->top_act);
                    770:                statep->argv_status = FALSE;
                    771:                if (syscall_exc_copyin && copyin((char *)statep->uesp,
                    772:                           (char *)statep->argv,
                    773:                           i386_SAVED_ARGV_COUNT * sizeof(int)) == 0) {
                    774:                        /* Indicate success for the server: */
                    775:                        statep->argv_status = TRUE;
                    776:                }
                    777:        }
                    778: #endif
                    779: 
                    780:        ip_lock(exc_port);
                    781:        act_unlock(a_self);
                    782:        if (!ip_active(exc_port)) {
                    783:                ip_unlock(exc_port);
                    784:                return(alert_exception_try_task(exception, code, codeCnt));
                    785:        }
                    786: 
                    787:        /*
                    788:         * Hold a reference to the port over the exception_raise_* calls
                    789:         * so it can't be destroyed.  This seems like overkill, but keeps
                    790:         * the port from disappearing between now and when
                    791:         * ipc_object_copyin_from_kernel is finally called.
                    792:         */
                    793:        ip_reference(exc_port);
                    794:        /* CHECKME! */
                    795:        /* exc_port->ip_srights++; ipc_object_copy_from_kernel does this */
                    796:        ip_unlock(exc_port);
                    797: 
                    798:        switch (excp->behavior) {
                    799:        case EXCEPTION_STATE: {
                    800:            mach_msg_type_number_t state_cnt;
                    801:            {
                    802:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    803: 
                    804:                state_cnt = state_count[flavor];
                    805:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                    806:                if (kr == KERN_SUCCESS) {
                    807:                    kr = exception_raise_state(exc_port, exception,
                    808:                                code, codeCnt,
                    809:                                &flavor,
                    810:                                state, state_cnt,
                    811:                                state, &state_cnt);
                    812:                    if (kr == MACH_MSG_SUCCESS)
                    813:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                    814:                }
                    815:            }
                    816:            ip_lock(exc_port);
                    817:            ip_release(exc_port);       
                    818:            ip_unlock(exc_port);
                    819: 
                    820:            if (kr == KERN_SUCCESS ||
                    821:                kr == MACH_RCV_PORT_DIED) {
                    822:                    return(KERN_RPC_TERMINATE_ORPHAN);
                    823:            }
                    824:            } break;
                    825: 
                    826:        case EXCEPTION_DEFAULT:
                    827:                c_thr_exc_raise++;
                    828:                kr = exception_raise(exc_port,
                    829:                                retrieve_act_self_fast(a_self),
                    830:                                retrieve_task_self_fast(a_self->task),
                    831:                                exception,
                    832:                                code, codeCnt);
                    833:                ip_lock(exc_port);
                    834:                ip_release(exc_port);   
                    835:                ip_unlock(exc_port);
                    836: 
                    837:                if (kr == KERN_SUCCESS ||
                    838:                    kr == MACH_RCV_PORT_DIED) {
                    839:                        return(KERN_RPC_TERMINATE_ORPHAN);
                    840:                }
                    841:                break;
                    842: 
                    843:        case EXCEPTION_STATE_IDENTITY: {
                    844:                mach_msg_type_number_t state_cnt;
                    845:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    846: 
                    847:                c_thr_exc_raise_state_id++;
                    848:                state_cnt = state_count[flavor];
                    849:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                    850:                if (kr == KERN_SUCCESS) {
                    851:                    kr = exception_raise_state_identity(exc_port,
                    852:                                retrieve_act_self_fast(a_self),
                    853:                                retrieve_task_self_fast(a_self->task),
                    854:                                exception,
                    855:                                code, codeCnt,
                    856:                                &flavor,
                    857:                                state, state_cnt,
                    858:                                state, &state_cnt);
                    859:                    if (kr == MACH_MSG_SUCCESS)
                    860:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                    861:                }
                    862:                ip_lock(exc_port);
                    863:                ip_release(exc_port);   
                    864:                ip_unlock(exc_port);
                    865: 
                    866:                if (kr == KERN_SUCCESS ||
                    867:                    kr == MACH_RCV_PORT_DIED) {
                    868:                        return(KERN_RPC_TERMINATE_ORPHAN);
                    869:                }
                    870:                } break;
                    871:        default:
                    872:                panic ("bad behavior!");
                    873:        }/* switch */
                    874: 
                    875:        /*
                    876:         * When a task is being terminated, it's no longer ripped
                    877:         * directly out of the rcv from its "kill me" message, and
                    878:         * so returns here.  The following causes it to return out
                    879:         * to the glue code and clean itself up.
                    880:         */
                    881:        if (self->top_act && !self->top_act->active)
                    882:                return(KERN_RPC_TERMINATE_ORPHAN);
                    883: 
                    884:        return(alert_exception_try_task(exception, code, codeCnt));
                    885: }
                    886: #else  /* MACHINE_FAST_EXCEPTION */
                    887: 
                    888: /*
                    889:  *     Routine:        alert_exception
                    890:  *     Purpose:
                    891:  *             The current thread caught an exception.
                    892:  *             We make an up-call to the thread's exception server.
                    893:  *     Conditions:
                    894:  *             Nothing locked and no resources held.
                    895:  *     Returns:
                    896:  *             KERN_RPC_TERMINATE_ORPHAN - if orphan should be terminated
                    897:  *             KERN_RPC_CONTINUE_ORPHAN - if orphan should be allowed to
                    898:  *                     continue execution
                    899:  */
                    900: 
                    901: kern_return_t
                    902: alert_exception(
                    903:        exception_type_t        exception,
                    904:        exception_data_t        code,
                    905:        int                     codeCnt )
                    906: {
                    907:        thread_t                self = current_thread();
                    908:        thread_act_t            a_self = self->top_act;
                    909:        ipc_port_t              exc_port;
                    910:        int                     i;
                    911:        struct exception_action *excp = &a_self->exc_actions[exception];
                    912:        int                     flavor;
                    913:        kern_return_t           kr;
                    914: 
                    915:        assert(exception == EXC_RPC_ALERT);
                    916: 
                    917:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                    918: 
                    919:        /*
                    920:         *      Optimized version of retrieve_thread_exception.
                    921:         */
                    922: 
                    923:        act_lock(a_self);
                    924:        assert(a_self->ith_self != IP_NULL);
                    925:        exc_port = excp->port;
                    926:        if (!IP_VALID(exc_port)) {
                    927:                act_unlock(a_self);
                    928:                return(alert_exception_try_task(exception, code, codeCnt));
                    929:        }
                    930:        flavor = excp->flavor;
                    931: 
                    932:        ip_lock(exc_port);
                    933:        act_unlock(a_self);
                    934:        if (!ip_active(exc_port)) {
                    935:                ip_unlock(exc_port);
                    936:                return(alert_exception_try_task(exception, code, codeCnt));
                    937:        }
                    938: 
                    939:        /*
                    940:         * Hold a reference to the port over the exception_raise_* calls
                    941:         * so it can't be destroyed.  This seems like overkill, but keeps
                    942:         * the port from disappearing between now and when
                    943:         * ipc_object_copyin_from_kernel is finally called.
                    944:         */
                    945:        ip_reference(exc_port); 
                    946:        /* CHECKME! */
                    947:        /* exc_port->ip_srights++; ipc_object_copy_from_kernel does this */
                    948:        ip_unlock(exc_port);
                    949: 
                    950:        switch (excp->behavior) {
                    951:        case EXCEPTION_STATE: {
                    952:                mach_msg_type_number_t state_cnt;
                    953:                rpc_subsystem_t subsystem = ((ipc_port_t)exc_port)->ip_subsystem;
                    954: 
                    955:                c_thr_exc_raise_state++;
                    956:                if (flavor == MACHINE_THREAD_STATE &&
                    957:                                subsystem &&
                    958:                            is_fast_space(exc_port->ip_receiver)) {
                    959:                        natural_t *statep;
                    960:                        /* Requested flavor is the same format in which
                    961:                         * we save state on this machine, so no copy is
                    962:                         * necessary.  Obtain direct pointer to saved state:
                    963:                         */
                    964:                        statep = act_machine_state_ptr(self->top_act);
                    965:                        state_cnt = MACHINE_THREAD_STATE_COUNT;
                    966:                        kr = exception_raise_state(exc_port, exception,
                    967:                                    code, codeCnt,
                    968:                                    &flavor,
                    969:                                    statep, state_cnt,
                    970:                                    statep, &state_cnt);
                    971:                        /* Server is required to return same flavor: */
                    972:                        assert(flavor == MACHINE_THREAD_STATE);
                    973:                } else {
                    974:                        natural_t state[ THREAD_MACHINE_STATE_MAX ];
                    975: 
                    976:                        state_cnt = state_count[flavor];
                    977:                        kr = thread_getstatus(a_self, flavor,
                    978:                                              (thread_state_t)state,
                    979:                                              &state_cnt);
                    980:                        if (kr == KERN_SUCCESS) {
                    981:                            kr = exception_raise_state(exc_port, exception,
                    982:                                        code, codeCnt,
                    983:                                        &flavor,
                    984:                                        state, state_cnt,
                    985:                                        state, &state_cnt);
                    986:                            if (kr == MACH_MSG_SUCCESS)
                    987:                                kr = thread_setstatus(a_self, flavor,
                    988:                                                      (thread_state_t)state,
                    989:                                                      state_cnt);
                    990:                        }
                    991:                }
                    992:                ip_lock(exc_port);
                    993:                ip_release(exc_port);   
                    994:                ip_unlock(exc_port);
                    995: 
                    996:                if (kr == KERN_SUCCESS ||
                    997:                    kr == MACH_RCV_PORT_DIED) {
                    998:                        return(KERN_RPC_TERMINATE_ORPHAN);
                    999:                }
                   1000:                } break;
                   1001: 
                   1002:        case EXCEPTION_DEFAULT:
                   1003:                c_thr_exc_raise++;
                   1004:                kr = exception_raise(exc_port,
                   1005:                                retrieve_act_self_fast(a_self),
                   1006:                                retrieve_task_self_fast(a_self->task),
                   1007:                                exception,
                   1008:                                code, codeCnt);
                   1009:                ip_lock(exc_port);
                   1010:                ip_release(exc_port);   
                   1011:                ip_unlock(exc_port);
                   1012: 
                   1013:                if (kr == KERN_SUCCESS ||
                   1014:                    kr == MACH_RCV_PORT_DIED) {
                   1015:                        return(KERN_RPC_TERMINATE_ORPHAN);
                   1016:                }
                   1017:                break;
                   1018: 
                   1019:        case EXCEPTION_STATE_IDENTITY: {
                   1020:                mach_msg_type_number_t state_cnt;
                   1021:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                   1022: 
                   1023:                c_thr_exc_raise_state_id++;
                   1024:                state_cnt = state_count[flavor];
                   1025:                kr = thread_getstatus(a_self, flavor,
                   1026:                                      (thread_state_t)state,
                   1027:                                      &state_cnt);
                   1028:                if (kr == KERN_SUCCESS) {
                   1029:                    kr = exception_raise_state_identity(exc_port,
                   1030:                                retrieve_act_self_fast(a_self),
                   1031:                                retrieve_task_self_fast(a_self->task),
                   1032:                                exception,
                   1033:                                code, codeCnt,
                   1034:                                &flavor,
                   1035:                                state, state_cnt,
                   1036:                                state, &state_cnt);
                   1037:                    if (kr == MACH_MSG_SUCCESS)
                   1038:                            kr = thread_setstatus(a_self, flavor,
                   1039:                                                  (thread_state_t)state,
                   1040:                                                  state_cnt);
                   1041:                }
                   1042:                ip_lock(exc_port);
                   1043:                ip_release(exc_port);   
                   1044:                ip_unlock(exc_port);
                   1045: 
                   1046:                if (kr == KERN_SUCCESS ||
                   1047:                    kr == MACH_RCV_PORT_DIED) {
                   1048:                        return(KERN_RPC_TERMINATE_ORPHAN);
                   1049:                }
                   1050:                } break;
                   1051:        default:
                   1052:                panic ("bad behavior!");
                   1053:        }/* switch */
                   1054: 
                   1055:        /*
                   1056:         * When a task is being terminated, it's no longer ripped
                   1057:         * directly out of the rcv from its "kill me" message, and
                   1058:         * so returns here.  The following causes it to return out
                   1059:         * to the glue code and clean itself up.
                   1060:         */
                   1061:        if (thread_should_halt(self)) {
                   1062:                return(KERN_RPC_TERMINATE_ORPHAN);
                   1063:        }
                   1064: 
                   1065:        return(alert_exception_try_task(exception, code, codeCnt));
                   1066: }
                   1067: #endif /* defined MACHINE_FAST_EXCEPTION */
                   1068: 
                   1069: /*
                   1070:  *     Routine:        alert_exception_try_task
                   1071:  *     Purpose:
                   1072:  *             The current thread caught an exception.
                   1073:  *             We make an up-call to the task's exception server.
                   1074:  *     Conditions:
                   1075:  *             Nothing locked and no resources held.
                   1076:  *     Returns:
                   1077:  *             KERN_RPC_TERMINATE_ORPHAN - if orphan should be terminated
                   1078:  *             KERN_RPC_CONTINUE_ORPHAN - if orphan should be allowed to
                   1079:  *                     continue execution
                   1080:  */
                   1081: 
                   1082: kern_return_t
                   1083: alert_exception_try_task(
                   1084:        exception_type_t        exception,
                   1085:        exception_data_t        code,
                   1086:        int                     codeCnt )
                   1087: {
                   1088:        thread_act_t    a_self = current_act();
                   1089:        thread_t self = a_self->thread;
                   1090:        register task_t task = a_self->task;
                   1091:        register ipc_port_t exc_port;
                   1092:        int flavor;
                   1093:        kern_return_t kr;
                   1094: 
                   1095:        assert(exception == EXC_RPC_ALERT);
                   1096: 
                   1097:        self->ith_scatter_list = MACH_MSG_BODY_NULL;
                   1098: 
                   1099:        /*
                   1100:         *      Optimized version of retrieve_task_exception.
                   1101:         */
                   1102: 
                   1103:        itk_lock(task);
                   1104:        assert(task->itk_self != IP_NULL);
                   1105:        exc_port = task->exc_actions[exception].port;
                   1106:        if (!IP_VALID(exc_port)) {
                   1107:                itk_unlock(task);
                   1108:                return(KERN_RPC_CONTINUE_ORPHAN);
                   1109:        }
                   1110:        flavor = task->exc_actions[exception].flavor;
                   1111: 
                   1112:        ip_lock(exc_port);
                   1113:        itk_unlock(task);
                   1114:        if (!ip_active(exc_port)) {
                   1115:                ip_unlock(exc_port);
                   1116:                return(KERN_RPC_CONTINUE_ORPHAN);
                   1117:        }
                   1118: 
                   1119:        /*
                   1120:         * Hold a reference to the port over the exception_raise_* calls
                   1121:         * (see longer comment in exception())
                   1122:         */
                   1123:        ip_reference(exc_port);
                   1124:        /* CHECKME! */
                   1125:        /* exc_port->ip_srights++; */
                   1126:        ip_unlock(exc_port);
                   1127: 
                   1128:        switch (task->exc_actions[exception].behavior) {
                   1129:        case EXCEPTION_STATE: {
                   1130:                mach_msg_type_number_t state_cnt;
                   1131:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                   1132: 
                   1133:                c_tsk_exc_raise_state++;
                   1134:                state_cnt = state_count[flavor];
                   1135:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                   1136:                if (kr == KERN_SUCCESS) {
                   1137:                    kr = exception_raise_state(exc_port, exception,
                   1138:                                code, codeCnt,
                   1139:                                &flavor,
                   1140:                                state, state_cnt,
                   1141:                                state, &state_cnt);
                   1142:                    if (kr == KERN_SUCCESS)
                   1143:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                   1144:                }
                   1145:                ip_lock(exc_port);
                   1146:                ip_release(exc_port);
                   1147:                ip_unlock(exc_port);
                   1148: 
                   1149:                if (kr == MACH_MSG_SUCCESS || kr == MACH_RCV_PORT_DIED) {
                   1150:                    return(KERN_RPC_TERMINATE_ORPHAN);
                   1151:                }
                   1152:                } break;
                   1153: 
                   1154:        case EXCEPTION_DEFAULT:
                   1155:                c_tsk_exc_raise++;
                   1156:                kr = exception_raise(exc_port,
                   1157:                                retrieve_act_self_fast(a_self),
                   1158:                                retrieve_task_self_fast(a_self->task),
                   1159:                                exception, code, codeCnt);
                   1160:                ip_lock(exc_port);
                   1161:                ip_release(exc_port);
                   1162:                ip_unlock(exc_port);
                   1163: 
                   1164:                if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED) {
                   1165:                    return(KERN_RPC_TERMINATE_ORPHAN);
                   1166:                }
                   1167:                break;
                   1168: 
                   1169:        case EXCEPTION_STATE_IDENTITY: {
                   1170:                mach_msg_type_number_t state_cnt;
                   1171:                natural_t state[ THREAD_MACHINE_STATE_MAX ];
                   1172: 
                   1173:                c_tsk_exc_raise_state_id++;
                   1174:                state_cnt = state_count[flavor];
                   1175:                kr = thread_getstatus(a_self, flavor, state, &state_cnt);
                   1176:                if (kr == KERN_SUCCESS) {
                   1177:                    kr = exception_raise_state_identity(exc_port,
                   1178:                                retrieve_act_self_fast(a_self),
                   1179:                                retrieve_task_self_fast(a_self->task),
                   1180:                                exception,
                   1181:                                code, codeCnt,
                   1182:                                &flavor,
                   1183:                                state, state_cnt,
                   1184:                                state, &state_cnt);
                   1185:                    if (kr == KERN_SUCCESS)
                   1186:                        kr = thread_setstatus(a_self, flavor, state, state_cnt);
                   1187:                }
                   1188:                ip_lock(exc_port);
                   1189:                ip_release(exc_port);
                   1190:                ip_unlock(exc_port);
                   1191: 
                   1192:                if (kr == MACH_MSG_SUCCESS || kr == MACH_RCV_PORT_DIED) {
                   1193:                    return(KERN_RPC_TERMINATE_ORPHAN);
                   1194:                }
                   1195:                } break;
                   1196: 
                   1197:        default:
                   1198:                panic ("bad behavior!");
                   1199:        }/* switch */
                   1200: 
                   1201:        return(KERN_RPC_CONTINUE_ORPHAN);
                   1202: }

unix.superglobalmegacorp.com

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