Annotation of OSKit-Mach/kern/ipc_tt.c, revision 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.