Annotation of XNU/osfmk/kern/exception.c, revision 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.