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

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

unix.superglobalmegacorp.com

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