Annotation of OSKit-Mach/kern/ipc_tt.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  *
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  *
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  *
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  *
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  *
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  * File:       ipc_tt.c
                     28:  * Purpose:
                     29:  *     Task and thread related IPC functions.
                     30:  */
                     31: 
                     32: #include <mach_ipc_compat.h>
                     33: 
                     34: #include <mach/boolean.h>
                     35: #include <mach/kern_return.h>
                     36: #include <mach/mach_param.h>
                     37: #include <mach/task_special_ports.h>
                     38: #include <mach/thread_special_ports.h>
                     39: #include <vm/vm_kern.h>
                     40: #include <kern/task.h>
                     41: #include <kern/thread.h>
                     42: #include <kern/ipc_kobject.h>
                     43: #include <kern/ipc_tt.h>
                     44: #include <ipc/ipc_space.h>
                     45: #include <ipc/ipc_table.h>
                     46: #include <ipc/ipc_port.h>
                     47: #include <ipc/ipc_right.h>
                     48: #include <ipc/ipc_entry.h>
                     49: #include <ipc/ipc_object.h>
                     50: 
                     51: 
                     52: 
                     53: /*
                     54:  *     Routine:        ipc_task_init
                     55:  *     Purpose:
                     56:  *             Initialize a task's IPC state.
                     57:  *
                     58:  *             If non-null, some state will be inherited from the parent.
                     59:  *             The parent must be appropriately initialized.
                     60:  *     Conditions:
                     61:  *             Nothing locked.
                     62:  */
                     63: 
                     64: void
                     65: ipc_task_init(
                     66:        task_t          task,
                     67:        task_t          parent)
                     68: {
                     69:        ipc_space_t space;
                     70:        ipc_port_t kport;
                     71:        kern_return_t kr;
                     72:        int i;
                     73: 
                     74: 
                     75:        kr = ipc_space_create(&ipc_table_entries[0], &space);
                     76:        if (kr != KERN_SUCCESS)
                     77:                panic("ipc_task_init");
                     78: 
                     79: 
                     80:        kport = ipc_port_alloc_kernel();
                     81:        if (kport == IP_NULL)
                     82:                panic("ipc_task_init");
                     83: 
                     84:        itk_lock_init(task);
                     85:        task->itk_self = kport;
                     86:        task->itk_sself = ipc_port_make_send(kport);
                     87:        task->itk_space = space;
                     88: 
                     89:        if (parent == TASK_NULL) {
                     90:                task->itk_exception = IP_NULL;
                     91:                task->itk_bootstrap = IP_NULL;
                     92:                for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                     93:                        task->itk_registered[i] = IP_NULL;
                     94:        } else {
                     95:                itk_lock(parent);
                     96:                assert(parent->itk_self != IP_NULL);
                     97: 
                     98:                /* inherit registered ports */
                     99: 
                    100:                for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                    101:                        task->itk_registered[i] =
                    102:                                ipc_port_copy_send(parent->itk_registered[i]);
                    103: 
                    104:                /* inherit exception and bootstrap ports */
                    105: 
                    106:                task->itk_exception =
                    107:                        ipc_port_copy_send(parent->itk_exception);
                    108:                task->itk_bootstrap =
                    109:                        ipc_port_copy_send(parent->itk_bootstrap);
                    110: 
                    111:                itk_unlock(parent);
                    112:        }
                    113: }
                    114: 
                    115: /*
                    116:  *     Routine:        ipc_task_enable
                    117:  *     Purpose:
                    118:  *             Enable a task for IPC access.
                    119:  *     Conditions:
                    120:  *             Nothing locked.
                    121:  */
                    122: 
                    123: void
                    124: ipc_task_enable(
                    125:        task_t          task)
                    126: {
                    127:        ipc_port_t kport;
                    128: 
                    129:        itk_lock(task);
                    130:        kport = task->itk_self;
                    131:        if (kport != IP_NULL)
                    132:                ipc_kobject_set(kport, (ipc_kobject_t) task, IKOT_TASK);
                    133:        itk_unlock(task);
                    134: }
                    135: 
                    136: /*
                    137:  *     Routine:        ipc_task_disable
                    138:  *     Purpose:
                    139:  *             Disable IPC access to a task.
                    140:  *     Conditions:
                    141:  *             Nothing locked.
                    142:  */
                    143: 
                    144: void
                    145: ipc_task_disable(
                    146:        task_t          task)
                    147: {
                    148:        ipc_port_t kport;
                    149: 
                    150:        itk_lock(task);
                    151:        kport = task->itk_self;
                    152:        if (kport != IP_NULL)
                    153:                ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
                    154:        itk_unlock(task);
                    155: }
                    156: 
                    157: /*
                    158:  *     Routine:        ipc_task_terminate
                    159:  *     Purpose:
                    160:  *             Clean up and destroy a task's IPC state.
                    161:  *     Conditions:
                    162:  *             Nothing locked.  The task must be suspended.
                    163:  *             (Or the current thread must be in the task.)
                    164:  */
                    165: 
                    166: void
                    167: ipc_task_terminate(
                    168:        task_t          task)
                    169: {
                    170:        ipc_port_t kport;
                    171:        int i;
                    172: 
                    173:        itk_lock(task);
                    174:        kport = task->itk_self;
                    175: 
                    176:        if (kport == IP_NULL) {
                    177:                /* the task is already terminated (can this happen?) */
                    178:                itk_unlock(task);
                    179:                return;
                    180:        }
                    181: 
                    182:        task->itk_self = IP_NULL;
                    183:        itk_unlock(task);
                    184: 
                    185:        /* release the naked send rights */
                    186: 
                    187:        if (IP_VALID(task->itk_sself))
                    188:                ipc_port_release_send(task->itk_sself);
                    189:        if (IP_VALID(task->itk_exception))
                    190:                ipc_port_release_send(task->itk_exception);
                    191:        if (IP_VALID(task->itk_bootstrap))
                    192:                ipc_port_release_send(task->itk_bootstrap);
                    193: 
                    194:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                    195:                if (IP_VALID(task->itk_registered[i]))
                    196:                        ipc_port_release_send(task->itk_registered[i]);
                    197: 
                    198:        /* destroy the space, leaving just a reference for it */
                    199: 
                    200:        ipc_space_destroy(task->itk_space);
                    201: 
                    202:        /* destroy the kernel port */
                    203: 
                    204:        ipc_port_dealloc_kernel(kport);
                    205: }
                    206: 
                    207: /*
                    208:  *     Routine:        ipc_thread_init
                    209:  *     Purpose:
                    210:  *             Initialize a thread's IPC state.
                    211:  *     Conditions:
                    212:  *             Nothing locked.
                    213:  */
                    214: 
                    215: void
                    216: ipc_thread_init(thread)
                    217:        thread_t thread;
                    218: {
                    219:        ipc_port_t kport;
                    220: 
                    221:        kport = ipc_port_alloc_kernel();
                    222:        if (kport == IP_NULL)
                    223:                panic("ipc_thread_init");
                    224: 
                    225:        ipc_thread_links_init(thread);
                    226:        ipc_kmsg_queue_init(&thread->ith_messages);
                    227: 
                    228:        ith_lock_init(thread);
                    229:        thread->ith_self = kport;
                    230:        thread->ith_sself = ipc_port_make_send(kport);
                    231:        thread->ith_exception = IP_NULL;
                    232: 
                    233:        thread->ith_mig_reply = MACH_PORT_NULL;
                    234:        thread->ith_rpc_reply = IP_NULL;
                    235: 
                    236: #if    MACH_IPC_COMPAT
                    237:     {
                    238:        ipc_space_t space = thread->task->itk_space;
                    239:        ipc_port_t port;
                    240:        mach_port_t name;
                    241:        kern_return_t kr;
                    242: 
                    243:        kr = ipc_port_alloc_compat(space, &name, &port);
                    244:        if (kr != KERN_SUCCESS)
                    245:                panic("ipc_thread_init");
                    246:        /* port is locked and active */
                    247: 
                    248:        /*
                    249:         *      Now we have a reply port.  We need to make a naked
                    250:         *      send right to stash in ith_reply.  We can't use
                    251:         *      ipc_port_make_send, because we can't unlock the port
                    252:         *      before making the right.  Also we don't want to
                    253:         *      increment ip_mscount.  The net effect of all this
                    254:         *      is the same as doing
                    255:         *              ipc_port_alloc_kernel           get the port
                    256:         *              ipc_port_make_send              make the send right
                    257:         *              ipc_object_copyin_from_kernel   grab receive right
                    258:         *              ipc_object_copyout_compat       and give to user
                    259:         */
                    260: 
                    261:        port->ip_srights++;
                    262:        ip_reference(port);
                    263:        ip_unlock(port);
                    264: 
                    265:        thread->ith_reply = port;
                    266:     }
                    267: #endif /* MACH_IPC_COMPAT */
                    268: }
                    269: 
                    270: /*
                    271:  *     Routine:        ipc_thread_enable
                    272:  *     Purpose:
                    273:  *             Enable a thread for IPC access.
                    274:  *     Conditions:
                    275:  *             Nothing locked.
                    276:  */
                    277: 
                    278: void
                    279: ipc_thread_enable(thread)
                    280:        thread_t thread;
                    281: {
                    282:        ipc_port_t kport;
                    283: 
                    284:        ith_lock(thread);
                    285:        kport = thread->ith_self;
                    286:        if (kport != IP_NULL)
                    287:                ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD);
                    288:        ith_unlock(thread);
                    289: }
                    290: 
                    291: /*
                    292:  *     Routine:        ipc_thread_disable
                    293:  *     Purpose:
                    294:  *             Disable IPC access to a thread.
                    295:  *     Conditions:
                    296:  *             Nothing locked.
                    297:  */
                    298: 
                    299: void
                    300: ipc_thread_disable(thread)
                    301:        thread_t thread;
                    302: {
                    303:        ipc_port_t kport;
                    304: 
                    305:        ith_lock(thread);
                    306:        kport = thread->ith_self;
                    307:        if (kport != IP_NULL)
                    308:                ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
                    309:        ith_unlock(thread);
                    310: }
                    311: 
                    312: /*
                    313:  *     Routine:        ipc_thread_terminate
                    314:  *     Purpose:
                    315:  *             Clean up and destroy a thread's IPC state.
                    316:  *     Conditions:
                    317:  *             Nothing locked.  The thread must be suspended.
                    318:  *             (Or be the current thread.)
                    319:  */
                    320: 
                    321: void
                    322: ipc_thread_terminate(thread)
                    323:        thread_t thread;
                    324: {
                    325:        ipc_port_t kport;
                    326: 
                    327:        ith_lock(thread);
                    328:        kport = thread->ith_self;
                    329: 
                    330:        if (kport == IP_NULL) {
                    331:                /* the thread is already terminated (can this happen?) */
                    332:                ith_unlock(thread);
                    333:                return;
                    334:        }
                    335: 
                    336:        thread->ith_self = IP_NULL;
                    337:        ith_unlock(thread);
                    338: 
                    339:        assert(ipc_kmsg_queue_empty(&thread->ith_messages));
                    340: 
                    341:        /* release the naked send rights */
                    342: 
                    343:        if (IP_VALID(thread->ith_sself))
                    344:                ipc_port_release_send(thread->ith_sself);
                    345:        if (IP_VALID(thread->ith_exception))
                    346:                ipc_port_release_send(thread->ith_exception);
                    347: 
                    348: #if    MACH_IPC_COMPAT
                    349:        if (IP_VALID(thread->ith_reply)) {
                    350:                ipc_space_t space = thread->task->itk_space;
                    351:                ipc_port_t port = thread->ith_reply;
                    352:                ipc_entry_t entry;
                    353:                mach_port_t name;
                    354: 
                    355:                /* destroy any rights the task may have for the port */
                    356: 
                    357:                is_write_lock(space);
                    358:                if (space->is_active &&
                    359:                    ipc_right_reverse(space, (ipc_object_t) port,
                    360:                                      &name, &entry)) {
                    361:                        /* reply port is locked and active */
                    362:                        ip_unlock(port);
                    363: 
                    364:                        (void) ipc_right_destroy(space, name, entry);
                    365:                        /* space is unlocked */
                    366:                } else
                    367:                        is_write_unlock(space);
                    368: 
                    369:                ipc_port_release_send(port);
                    370:        }
                    371: 
                    372:        /*
                    373:         *      Note we do *not* destroy any rights the space may have
                    374:         *      for the thread's kernel port.  The old IPC code did this,
                    375:         *      to avoid generating a notification when the port is
                    376:         *      destroyed.  However, this isn't a good idea when
                    377:         *      the kernel port is interposed, because then it doesn't
                    378:         *      happen, exposing the interposition to the task.
                    379:         *      Because we don't need the efficiency hack, I flushed
                    380:         *      this behaviour, introducing a small incompatibility
                    381:         *      with the old IPC code.
                    382:         */
                    383: #endif /* MACH_IPC_COMPAT */
                    384: 
                    385:        /* destroy the kernel port */
                    386: 
                    387:        ipc_port_dealloc_kernel(kport);
                    388: }
                    389: 
                    390: #if    0
                    391: /*
                    392:  *     Routine:        retrieve_task_self
                    393:  *     Purpose:
                    394:  *             Return a send right (possibly null/dead)
                    395:  *             for the task's user-visible self port.
                    396:  *     Conditions:
                    397:  *             Nothing locked.
                    398:  */
                    399: 
                    400: ipc_port_t
                    401: retrieve_task_self(task)
                    402:        task_t task;
                    403: {
                    404:        ipc_port_t port;
                    405: 
                    406:        assert(task != TASK_NULL);
                    407: 
                    408:        itk_lock(task);
                    409:        if (task->itk_self != IP_NULL)
                    410:                port = ipc_port_copy_send(task->itk_sself);
                    411:        else
                    412:                port = IP_NULL;
                    413:        itk_unlock(task);
                    414: 
                    415:        return port;
                    416: }
                    417: 
                    418: /*
                    419:  *     Routine:        retrieve_thread_self
                    420:  *     Purpose:
                    421:  *             Return a send right (possibly null/dead)
                    422:  *             for the thread's user-visible self port.
                    423:  *     Conditions:
                    424:  *             Nothing locked.
                    425:  */
                    426: 
                    427: ipc_port_t
                    428: retrieve_thread_self(thread)
                    429:        thread_t thread;
                    430: {
                    431:        ipc_port_t port;
                    432: 
                    433:        assert(thread != ITH_NULL);
                    434: 
                    435:        ith_lock(thread);
                    436:        if (thread->ith_self != IP_NULL)
                    437:                port = ipc_port_copy_send(thread->ith_sself);
                    438:        else
                    439:                port = IP_NULL;
                    440:        ith_unlock(thread);
                    441: 
                    442:        return port;
                    443: }
                    444: #endif /* 0 */
                    445: 
                    446: /*
                    447:  *     Routine:        retrieve_task_self_fast
                    448:  *     Purpose:
                    449:  *             Optimized version of retrieve_task_self,
                    450:  *             that only works for the current task.
                    451:  *
                    452:  *             Return a send right (possibly null/dead)
                    453:  *             for the task's user-visible self port.
                    454:  *     Conditions:
                    455:  *             Nothing locked.
                    456:  */
                    457: 
                    458: ipc_port_t
                    459: retrieve_task_self_fast(
                    460:        register task_t         task)
                    461: {
                    462:        register ipc_port_t port;
                    463: 
                    464:        assert(task == current_task());
                    465: 
                    466:        itk_lock(task);
                    467:        assert(task->itk_self != IP_NULL);
                    468: 
                    469:        if ((port = task->itk_sself) == task->itk_self) {
                    470:                /* no interposing */
                    471: 
                    472:                ip_lock(port);
                    473:                assert(ip_active(port));
                    474:                ip_reference(port);
                    475:                port->ip_srights++;
                    476:                ip_unlock(port);
                    477:        } else
                    478:                port = ipc_port_copy_send(port);
                    479:        itk_unlock(task);
                    480: 
                    481:        return port;
                    482: }
                    483: 
                    484: /*
                    485:  *     Routine:        retrieve_thread_self_fast
                    486:  *     Purpose:
                    487:  *             Optimized version of retrieve_thread_self,
                    488:  *             that only works for the current thread.
                    489:  *
                    490:  *             Return a send right (possibly null/dead)
                    491:  *             for the thread's user-visible self port.
                    492:  *     Conditions:
                    493:  *             Nothing locked.
                    494:  */
                    495: 
                    496: ipc_port_t
                    497: retrieve_thread_self_fast(thread)
                    498:        register thread_t thread;
                    499: {
                    500:        register ipc_port_t port;
                    501: 
                    502:        assert(thread == current_thread());
                    503: 
                    504:        ith_lock(thread);
                    505:        assert(thread->ith_self != IP_NULL);
                    506: 
                    507:        if ((port = thread->ith_sself) == thread->ith_self) {
                    508:                /* no interposing */
                    509: 
                    510:                ip_lock(port);
                    511:                assert(ip_active(port));
                    512:                ip_reference(port);
                    513:                port->ip_srights++;
                    514:                ip_unlock(port);
                    515:        } else
                    516:                port = ipc_port_copy_send(port);
                    517:        ith_unlock(thread);
                    518: 
                    519:        return port;
                    520: }
                    521: 
                    522: #if    0
                    523: /*
                    524:  *     Routine:        retrieve_task_exception
                    525:  *     Purpose:
                    526:  *             Return a send right (possibly null/dead)
                    527:  *             for the task's exception port.
                    528:  *     Conditions:
                    529:  *             Nothing locked.
                    530:  */
                    531: 
                    532: ipc_port_t
                    533: retrieve_task_exception(task)
                    534:        task_t task;
                    535: {
                    536:        ipc_port_t port;
                    537: 
                    538:        assert(task != TASK_NULL);
                    539: 
                    540:        itk_lock(task);
                    541:        if (task->itk_self != IP_NULL)
                    542:                port = ipc_port_copy_send(task->itk_exception);
                    543:        else
                    544:                port = IP_NULL;
                    545:        itk_unlock(task);
                    546: 
                    547:        return port;
                    548: }
                    549: 
                    550: /*
                    551:  *     Routine:        retrieve_thread_exception
                    552:  *     Purpose:
                    553:  *             Return a send right (possibly null/dead)
                    554:  *             for the thread's exception port.
                    555:  *     Conditions:
                    556:  *             Nothing locked.
                    557:  */
                    558: 
                    559: ipc_port_t
                    560: retrieve_thread_exception(thread)
                    561:        thread_t thread;
                    562: {
                    563:        ipc_port_t port;
                    564: 
                    565:        assert(thread != ITH_NULL);
                    566: 
                    567:        ith_lock(thread);
                    568:        if (thread->ith_self != IP_NULL)
                    569:                port = ipc_port_copy_send(thread->ith_exception);
                    570:        else
                    571:                port = IP_NULL;
                    572:        ith_unlock(thread);
                    573: 
                    574:        return port;
                    575: }
                    576: #endif /* 0 */
                    577: 
                    578: /*
                    579:  *     Routine:        mach_task_self [mach trap]
                    580:  *     Purpose:
                    581:  *             Give the caller send rights for his own task port.
                    582:  *     Conditions:
                    583:  *             Nothing locked.
                    584:  *     Returns:
                    585:  *             MACH_PORT_NULL if there are any resource failures
                    586:  *             or other errors.
                    587:  */
                    588: 
                    589: mach_port_t
                    590: mach_task_self(void)
                    591: {
                    592:        task_t task = current_task();
                    593:        ipc_port_t sright;
                    594: 
                    595:        sright = retrieve_task_self_fast(task);
                    596:        return ipc_port_copyout_send(sright, task->itk_space);
                    597: }
                    598: 
                    599: /*
                    600:  *     Routine:        mach_thread_self [mach trap]
                    601:  *     Purpose:
                    602:  *             Give the caller send rights for his own thread port.
                    603:  *     Conditions:
                    604:  *             Nothing locked.
                    605:  *     Returns:
                    606:  *             MACH_PORT_NULL if there are any resource failures
                    607:  *             or other errors.
                    608:  */
                    609: 
                    610: mach_port_t
                    611: mach_thread_self()
                    612: {
                    613:        thread_t thread = current_thread();
                    614:        task_t task = thread->task;
                    615:        ipc_port_t sright;
                    616: 
                    617:        sright = retrieve_thread_self_fast(thread);
                    618:        return ipc_port_copyout_send(sright, task->itk_space);
                    619: }
                    620: 
                    621: /*
                    622:  *     Routine:        mach_reply_port [mach trap]
                    623:  *     Purpose:
                    624:  *             Allocate a port for the caller.
                    625:  *     Conditions:
                    626:  *             Nothing locked.
                    627:  *     Returns:
                    628:  *             MACH_PORT_NULL if there are any resource failures
                    629:  *             or other errors.
                    630:  */
                    631: 
                    632: mach_port_t
                    633: mach_reply_port(void)
                    634: {
                    635:        ipc_port_t port;
                    636:        mach_port_t name;
                    637:        kern_return_t kr;
                    638: 
                    639:        kr = ipc_port_alloc(current_task()->itk_space, &name, &port);
                    640:        if (kr == KERN_SUCCESS)
                    641:                ip_unlock(port);
                    642:        else
                    643:                name = MACH_PORT_NULL;
                    644: 
                    645:        return name;
                    646: }
                    647: 
                    648: #if    MACH_IPC_COMPAT
                    649: 
                    650: /*
                    651:  *     Routine:        retrieve_task_notify
                    652:  *     Purpose:
                    653:  *             Return a reference (or null) for
                    654:  *             the task's notify port.
                    655:  *     Conditions:
                    656:  *             Nothing locked.
                    657:  */
                    658: 
                    659: ipc_port_t
                    660: retrieve_task_notify(task)
                    661:        task_t task;
                    662: {
                    663:        ipc_space_t space = task->itk_space;
                    664:        ipc_port_t port;
                    665: 
                    666:        is_read_lock(space);
                    667:        if (space->is_active) {
                    668:                port = space->is_notify;
                    669:                if (IP_VALID(port))
                    670:                        ipc_port_reference(port);
                    671:        } else
                    672:                port = IP_NULL;
                    673:        is_read_unlock(space);
                    674: 
                    675:        return port;
                    676: }
                    677: 
                    678: /*
                    679:  *     Routine:        retrieve_thread_reply
                    680:  *     Purpose:
                    681:  *             Return a reference (or null) for
                    682:  *             the thread's reply port.
                    683:  *     Conditions:
                    684:  *             Nothing locked.
                    685:  */
                    686: 
                    687: ipc_port_t
                    688: retrieve_thread_reply(thread)
                    689:        thread_t thread;
                    690: {
                    691:        ipc_port_t port;
                    692: 
                    693:        ith_lock(thread);
                    694:        if (thread->ith_self != IP_NULL) {
                    695:                port = thread->ith_reply;
                    696:                if (IP_VALID(port))
                    697:                        ipc_port_reference(port);
                    698:        } else
                    699:                port = IP_NULL;
                    700:        ith_unlock(thread);
                    701: 
                    702:        return port;
                    703: }
                    704: 
                    705: /*
                    706:  *     Routine:        task_self [mach trap]
                    707:  *     Purpose:
                    708:  *             Give the caller send rights for his task port.
                    709:  *             If new, the send right is marked with IE_BITS_COMPAT.
                    710:  *     Conditions:
                    711:  *             Nothing locked.
                    712:  *     Returns:
                    713:  *             MACH_PORT_NULL if there are any resource failures
                    714:  *             or other errors.
                    715:  */
                    716: 
                    717: port_name_t
                    718: task_self()
                    719: {
                    720:        task_t task = current_task();
                    721:        ipc_port_t sright;
                    722:        mach_port_t name;
                    723: 
                    724:        sright = retrieve_task_self_fast(task);
                    725:        name = ipc_port_copyout_send_compat(sright, task->itk_space);
                    726:        return (port_name_t) name;
                    727: }
                    728: 
                    729: /*
                    730:  *     Routine:        task_notify [mach trap]
                    731:  *     Purpose:
                    732:  *             Give the caller the name of his own notify port.
                    733:  *     Conditions:
                    734:  *             Nothing locked.
                    735:  *     Returns:
                    736:  *             MACH_PORT_NULL if there isn't a notify port,
                    737:  *             if it is dead, or if the caller doesn't hold
                    738:  *             receive rights for it.
                    739:  */
                    740: 
                    741: port_name_t
                    742: task_notify()
                    743: {
                    744:        task_t task = current_task();
                    745:        ipc_port_t notify;
                    746:        mach_port_t name;
                    747: 
                    748:        notify = retrieve_task_notify(task);
                    749:        name = ipc_port_copyout_receiver(notify, task->itk_space);
                    750:        return (port_name_t) name;
                    751: }
                    752: 
                    753: /*
                    754:  *     Routine:        thread_self [mach trap]
                    755:  *     Purpose:
                    756:  *             Give the caller send rights for his own thread port.
                    757:  *             If new, the send right is marked with IE_BITS_COMPAT.
                    758:  *     Conditions:
                    759:  *             Nothing locked.
                    760:  *     Returns:
                    761:  *             MACH_PORT_NULL if there are any resource failures
                    762:  *             or other errors.
                    763:  */
                    764: 
                    765: port_name_t
                    766: thread_self()
                    767: {
                    768:        thread_t thread = current_thread();
                    769:        task_t task = thread->task;
                    770:        ipc_port_t sright;
                    771:        mach_port_t name;
                    772: 
                    773:        sright = retrieve_thread_self_fast(thread);
                    774:        name = ipc_port_copyout_send_compat(sright, task->itk_space);
                    775:        return (port_name_t) name;
                    776: }
                    777: 
                    778: /*
                    779:  *     Routine:        thread_reply [mach trap]
                    780:  *     Purpose:
                    781:  *             Give the caller the name of his own reply port.
                    782:  *     Conditions:
                    783:  *             Nothing locked.
                    784:  *     Returns:
                    785:  *             MACH_PORT_NULL if there isn't a reply port,
                    786:  *             if it is dead, or if the caller doesn't hold
                    787:  *             receive rights for it.
                    788:  */
                    789: 
                    790: port_name_t
                    791: thread_reply()
                    792: {
                    793:        task_t task = current_task();
                    794:        thread_t thread = current_thread();
                    795:        ipc_port_t reply;
                    796:        mach_port_t name;
                    797: 
                    798:        reply = retrieve_thread_reply(thread);
                    799:        name = ipc_port_copyout_receiver(reply, task->itk_space);
                    800:        return (port_name_t) name;
                    801: }
                    802: 
                    803: #endif /* MACH_IPC_COMPAT */
                    804: 
                    805: /*
                    806:  *     Routine:        task_get_special_port [kernel call]
                    807:  *     Purpose:
                    808:  *             Clones a send right for one of the task's
                    809:  *             special ports.
                    810:  *     Conditions:
                    811:  *             Nothing locked.
                    812:  *     Returns:
                    813:  *             KERN_SUCCESS            Extracted a send right.
                    814:  *             KERN_INVALID_ARGUMENT   The task is null.
                    815:  *             KERN_FAILURE            The task/space is dead.
                    816:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    817:  */
                    818: 
                    819: kern_return_t
                    820: task_get_special_port(
                    821:        task_t          task,
                    822:        int             which,
                    823:        ipc_port_t      *portp)
                    824: {
                    825:        ipc_port_t *whichp;
                    826:        ipc_port_t port;
                    827: 
                    828:        if (task == TASK_NULL)
                    829:                return KERN_INVALID_ARGUMENT;
                    830: 
                    831:        switch (which) {
                    832: #if    MACH_IPC_COMPAT
                    833:            case TASK_NOTIFY_PORT: {
                    834:                ipc_space_t space = task->itk_space;
                    835: 
                    836:                is_read_lock(space);
                    837:                if (!space->is_active) {
                    838:                        is_read_unlock(space);
                    839:                        return KERN_FAILURE;
                    840:                }
                    841: 
                    842:                port = ipc_port_copy_send(space->is_notify);
                    843:                is_read_unlock(space);
                    844: 
                    845:                *portp = port;
                    846:                return KERN_SUCCESS;
                    847:            }
                    848: #endif /* MACH_IPC_COMPAT */
                    849: 
                    850:            case TASK_KERNEL_PORT:
                    851:                whichp = &task->itk_sself;
                    852:                break;
                    853: 
                    854:            case TASK_EXCEPTION_PORT:
                    855:                whichp = &task->itk_exception;
                    856:                break;
                    857: 
                    858:            case TASK_BOOTSTRAP_PORT:
                    859:                whichp = &task->itk_bootstrap;
                    860:                break;
                    861: 
                    862:            default:
                    863:                return KERN_INVALID_ARGUMENT;
                    864:        }
                    865: 
                    866:        itk_lock(task);
                    867:        if (task->itk_self == IP_NULL) {
                    868:                itk_unlock(task);
                    869:                return KERN_FAILURE;
                    870:        }
                    871: 
                    872:        port = ipc_port_copy_send(*whichp);
                    873:        itk_unlock(task);
                    874: 
                    875:        *portp = port;
                    876:        return KERN_SUCCESS;
                    877: }
                    878: 
                    879: /*
                    880:  *     Routine:        task_set_special_port [kernel call]
                    881:  *     Purpose:
                    882:  *             Changes one of the task's special ports,
                    883:  *             setting it to the supplied send right.
                    884:  *     Conditions:
                    885:  *             Nothing locked.  If successful, consumes
                    886:  *             the supplied send right.
                    887:  *     Returns:
                    888:  *             KERN_SUCCESS            Changed the special port.
                    889:  *             KERN_INVALID_ARGUMENT   The task is null.
                    890:  *             KERN_FAILURE            The task/space is dead.
                    891:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    892:  */
                    893: 
                    894: kern_return_t
                    895: task_set_special_port(
                    896:        task_t          task,
                    897:        int             which,
                    898:        ipc_port_t      port)
                    899: {
                    900:        ipc_port_t *whichp;
                    901:        ipc_port_t old;
                    902: 
                    903:        if (task == TASK_NULL)
                    904:                return KERN_INVALID_ARGUMENT;
                    905: 
                    906:        switch (which) {
                    907: #if    MACH_IPC_COMPAT
                    908:            case TASK_NOTIFY_PORT: {
                    909:                ipc_space_t space = task->itk_space;
                    910: 
                    911:                is_write_lock(space);
                    912:                if (!space->is_active) {
                    913:                        is_write_unlock(space);
                    914:                        return KERN_FAILURE;
                    915:                }
                    916: 
                    917:                old = space->is_notify;
                    918:                space->is_notify = port;
                    919:                is_write_unlock(space);
                    920: 
                    921:                if (IP_VALID(old))
                    922:                        ipc_port_release_send(old);
                    923:                return KERN_SUCCESS;
                    924:            }
                    925: #endif /* MACH_IPC_COMPAT */
                    926: 
                    927:            case TASK_KERNEL_PORT:
                    928:                whichp = &task->itk_sself;
                    929:                break;
                    930: 
                    931:            case TASK_EXCEPTION_PORT:
                    932:                whichp = &task->itk_exception;
                    933:                break;
                    934: 
                    935:            case TASK_BOOTSTRAP_PORT:
                    936:                whichp = &task->itk_bootstrap;
                    937:                break;
                    938: 
                    939:            default:
                    940:                return KERN_INVALID_ARGUMENT;
                    941:        }
                    942: 
                    943:        itk_lock(task);
                    944:        if (task->itk_self == IP_NULL) {
                    945:                itk_unlock(task);
                    946:                return KERN_FAILURE;
                    947:        }
                    948: 
                    949:        old = *whichp;
                    950:        *whichp = port;
                    951:        itk_unlock(task);
                    952: 
                    953:        if (IP_VALID(old))
                    954:                ipc_port_release_send(old);
                    955:        return KERN_SUCCESS;
                    956: }
                    957: 
                    958: /*
                    959:  *     Routine:        thread_get_special_port [kernel call]
                    960:  *     Purpose:
                    961:  *             Clones a send right for one of the thread's
                    962:  *             special ports.
                    963:  *     Conditions:
                    964:  *             Nothing locked.
                    965:  *     Returns:
                    966:  *             KERN_SUCCESS            Extracted a send right.
                    967:  *             KERN_INVALID_ARGUMENT   The thread is null.
                    968:  *             KERN_FAILURE            The thread is dead.
                    969:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    970:  */
                    971: 
                    972: kern_return_t
                    973: thread_get_special_port(thread, which, portp)
                    974:        thread_t thread;
                    975:        int which;
                    976:        ipc_port_t *portp;
                    977: {
                    978:        ipc_port_t *whichp;
                    979:        ipc_port_t port;
                    980: 
                    981:        if (thread == ITH_NULL)
                    982:                return KERN_INVALID_ARGUMENT;
                    983: 
                    984:        switch (which) {
                    985: #if    MACH_IPC_COMPAT
                    986:            case THREAD_REPLY_PORT:
                    987:                whichp = &thread->ith_reply;
                    988:                break;
                    989: #endif /* MACH_IPC_COMPAT */
                    990: 
                    991:            case THREAD_KERNEL_PORT:
                    992:                whichp = &thread->ith_sself;
                    993:                break;
                    994: 
                    995:            case THREAD_EXCEPTION_PORT:
                    996:                whichp = &thread->ith_exception;
                    997:                break;
                    998: 
                    999:            default:
                   1000:                return KERN_INVALID_ARGUMENT;
                   1001:        }
                   1002: 
                   1003:        ith_lock(thread);
                   1004:        if (thread->ith_self == IP_NULL) {
                   1005:                ith_unlock(thread);
                   1006:                return KERN_FAILURE;
                   1007:        }
                   1008: 
                   1009:        port = ipc_port_copy_send(*whichp);
                   1010:        ith_unlock(thread);
                   1011: 
                   1012:        *portp = port;
                   1013:        return KERN_SUCCESS;
                   1014: }
                   1015: 
                   1016: /*
                   1017:  *     Routine:        thread_set_special_port [kernel call]
                   1018:  *     Purpose:
                   1019:  *             Changes one of the thread's special ports,
                   1020:  *             setting it to the supplied send right.
                   1021:  *     Conditions:
                   1022:  *             Nothing locked.  If successful, consumes
                   1023:  *             the supplied send right.
                   1024:  *     Returns:
                   1025:  *             KERN_SUCCESS            Changed the special port.
                   1026:  *             KERN_INVALID_ARGUMENT   The thread is null.
                   1027:  *             KERN_FAILURE            The thread is dead.
                   1028:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                   1029:  */
                   1030: 
                   1031: kern_return_t
                   1032: thread_set_special_port(thread, which, port)
                   1033:        thread_t thread;
                   1034:        int which;
                   1035:        ipc_port_t port;
                   1036: {
                   1037:        ipc_port_t *whichp;
                   1038:        ipc_port_t old;
                   1039: 
                   1040:        if (thread == ITH_NULL)
                   1041:                return KERN_INVALID_ARGUMENT;
                   1042: 
                   1043:        switch (which) {
                   1044: #if    MACH_IPC_COMPAT
                   1045:            case THREAD_REPLY_PORT:
                   1046:                whichp = &thread->ith_reply;
                   1047:                break;
                   1048: #endif /* MACH_IPC_COMPAT */
                   1049: 
                   1050:            case THREAD_KERNEL_PORT:
                   1051:                whichp = &thread->ith_sself;
                   1052:                break;
                   1053: 
                   1054:            case THREAD_EXCEPTION_PORT:
                   1055:                whichp = &thread->ith_exception;
                   1056:                break;
                   1057: 
                   1058:            default:
                   1059:                return KERN_INVALID_ARGUMENT;
                   1060:        }
                   1061: 
                   1062:        ith_lock(thread);
                   1063:        if (thread->ith_self == IP_NULL) {
                   1064:                ith_unlock(thread);
                   1065:                return KERN_FAILURE;
                   1066:        }
                   1067: 
                   1068:        old = *whichp;
                   1069:        *whichp = port;
                   1070:        ith_unlock(thread);
                   1071: 
                   1072:        if (IP_VALID(old))
                   1073:                ipc_port_release_send(old);
                   1074:        return KERN_SUCCESS;
                   1075: }
                   1076: 
                   1077: /*
                   1078:  *     Routine:        mach_ports_register [kernel call]
                   1079:  *     Purpose:
                   1080:  *             Stash a handful of port send rights in the task.
                   1081:  *             Child tasks will inherit these rights, but they
                   1082:  *             must use mach_ports_lookup to acquire them.
                   1083:  *
                   1084:  *             The rights are supplied in a (wired) kalloc'd segment.
                   1085:  *             Rights which aren't supplied are assumed to be null.
                   1086:  *     Conditions:
                   1087:  *             Nothing locked.  If successful, consumes
                   1088:  *             the supplied rights and memory.
                   1089:  *     Returns:
                   1090:  *             KERN_SUCCESS            Stashed the port rights.
                   1091:  *             KERN_INVALID_ARGUMENT   The task is null.
                   1092:  *             KERN_INVALID_ARGUMENT   The task is dead.
                   1093:  *             KERN_INVALID_ARGUMENT   Too many port rights supplied.
                   1094:  */
                   1095: 
                   1096: kern_return_t
                   1097: mach_ports_register(
                   1098:        task_t                  task,
                   1099:        mach_port_array_t       memory,
                   1100:        mach_msg_type_number_t  portsCnt)
                   1101: {
                   1102:        ipc_port_t ports[TASK_PORT_REGISTER_MAX];
                   1103:        int i;
                   1104: 
                   1105:        if ((task == TASK_NULL) ||
                   1106:            (portsCnt > TASK_PORT_REGISTER_MAX))
                   1107:                return KERN_INVALID_ARGUMENT;
                   1108: 
                   1109:        /*
                   1110:         *      Pad the port rights with nulls.
                   1111:         */
                   1112: 
                   1113:        for (i = 0; i < portsCnt; i++)
                   1114:                ports[i] = (ipc_port_t) memory[i];
                   1115:        for (; i < TASK_PORT_REGISTER_MAX; i++)
                   1116:                ports[i] = IP_NULL;
                   1117: 
                   1118:        itk_lock(task);
                   1119:        if (task->itk_self == IP_NULL) {
                   1120:                itk_unlock(task);
                   1121:                return KERN_INVALID_ARGUMENT;
                   1122:        }
                   1123: 
                   1124:        /*
                   1125:         *      Replace the old send rights with the new.
                   1126:         *      Release the old rights after unlocking.
                   1127:         */
                   1128: 
                   1129:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) {
                   1130:                ipc_port_t old;
                   1131: 
                   1132:                old = task->itk_registered[i];
                   1133:                task->itk_registered[i] = ports[i];
                   1134:                ports[i] = old;
                   1135:        }
                   1136: 
                   1137:        itk_unlock(task);
                   1138: 
                   1139:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                   1140:                if (IP_VALID(ports[i]))
                   1141:                        ipc_port_release_send(ports[i]);
                   1142: 
                   1143:        /*
                   1144:         *      Now that the operation is known to be successful,
                   1145:         *      we can free the memory.
                   1146:         */
                   1147: 
                   1148:        if (portsCnt != 0)
                   1149:                kfree((vm_offset_t) memory,
                   1150:                      (vm_size_t) (portsCnt * sizeof(mach_port_t)));
                   1151: 
                   1152:        return KERN_SUCCESS;
                   1153: }
                   1154: 
                   1155: /*
                   1156:  *     Routine:        mach_ports_lookup [kernel call]
                   1157:  *     Purpose:
                   1158:  *             Retrieves (clones) the stashed port send rights.
                   1159:  *     Conditions:
                   1160:  *             Nothing locked.  If successful, the caller gets
                   1161:  *             rights and memory.
                   1162:  *     Returns:
                   1163:  *             KERN_SUCCESS            Retrieved the send rights.
                   1164:  *             KERN_INVALID_ARGUMENT   The task is null.
                   1165:  *             KERN_INVALID_ARGUMENT   The task is dead.
                   1166:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                   1167:  */
                   1168: 
                   1169: kern_return_t
                   1170: mach_ports_lookup(task, portsp, portsCnt)
                   1171:        task_t task;
                   1172:        ipc_port_t **portsp;
                   1173:        mach_msg_type_number_t *portsCnt;
                   1174: {
                   1175:        vm_offset_t memory;
                   1176:        vm_size_t size;
                   1177:        ipc_port_t *ports;
                   1178:        int i;
                   1179: 
                   1180:        if (task == TASK_NULL)
                   1181:                return KERN_INVALID_ARGUMENT;
                   1182: 
                   1183:        size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t));
                   1184: 
                   1185:        memory = kalloc(size);
                   1186:        if (memory == 0)
                   1187:                return KERN_RESOURCE_SHORTAGE;
                   1188: 
                   1189:        itk_lock(task);
                   1190:        if (task->itk_self == IP_NULL) {
                   1191:                itk_unlock(task);
                   1192: 
                   1193:                kfree(memory, size);
                   1194:                return KERN_INVALID_ARGUMENT;
                   1195:        }
                   1196: 
                   1197:        ports = (ipc_port_t *) memory;
                   1198: 
                   1199:        /*
                   1200:         *      Clone port rights.  Because kalloc'd memory
                   1201:         *      is wired, we won't fault while holding the task lock.
                   1202:         */
                   1203: 
                   1204:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                   1205:                ports[i] = ipc_port_copy_send(task->itk_registered[i]);
                   1206: 
                   1207:        itk_unlock(task);
                   1208: 
                   1209:        *portsp = ports;
                   1210:        *portsCnt = TASK_PORT_REGISTER_MAX;
                   1211:        return KERN_SUCCESS;
                   1212: }
                   1213: 
                   1214: /*
                   1215:  *     Routine:        convert_port_to_task
                   1216:  *     Purpose:
                   1217:  *             Convert from a port to a task.
                   1218:  *             Doesn't consume the port ref; produces a task ref,
                   1219:  *             which may be null.
                   1220:  *     Conditions:
                   1221:  *             Nothing locked.
                   1222:  */
                   1223: 
                   1224: task_t
                   1225: convert_port_to_task(
                   1226:        ipc_port_t      port)
                   1227: {
                   1228:        task_t task = TASK_NULL;
                   1229: 
                   1230:        if (IP_VALID(port)) {
                   1231:                ip_lock(port);
                   1232:                if (ip_active(port) &&
                   1233:                    (ip_kotype(port) == IKOT_TASK)) {
                   1234:                        task = (task_t) port->ip_kobject;
                   1235:                        task_reference(task);
                   1236:                }
                   1237:                ip_unlock(port);
                   1238:        }
                   1239: 
                   1240:        return task;
                   1241: }
                   1242: 
                   1243: /*
                   1244:  *     Routine:        convert_port_to_space
                   1245:  *     Purpose:
                   1246:  *             Convert from a port to a space.
                   1247:  *             Doesn't consume the port ref; produces a space ref,
                   1248:  *             which may be null.
                   1249:  *     Conditions:
                   1250:  *             Nothing locked.
                   1251:  */
                   1252: 
                   1253: ipc_space_t
                   1254: convert_port_to_space(
                   1255:        ipc_port_t      port)
                   1256: {
                   1257:        ipc_space_t space = IS_NULL;
                   1258: 
                   1259:        if (IP_VALID(port)) {
                   1260:                ip_lock(port);
                   1261:                if (ip_active(port) &&
                   1262:                    (ip_kotype(port) == IKOT_TASK)) {
                   1263:                        space = ((task_t) port->ip_kobject)->itk_space;
                   1264:                        is_reference(space);
                   1265:                }
                   1266:                ip_unlock(port);
                   1267:        }
                   1268: 
                   1269:        return space;
                   1270: }
                   1271: 
                   1272: /*
                   1273:  *     Routine:        convert_port_to_map
                   1274:  *     Purpose:
                   1275:  *             Convert from a port to a map.
                   1276:  *             Doesn't consume the port ref; produces a map ref,
                   1277:  *             which may be null.
                   1278:  *     Conditions:
                   1279:  *             Nothing locked.
                   1280:  */
                   1281: 
                   1282: vm_map_t
                   1283: convert_port_to_map(port)
                   1284:        ipc_port_t port;
                   1285: {
                   1286:        vm_map_t map = VM_MAP_NULL;
                   1287: 
                   1288:        if (IP_VALID(port)) {
                   1289:                ip_lock(port);
                   1290:                if (ip_active(port) &&
                   1291:                    (ip_kotype(port) == IKOT_TASK)) {
                   1292:                        map = ((task_t) port->ip_kobject)->map;
                   1293:                        vm_map_reference(map);
                   1294:                }
                   1295:                ip_unlock(port);
                   1296:        }
                   1297: 
                   1298:        return map;
                   1299: }
                   1300: 
                   1301: /*
                   1302:  *     Routine:        convert_port_to_thread
                   1303:  *     Purpose:
                   1304:  *             Convert from a port to a thread.
                   1305:  *             Doesn't consume the port ref; produces a thread ref,
                   1306:  *             which may be null.
                   1307:  *     Conditions:
                   1308:  *             Nothing locked.
                   1309:  */
                   1310: 
                   1311: thread_t
                   1312: convert_port_to_thread(port)
                   1313:        ipc_port_t port;
                   1314: {
                   1315:        thread_t thread = THREAD_NULL;
                   1316: 
                   1317:        if (IP_VALID(port)) {
                   1318:                ip_lock(port);
                   1319:                if (ip_active(port) &&
                   1320:                    (ip_kotype(port) == IKOT_THREAD)) {
                   1321:                        thread = (thread_t) port->ip_kobject;
                   1322:                        thread_reference(thread);
                   1323:                }
                   1324:                ip_unlock(port);
                   1325:        }
                   1326: 
                   1327:        return thread;
                   1328: }
                   1329: 
                   1330: /*
                   1331:  *     Routine:        convert_task_to_port
                   1332:  *     Purpose:
                   1333:  *             Convert from a task to a port.
                   1334:  *             Consumes a task ref; produces a naked send right
                   1335:  *             which may be invalid.
                   1336:  *     Conditions:
                   1337:  *             Nothing locked.
                   1338:  */
                   1339: 
                   1340: ipc_port_t
                   1341: convert_task_to_port(task)
                   1342:        task_t task;
                   1343: {
                   1344:        ipc_port_t port;
                   1345: 
                   1346:        itk_lock(task);
                   1347:        if (task->itk_self != IP_NULL)
                   1348:                port = ipc_port_make_send(task->itk_self);
                   1349:        else
                   1350:                port = IP_NULL;
                   1351:        itk_unlock(task);
                   1352: 
                   1353:        task_deallocate(task);
                   1354:        return port;
                   1355: }
                   1356: 
                   1357: /*
                   1358:  *     Routine:        convert_thread_to_port
                   1359:  *     Purpose:
                   1360:  *             Convert from a thread to a port.
                   1361:  *             Consumes a thread ref; produces a naked send right
                   1362:  *             which may be invalid.
                   1363:  *     Conditions:
                   1364:  *             Nothing locked.
                   1365:  */
                   1366: 
                   1367: ipc_port_t
                   1368: convert_thread_to_port(thread)
                   1369:        thread_t thread;
                   1370: {
                   1371:        ipc_port_t port;
                   1372: 
                   1373:        ith_lock(thread);
                   1374:        if (thread->ith_self != IP_NULL)
                   1375:                port = ipc_port_make_send(thread->ith_self);
                   1376:        else
                   1377:                port = IP_NULL;
                   1378:        ith_unlock(thread);
                   1379: 
                   1380:        thread_deallocate(thread);
                   1381:        return port;
                   1382: }
                   1383: 
                   1384: /*
                   1385:  *     Routine:        space_deallocate
                   1386:  *     Purpose:
                   1387:  *             Deallocate a space ref produced by convert_port_to_space.
                   1388:  *     Conditions:
                   1389:  *             Nothing locked.
                   1390:  */
                   1391: 
                   1392: void
                   1393: space_deallocate(space)
                   1394:        ipc_space_t space;
                   1395: {
                   1396:        if (space != IS_NULL)
                   1397:                is_release(space);
                   1398: }

unix.superglobalmegacorp.com

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