Annotation of Gnu-Mach/kern/ipc_tt.c, revision 1.1.1.4

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        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.
1.1.1.2   root       11:  *
1.1       root       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.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       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/boolean.h>
                     33: #include <mach/kern_return.h>
                     34: #include <mach/mach_param.h>
                     35: #include <mach/task_special_ports.h>
                     36: #include <mach/thread_special_ports.h>
                     37: #include <vm/vm_kern.h>
1.1.1.4 ! root       38: #include <kern/debug.h>
        !            39: #include <kern/kalloc.h>
1.1       root       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: 
                    237: /*
                    238:  *     Routine:        ipc_thread_enable
                    239:  *     Purpose:
                    240:  *             Enable a thread for IPC access.
                    241:  *     Conditions:
                    242:  *             Nothing locked.
                    243:  */
                    244: 
                    245: void
                    246: ipc_thread_enable(thread)
                    247:        thread_t thread;
                    248: {
                    249:        ipc_port_t kport;
                    250: 
                    251:        ith_lock(thread);
                    252:        kport = thread->ith_self;
                    253:        if (kport != IP_NULL)
                    254:                ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD);
                    255:        ith_unlock(thread);
                    256: }
                    257: 
                    258: /*
                    259:  *     Routine:        ipc_thread_disable
                    260:  *     Purpose:
                    261:  *             Disable IPC access to a thread.
                    262:  *     Conditions:
                    263:  *             Nothing locked.
                    264:  */
                    265: 
                    266: void
                    267: ipc_thread_disable(thread)
                    268:        thread_t thread;
                    269: {
                    270:        ipc_port_t kport;
                    271: 
                    272:        ith_lock(thread);
                    273:        kport = thread->ith_self;
                    274:        if (kport != IP_NULL)
                    275:                ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
                    276:        ith_unlock(thread);
                    277: }
                    278: 
                    279: /*
                    280:  *     Routine:        ipc_thread_terminate
                    281:  *     Purpose:
                    282:  *             Clean up and destroy a thread's IPC state.
                    283:  *     Conditions:
                    284:  *             Nothing locked.  The thread must be suspended.
                    285:  *             (Or be the current thread.)
                    286:  */
                    287: 
                    288: void
                    289: ipc_thread_terminate(thread)
                    290:        thread_t thread;
                    291: {
                    292:        ipc_port_t kport;
                    293: 
                    294:        ith_lock(thread);
                    295:        kport = thread->ith_self;
                    296: 
                    297:        if (kport == IP_NULL) {
                    298:                /* the thread is already terminated (can this happen?) */
                    299:                ith_unlock(thread);
                    300:                return;
                    301:        }
                    302: 
                    303:        thread->ith_self = IP_NULL;
                    304:        ith_unlock(thread);
                    305: 
                    306:        assert(ipc_kmsg_queue_empty(&thread->ith_messages));
                    307: 
                    308:        /* release the naked send rights */
                    309: 
                    310:        if (IP_VALID(thread->ith_sself))
                    311:                ipc_port_release_send(thread->ith_sself);
                    312:        if (IP_VALID(thread->ith_exception))
                    313:                ipc_port_release_send(thread->ith_exception);
                    314: 
                    315:        /* destroy the kernel port */
                    316: 
                    317:        ipc_port_dealloc_kernel(kport);
                    318: }
                    319: 
                    320: #if    0
                    321: /*
                    322:  *     Routine:        retrieve_task_self
                    323:  *     Purpose:
                    324:  *             Return a send right (possibly null/dead)
                    325:  *             for the task's user-visible self port.
                    326:  *     Conditions:
                    327:  *             Nothing locked.
                    328:  */
                    329: 
                    330: ipc_port_t
                    331: retrieve_task_self(task)
                    332:        task_t task;
                    333: {
                    334:        ipc_port_t port;
                    335: 
                    336:        assert(task != TASK_NULL);
                    337: 
                    338:        itk_lock(task);
                    339:        if (task->itk_self != IP_NULL)
                    340:                port = ipc_port_copy_send(task->itk_sself);
                    341:        else
                    342:                port = IP_NULL;
                    343:        itk_unlock(task);
                    344: 
                    345:        return port;
                    346: }
                    347: 
                    348: /*
                    349:  *     Routine:        retrieve_thread_self
                    350:  *     Purpose:
                    351:  *             Return a send right (possibly null/dead)
                    352:  *             for the thread's user-visible self port.
                    353:  *     Conditions:
                    354:  *             Nothing locked.
                    355:  */
                    356: 
                    357: ipc_port_t
                    358: retrieve_thread_self(thread)
                    359:        thread_t thread;
                    360: {
                    361:        ipc_port_t port;
                    362: 
                    363:        assert(thread != ITH_NULL);
                    364: 
                    365:        ith_lock(thread);
                    366:        if (thread->ith_self != IP_NULL)
                    367:                port = ipc_port_copy_send(thread->ith_sself);
                    368:        else
                    369:                port = IP_NULL;
                    370:        ith_unlock(thread);
                    371: 
                    372:        return port;
                    373: }
1.1.1.3   root      374: #endif /* 0 */
1.1       root      375: 
                    376: /*
                    377:  *     Routine:        retrieve_task_self_fast
                    378:  *     Purpose:
                    379:  *             Optimized version of retrieve_task_self,
                    380:  *             that only works for the current task.
                    381:  *
                    382:  *             Return a send right (possibly null/dead)
                    383:  *             for the task's user-visible self port.
                    384:  *     Conditions:
                    385:  *             Nothing locked.
                    386:  */
                    387: 
                    388: ipc_port_t
                    389: retrieve_task_self_fast(
                    390:        register task_t         task)
                    391: {
                    392:        register ipc_port_t port;
                    393: 
                    394:        assert(task == current_task());
                    395: 
                    396:        itk_lock(task);
                    397:        assert(task->itk_self != IP_NULL);
                    398: 
                    399:        if ((port = task->itk_sself) == task->itk_self) {
                    400:                /* no interposing */
                    401: 
                    402:                ip_lock(port);
                    403:                assert(ip_active(port));
                    404:                ip_reference(port);
                    405:                port->ip_srights++;
                    406:                ip_unlock(port);
                    407:        } else
                    408:                port = ipc_port_copy_send(port);
                    409:        itk_unlock(task);
                    410: 
                    411:        return port;
                    412: }
                    413: 
                    414: /*
                    415:  *     Routine:        retrieve_thread_self_fast
                    416:  *     Purpose:
                    417:  *             Optimized version of retrieve_thread_self,
                    418:  *             that only works for the current thread.
                    419:  *
                    420:  *             Return a send right (possibly null/dead)
                    421:  *             for the thread's user-visible self port.
                    422:  *     Conditions:
                    423:  *             Nothing locked.
                    424:  */
                    425: 
                    426: ipc_port_t
                    427: retrieve_thread_self_fast(thread)
                    428:        register thread_t thread;
                    429: {
                    430:        register ipc_port_t port;
                    431: 
                    432:        assert(thread == current_thread());
                    433: 
                    434:        ith_lock(thread);
                    435:        assert(thread->ith_self != IP_NULL);
                    436: 
                    437:        if ((port = thread->ith_sself) == thread->ith_self) {
                    438:                /* no interposing */
                    439: 
                    440:                ip_lock(port);
                    441:                assert(ip_active(port));
                    442:                ip_reference(port);
                    443:                port->ip_srights++;
                    444:                ip_unlock(port);
                    445:        } else
                    446:                port = ipc_port_copy_send(port);
                    447:        ith_unlock(thread);
                    448: 
                    449:        return port;
                    450: }
                    451: 
                    452: #if    0
                    453: /*
                    454:  *     Routine:        retrieve_task_exception
                    455:  *     Purpose:
                    456:  *             Return a send right (possibly null/dead)
                    457:  *             for the task's exception port.
                    458:  *     Conditions:
                    459:  *             Nothing locked.
                    460:  */
                    461: 
                    462: ipc_port_t
                    463: retrieve_task_exception(task)
                    464:        task_t task;
                    465: {
                    466:        ipc_port_t port;
                    467: 
                    468:        assert(task != TASK_NULL);
                    469: 
                    470:        itk_lock(task);
                    471:        if (task->itk_self != IP_NULL)
                    472:                port = ipc_port_copy_send(task->itk_exception);
                    473:        else
                    474:                port = IP_NULL;
                    475:        itk_unlock(task);
                    476: 
                    477:        return port;
                    478: }
                    479: 
                    480: /*
                    481:  *     Routine:        retrieve_thread_exception
                    482:  *     Purpose:
                    483:  *             Return a send right (possibly null/dead)
                    484:  *             for the thread's exception port.
                    485:  *     Conditions:
                    486:  *             Nothing locked.
                    487:  */
                    488: 
                    489: ipc_port_t
                    490: retrieve_thread_exception(thread)
                    491:        thread_t thread;
                    492: {
                    493:        ipc_port_t port;
                    494: 
                    495:        assert(thread != ITH_NULL);
                    496: 
                    497:        ith_lock(thread);
                    498:        if (thread->ith_self != IP_NULL)
                    499:                port = ipc_port_copy_send(thread->ith_exception);
                    500:        else
                    501:                port = IP_NULL;
                    502:        ith_unlock(thread);
                    503: 
                    504:        return port;
                    505: }
1.1.1.3   root      506: #endif /* 0 */
1.1       root      507: 
                    508: /*
                    509:  *     Routine:        mach_task_self [mach trap]
                    510:  *     Purpose:
                    511:  *             Give the caller send rights for his own task port.
                    512:  *     Conditions:
                    513:  *             Nothing locked.
                    514:  *     Returns:
                    515:  *             MACH_PORT_NULL if there are any resource failures
                    516:  *             or other errors.
                    517:  */
                    518: 
                    519: mach_port_t
                    520: mach_task_self(void)
                    521: {
                    522:        task_t task = current_task();
                    523:        ipc_port_t sright;
                    524: 
                    525:        sright = retrieve_task_self_fast(task);
                    526:        return ipc_port_copyout_send(sright, task->itk_space);
                    527: }
                    528: 
                    529: /*
                    530:  *     Routine:        mach_thread_self [mach trap]
                    531:  *     Purpose:
                    532:  *             Give the caller send rights for his own thread port.
                    533:  *     Conditions:
                    534:  *             Nothing locked.
                    535:  *     Returns:
                    536:  *             MACH_PORT_NULL if there are any resource failures
                    537:  *             or other errors.
                    538:  */
                    539: 
                    540: mach_port_t
1.1.1.4 ! root      541: mach_thread_self(void)
1.1       root      542: {
                    543:        thread_t thread = current_thread();
                    544:        task_t task = thread->task;
                    545:        ipc_port_t sright;
                    546: 
                    547:        sright = retrieve_thread_self_fast(thread);
                    548:        return ipc_port_copyout_send(sright, task->itk_space);
                    549: }
                    550: 
                    551: /*
                    552:  *     Routine:        mach_reply_port [mach trap]
                    553:  *     Purpose:
                    554:  *             Allocate a port for the caller.
                    555:  *     Conditions:
                    556:  *             Nothing locked.
                    557:  *     Returns:
                    558:  *             MACH_PORT_NULL if there are any resource failures
                    559:  *             or other errors.
                    560:  */
                    561: 
                    562: mach_port_t
                    563: mach_reply_port(void)
                    564: {
                    565:        ipc_port_t port;
                    566:        mach_port_t name;
                    567:        kern_return_t kr;
                    568: 
                    569:        kr = ipc_port_alloc(current_task()->itk_space, &name, &port);
                    570:        if (kr == KERN_SUCCESS)
                    571:                ip_unlock(port);
                    572:        else
                    573:                name = MACH_PORT_NULL;
                    574: 
                    575:        return name;
                    576: }
                    577: 
                    578: /*
                    579:  *     Routine:        task_get_special_port [kernel call]
                    580:  *     Purpose:
                    581:  *             Clones a send right for one of the task's
                    582:  *             special ports.
                    583:  *     Conditions:
                    584:  *             Nothing locked.
                    585:  *     Returns:
                    586:  *             KERN_SUCCESS            Extracted a send right.
                    587:  *             KERN_INVALID_ARGUMENT   The task is null.
                    588:  *             KERN_FAILURE            The task/space is dead.
                    589:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    590:  */
                    591: 
                    592: kern_return_t
                    593: task_get_special_port(
                    594:        task_t          task,
                    595:        int             which,
                    596:        ipc_port_t      *portp)
                    597: {
                    598:        ipc_port_t *whichp;
                    599:        ipc_port_t port;
                    600: 
                    601:        if (task == TASK_NULL)
                    602:                return KERN_INVALID_ARGUMENT;
                    603: 
                    604:        switch (which) {
                    605:            case TASK_KERNEL_PORT:
                    606:                whichp = &task->itk_sself;
                    607:                break;
                    608: 
                    609:            case TASK_EXCEPTION_PORT:
                    610:                whichp = &task->itk_exception;
                    611:                break;
                    612: 
                    613:            case TASK_BOOTSTRAP_PORT:
                    614:                whichp = &task->itk_bootstrap;
                    615:                break;
                    616: 
                    617:            default:
                    618:                return KERN_INVALID_ARGUMENT;
                    619:        }
                    620: 
                    621:        itk_lock(task);
                    622:        if (task->itk_self == IP_NULL) {
                    623:                itk_unlock(task);
                    624:                return KERN_FAILURE;
                    625:        }
                    626: 
                    627:        port = ipc_port_copy_send(*whichp);
                    628:        itk_unlock(task);
                    629: 
                    630:        *portp = port;
                    631:        return KERN_SUCCESS;
                    632: }
                    633: 
                    634: /*
                    635:  *     Routine:        task_set_special_port [kernel call]
                    636:  *     Purpose:
                    637:  *             Changes one of the task's special ports,
                    638:  *             setting it to the supplied send right.
                    639:  *     Conditions:
                    640:  *             Nothing locked.  If successful, consumes
                    641:  *             the supplied send right.
                    642:  *     Returns:
                    643:  *             KERN_SUCCESS            Changed the special port.
                    644:  *             KERN_INVALID_ARGUMENT   The task is null.
                    645:  *             KERN_FAILURE            The task/space is dead.
                    646:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    647:  */
                    648: 
                    649: kern_return_t
                    650: task_set_special_port(
                    651:        task_t          task,
                    652:        int             which,
                    653:        ipc_port_t      port)
                    654: {
                    655:        ipc_port_t *whichp;
                    656:        ipc_port_t old;
                    657: 
                    658:        if (task == TASK_NULL)
                    659:                return KERN_INVALID_ARGUMENT;
                    660: 
                    661:        switch (which) {
                    662:            case TASK_KERNEL_PORT:
                    663:                whichp = &task->itk_sself;
                    664:                break;
                    665: 
                    666:            case TASK_EXCEPTION_PORT:
                    667:                whichp = &task->itk_exception;
                    668:                break;
                    669: 
                    670:            case TASK_BOOTSTRAP_PORT:
                    671:                whichp = &task->itk_bootstrap;
                    672:                break;
                    673: 
                    674:            default:
                    675:                return KERN_INVALID_ARGUMENT;
                    676:        }
                    677: 
                    678:        itk_lock(task);
                    679:        if (task->itk_self == IP_NULL) {
                    680:                itk_unlock(task);
                    681:                return KERN_FAILURE;
                    682:        }
                    683: 
                    684:        old = *whichp;
                    685:        *whichp = port;
                    686:        itk_unlock(task);
                    687: 
                    688:        if (IP_VALID(old))
                    689:                ipc_port_release_send(old);
                    690:        return KERN_SUCCESS;
                    691: }
                    692: 
                    693: /*
                    694:  *     Routine:        thread_get_special_port [kernel call]
                    695:  *     Purpose:
                    696:  *             Clones a send right for one of the thread's
                    697:  *             special ports.
                    698:  *     Conditions:
                    699:  *             Nothing locked.
                    700:  *     Returns:
                    701:  *             KERN_SUCCESS            Extracted a send right.
                    702:  *             KERN_INVALID_ARGUMENT   The thread is null.
                    703:  *             KERN_FAILURE            The thread is dead.
                    704:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    705:  */
                    706: 
                    707: kern_return_t
                    708: thread_get_special_port(thread, which, portp)
                    709:        thread_t thread;
                    710:        int which;
                    711:        ipc_port_t *portp;
                    712: {
                    713:        ipc_port_t *whichp;
                    714:        ipc_port_t port;
                    715: 
                    716:        if (thread == ITH_NULL)
                    717:                return KERN_INVALID_ARGUMENT;
                    718: 
                    719:        switch (which) {
                    720:            case THREAD_KERNEL_PORT:
                    721:                whichp = &thread->ith_sself;
                    722:                break;
                    723: 
                    724:            case THREAD_EXCEPTION_PORT:
                    725:                whichp = &thread->ith_exception;
                    726:                break;
                    727: 
                    728:            default:
                    729:                return KERN_INVALID_ARGUMENT;
                    730:        }
                    731: 
                    732:        ith_lock(thread);
                    733:        if (thread->ith_self == IP_NULL) {
                    734:                ith_unlock(thread);
                    735:                return KERN_FAILURE;
                    736:        }
                    737: 
                    738:        port = ipc_port_copy_send(*whichp);
                    739:        ith_unlock(thread);
                    740: 
                    741:        *portp = port;
                    742:        return KERN_SUCCESS;
                    743: }
                    744: 
                    745: /*
                    746:  *     Routine:        thread_set_special_port [kernel call]
                    747:  *     Purpose:
                    748:  *             Changes one of the thread's special ports,
                    749:  *             setting it to the supplied send right.
                    750:  *     Conditions:
                    751:  *             Nothing locked.  If successful, consumes
                    752:  *             the supplied send right.
                    753:  *     Returns:
                    754:  *             KERN_SUCCESS            Changed the special port.
                    755:  *             KERN_INVALID_ARGUMENT   The thread is null.
                    756:  *             KERN_FAILURE            The thread is dead.
                    757:  *             KERN_INVALID_ARGUMENT   Invalid special port.
                    758:  */
                    759: 
                    760: kern_return_t
                    761: thread_set_special_port(thread, which, port)
                    762:        thread_t thread;
                    763:        int which;
                    764:        ipc_port_t port;
                    765: {
                    766:        ipc_port_t *whichp;
                    767:        ipc_port_t old;
                    768: 
                    769:        if (thread == ITH_NULL)
                    770:                return KERN_INVALID_ARGUMENT;
                    771: 
                    772:        switch (which) {
                    773:            case THREAD_KERNEL_PORT:
                    774:                whichp = &thread->ith_sself;
                    775:                break;
                    776: 
                    777:            case THREAD_EXCEPTION_PORT:
                    778:                whichp = &thread->ith_exception;
                    779:                break;
                    780: 
                    781:            default:
                    782:                return KERN_INVALID_ARGUMENT;
                    783:        }
                    784: 
                    785:        ith_lock(thread);
                    786:        if (thread->ith_self == IP_NULL) {
                    787:                ith_unlock(thread);
                    788:                return KERN_FAILURE;
                    789:        }
                    790: 
                    791:        old = *whichp;
                    792:        *whichp = port;
                    793:        ith_unlock(thread);
                    794: 
                    795:        if (IP_VALID(old))
                    796:                ipc_port_release_send(old);
                    797:        return KERN_SUCCESS;
                    798: }
                    799: 
                    800: /*
                    801:  *     Routine:        mach_ports_register [kernel call]
                    802:  *     Purpose:
                    803:  *             Stash a handful of port send rights in the task.
                    804:  *             Child tasks will inherit these rights, but they
                    805:  *             must use mach_ports_lookup to acquire them.
                    806:  *
                    807:  *             The rights are supplied in a (wired) kalloc'd segment.
                    808:  *             Rights which aren't supplied are assumed to be null.
                    809:  *     Conditions:
                    810:  *             Nothing locked.  If successful, consumes
                    811:  *             the supplied rights and memory.
                    812:  *     Returns:
                    813:  *             KERN_SUCCESS            Stashed the port rights.
                    814:  *             KERN_INVALID_ARGUMENT   The task is null.
                    815:  *             KERN_INVALID_ARGUMENT   The task is dead.
                    816:  *             KERN_INVALID_ARGUMENT   Too many port rights supplied.
                    817:  */
                    818: 
                    819: kern_return_t
                    820: mach_ports_register(
                    821:        task_t                  task,
                    822:        mach_port_array_t       memory,
                    823:        mach_msg_type_number_t  portsCnt)
                    824: {
                    825:        ipc_port_t ports[TASK_PORT_REGISTER_MAX];
                    826:        int i;
                    827: 
                    828:        if ((task == TASK_NULL) ||
                    829:            (portsCnt > TASK_PORT_REGISTER_MAX))
                    830:                return KERN_INVALID_ARGUMENT;
                    831: 
                    832:        /*
                    833:         *      Pad the port rights with nulls.
                    834:         */
                    835: 
                    836:        for (i = 0; i < portsCnt; i++)
1.1.1.4 ! root      837:                ports[i] = (ipc_port_t)memory[i];
1.1       root      838:        for (; i < TASK_PORT_REGISTER_MAX; i++)
                    839:                ports[i] = IP_NULL;
                    840: 
                    841:        itk_lock(task);
                    842:        if (task->itk_self == IP_NULL) {
                    843:                itk_unlock(task);
                    844:                return KERN_INVALID_ARGUMENT;
                    845:        }
                    846: 
                    847:        /*
                    848:         *      Replace the old send rights with the new.
                    849:         *      Release the old rights after unlocking.
                    850:         */
                    851: 
                    852:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) {
                    853:                ipc_port_t old;
                    854: 
                    855:                old = task->itk_registered[i];
                    856:                task->itk_registered[i] = ports[i];
                    857:                ports[i] = old;
                    858:        }
                    859: 
                    860:        itk_unlock(task);
                    861: 
                    862:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                    863:                if (IP_VALID(ports[i]))
                    864:                        ipc_port_release_send(ports[i]);
                    865: 
                    866:        /*
                    867:         *      Now that the operation is known to be successful,
                    868:         *      we can free the memory.
                    869:         */
                    870: 
                    871:        if (portsCnt != 0)
                    872:                kfree((vm_offset_t) memory,
                    873:                      (vm_size_t) (portsCnt * sizeof(mach_port_t)));
                    874: 
                    875:        return KERN_SUCCESS;
                    876: }
                    877: 
                    878: /*
                    879:  *     Routine:        mach_ports_lookup [kernel call]
                    880:  *     Purpose:
                    881:  *             Retrieves (clones) the stashed port send rights.
                    882:  *     Conditions:
                    883:  *             Nothing locked.  If successful, the caller gets
                    884:  *             rights and memory.
                    885:  *     Returns:
                    886:  *             KERN_SUCCESS            Retrieved the send rights.
                    887:  *             KERN_INVALID_ARGUMENT   The task is null.
                    888:  *             KERN_INVALID_ARGUMENT   The task is dead.
                    889:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    890:  */
                    891: 
                    892: kern_return_t
                    893: mach_ports_lookup(task, portsp, portsCnt)
                    894:        task_t task;
                    895:        ipc_port_t **portsp;
                    896:        mach_msg_type_number_t *portsCnt;
                    897: {
                    898:        vm_offset_t memory;
                    899:        vm_size_t size;
                    900:        ipc_port_t *ports;
                    901:        int i;
                    902: 
                    903:        if (task == TASK_NULL)
                    904:                return KERN_INVALID_ARGUMENT;
                    905: 
                    906:        size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t));
                    907: 
                    908:        memory = kalloc(size);
                    909:        if (memory == 0)
                    910:                return KERN_RESOURCE_SHORTAGE;
                    911: 
                    912:        itk_lock(task);
                    913:        if (task->itk_self == IP_NULL) {
                    914:                itk_unlock(task);
                    915: 
                    916:                kfree(memory, size);
                    917:                return KERN_INVALID_ARGUMENT;
                    918:        }
                    919: 
                    920:        ports = (ipc_port_t *) memory;
                    921: 
                    922:        /*
                    923:         *      Clone port rights.  Because kalloc'd memory
                    924:         *      is wired, we won't fault while holding the task lock.
                    925:         */
                    926: 
                    927:        for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
                    928:                ports[i] = ipc_port_copy_send(task->itk_registered[i]);
                    929: 
                    930:        itk_unlock(task);
                    931: 
1.1.1.2   root      932:        *portsp = ports;
1.1       root      933:        *portsCnt = TASK_PORT_REGISTER_MAX;
                    934:        return KERN_SUCCESS;
                    935: }
                    936: 
                    937: /*
                    938:  *     Routine:        convert_port_to_task
                    939:  *     Purpose:
                    940:  *             Convert from a port to a task.
                    941:  *             Doesn't consume the port ref; produces a task ref,
                    942:  *             which may be null.
                    943:  *     Conditions:
                    944:  *             Nothing locked.
                    945:  */
                    946: 
                    947: task_t
                    948: convert_port_to_task(
                    949:        ipc_port_t      port)
                    950: {
                    951:        task_t task = TASK_NULL;
                    952: 
                    953:        if (IP_VALID(port)) {
                    954:                ip_lock(port);
                    955:                if (ip_active(port) &&
                    956:                    (ip_kotype(port) == IKOT_TASK)) {
                    957:                        task = (task_t) port->ip_kobject;
                    958:                        task_reference(task);
                    959:                }
                    960:                ip_unlock(port);
                    961:        }
                    962: 
                    963:        return task;
                    964: }
                    965: 
                    966: /*
                    967:  *     Routine:        convert_port_to_space
                    968:  *     Purpose:
                    969:  *             Convert from a port to a space.
                    970:  *             Doesn't consume the port ref; produces a space ref,
                    971:  *             which may be null.
                    972:  *     Conditions:
                    973:  *             Nothing locked.
                    974:  */
                    975: 
                    976: ipc_space_t
                    977: convert_port_to_space(
                    978:        ipc_port_t      port)
                    979: {
                    980:        ipc_space_t space = IS_NULL;
                    981: 
                    982:        if (IP_VALID(port)) {
                    983:                ip_lock(port);
                    984:                if (ip_active(port) &&
                    985:                    (ip_kotype(port) == IKOT_TASK)) {
                    986:                        space = ((task_t) port->ip_kobject)->itk_space;
                    987:                        is_reference(space);
                    988:                }
                    989:                ip_unlock(port);
                    990:        }
                    991: 
                    992:        return space;
                    993: }
                    994: 
                    995: /*
                    996:  *     Routine:        convert_port_to_map
                    997:  *     Purpose:
                    998:  *             Convert from a port to a map.
                    999:  *             Doesn't consume the port ref; produces a map ref,
                   1000:  *             which may be null.
                   1001:  *     Conditions:
                   1002:  *             Nothing locked.
                   1003:  */
                   1004: 
                   1005: vm_map_t
                   1006: convert_port_to_map(port)
                   1007:        ipc_port_t port;
                   1008: {
                   1009:        vm_map_t map = VM_MAP_NULL;
                   1010: 
                   1011:        if (IP_VALID(port)) {
                   1012:                ip_lock(port);
                   1013:                if (ip_active(port) &&
                   1014:                    (ip_kotype(port) == IKOT_TASK)) {
                   1015:                        map = ((task_t) port->ip_kobject)->map;
                   1016:                        vm_map_reference(map);
                   1017:                }
                   1018:                ip_unlock(port);
                   1019:        }
                   1020: 
                   1021:        return map;
                   1022: }
                   1023: 
                   1024: /*
                   1025:  *     Routine:        convert_port_to_thread
                   1026:  *     Purpose:
                   1027:  *             Convert from a port to a thread.
                   1028:  *             Doesn't consume the port ref; produces a thread ref,
                   1029:  *             which may be null.
                   1030:  *     Conditions:
                   1031:  *             Nothing locked.
                   1032:  */
                   1033: 
                   1034: thread_t
                   1035: convert_port_to_thread(port)
                   1036:        ipc_port_t port;
                   1037: {
                   1038:        thread_t thread = THREAD_NULL;
                   1039: 
                   1040:        if (IP_VALID(port)) {
                   1041:                ip_lock(port);
                   1042:                if (ip_active(port) &&
                   1043:                    (ip_kotype(port) == IKOT_THREAD)) {
                   1044:                        thread = (thread_t) port->ip_kobject;
                   1045:                        thread_reference(thread);
                   1046:                }
                   1047:                ip_unlock(port);
                   1048:        }
                   1049: 
                   1050:        return thread;
                   1051: }
                   1052: 
                   1053: /*
                   1054:  *     Routine:        convert_task_to_port
                   1055:  *     Purpose:
                   1056:  *             Convert from a task to a port.
                   1057:  *             Consumes a task ref; produces a naked send right
1.1.1.2   root     1058:  *             which may be invalid.
1.1       root     1059:  *     Conditions:
                   1060:  *             Nothing locked.
                   1061:  */
                   1062: 
                   1063: ipc_port_t
                   1064: convert_task_to_port(task)
                   1065:        task_t task;
                   1066: {
                   1067:        ipc_port_t port;
                   1068: 
                   1069:        itk_lock(task);
                   1070:        if (task->itk_self != IP_NULL)
                   1071:                port = ipc_port_make_send(task->itk_self);
                   1072:        else
                   1073:                port = IP_NULL;
                   1074:        itk_unlock(task);
                   1075: 
                   1076:        task_deallocate(task);
                   1077:        return port;
                   1078: }
                   1079: 
                   1080: /*
                   1081:  *     Routine:        convert_thread_to_port
                   1082:  *     Purpose:
                   1083:  *             Convert from a thread to a port.
                   1084:  *             Consumes a thread ref; produces a naked send right
                   1085:  *             which may be invalid.
                   1086:  *     Conditions:
                   1087:  *             Nothing locked.
                   1088:  */
                   1089: 
                   1090: ipc_port_t
                   1091: convert_thread_to_port(thread)
                   1092:        thread_t thread;
                   1093: {
                   1094:        ipc_port_t port;
                   1095: 
                   1096:        ith_lock(thread);
                   1097:        if (thread->ith_self != IP_NULL)
                   1098:                port = ipc_port_make_send(thread->ith_self);
                   1099:        else
                   1100:                port = IP_NULL;
                   1101:        ith_unlock(thread);
                   1102: 
                   1103:        thread_deallocate(thread);
                   1104:        return port;
                   1105: }
                   1106: 
                   1107: /*
                   1108:  *     Routine:        space_deallocate
                   1109:  *     Purpose:
                   1110:  *             Deallocate a space ref produced by convert_port_to_space.
                   1111:  *     Conditions:
                   1112:  *             Nothing locked.
                   1113:  */
                   1114: 
                   1115: void
                   1116: space_deallocate(space)
                   1117:        ipc_space_t space;
                   1118: {
                   1119:        if (space != IS_NULL)
                   1120:                is_release(space);
                   1121: }

unix.superglobalmegacorp.com

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