Annotation of Gnu-Mach/ipc/ipc_object.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File:   ipc/ipc_object.c
                     28:  *     Author: Rich Draves
                     29:  *     Date:   1989
                     30:  *
                     31:  *     Functions to manipulate IPC objects.
                     32:  */
                     33: 
                     34: #include <mach_ipc_compat.h>
                     35: 
                     36: #include <mach/boolean.h>
                     37: #include <mach/kern_return.h>
                     38: #include <mach/port.h>
                     39: #include <mach/message.h>
                     40: #include <ipc/port.h>
                     41: #include <ipc/ipc_space.h>
                     42: #include <ipc/ipc_entry.h>
                     43: #include <ipc/ipc_object.h>
                     44: #include <ipc/ipc_hash.h>
                     45: #include <ipc/ipc_right.h>
                     46: #include <ipc/ipc_notify.h>
                     47: #include <ipc/ipc_pset.h>
                     48: 
                     49: zone_t ipc_object_zones[IOT_NUMBER];
                     50: 
                     51: 
                     52: 
                     53: /*
                     54:  *     Routine:        ipc_object_reference
                     55:  *     Purpose:
                     56:  *             Take a reference to an object.
                     57:  */
                     58: 
                     59: void
                     60: ipc_object_reference(
                     61:        ipc_object_t    object)
                     62: {
                     63:        io_lock(object);
                     64:        assert(object->io_references > 0);
                     65:        io_reference(object);
                     66:        io_unlock(object);
                     67: }
                     68: 
                     69: /*
                     70:  *     Routine:        ipc_object_release
                     71:  *     Purpose:
                     72:  *             Release a reference to an object.
                     73:  */
                     74: 
                     75: void
                     76: ipc_object_release(
                     77:        ipc_object_t    object)
                     78: {
                     79:        io_lock(object);
                     80:        assert(object->io_references > 0);
                     81:        io_release(object);
                     82:        io_check_unlock(object);
                     83: }
                     84: 
                     85: /*
                     86:  *     Routine:        ipc_object_translate
                     87:  *     Purpose:
                     88:  *             Look up an object in a space.
                     89:  *     Conditions:
                     90:  *             Nothing locked before.  If successful, the object
                     91:  *             is returned locked.  The caller doesn't get a ref.
                     92:  *     Returns:
                     93:  *             KERN_SUCCESS            Objected returned locked.
                     94:  *             KERN_INVALID_TASK       The space is dead.
                     95:  *             KERN_INVALID_NAME       The name doesn't denote a right.
                     96:  *             KERN_INVALID_RIGHT      Name doesn't denote the correct right.
                     97:  */
                     98: 
                     99: kern_return_t
                    100: ipc_object_translate(
                    101:        ipc_space_t             space,
                    102:        mach_port_t             name,
                    103:        mach_port_right_t       right,
                    104:        ipc_object_t            *objectp)
                    105: {
                    106:        ipc_entry_t entry;
                    107:        ipc_object_t object;
                    108:        kern_return_t kr;
                    109: 
                    110:        kr = ipc_right_lookup_read(space, name, &entry);
                    111:        if (kr != KERN_SUCCESS)
                    112:                return kr;
                    113:        /* space is read-locked and active */
                    114: 
                    115:        if ((entry->ie_bits & MACH_PORT_TYPE(right)) == (mach_port_right_t) 0) {
                    116:                is_read_unlock(space);
                    117:                return KERN_INVALID_RIGHT;
                    118:        }
                    119: 
                    120:        object = entry->ie_object;
                    121:        assert(object != IO_NULL);
                    122: 
                    123:        io_lock(object);
                    124:        is_read_unlock(space);
                    125: 
                    126:        *objectp = object;
                    127:        return KERN_SUCCESS;
                    128: }
                    129: 
                    130: /*
                    131:  *     Routine:        ipc_object_alloc_dead
                    132:  *     Purpose:
                    133:  *             Allocate a dead-name entry.
                    134:  *     Conditions:
                    135:  *             Nothing locked.
                    136:  *     Returns:
                    137:  *             KERN_SUCCESS            The dead name is allocated.
                    138:  *             KERN_INVALID_TASK       The space is dead.
                    139:  *             KERN_NO_SPACE           No room for an entry in the space.
                    140:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    141:  */
                    142: 
                    143: kern_return_t
                    144: ipc_object_alloc_dead(
                    145:        ipc_space_t     space,
                    146:        mach_port_t     *namep)
                    147: {
                    148:        ipc_entry_t entry;
                    149:        kern_return_t kr;
                    150: 
                    151: 
                    152:        kr = ipc_entry_alloc(space, namep, &entry);
                    153:        if (kr != KERN_SUCCESS)
                    154:                return kr;
                    155:        /* space is write-locked */
                    156: 
                    157:        /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
                    158: 
                    159:        assert(entry->ie_object == IO_NULL);
                    160:        entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
                    161: 
                    162:        is_write_unlock(space);
                    163:        return KERN_SUCCESS;
                    164: }
                    165: 
                    166: /*
                    167:  *     Routine:        ipc_object_alloc_dead_name
                    168:  *     Purpose:
                    169:  *             Allocate a dead-name entry, with a specific name.
                    170:  *     Conditions:
                    171:  *             Nothing locked.
                    172:  *     Returns:
                    173:  *             KERN_SUCCESS            The dead name is allocated.
                    174:  *             KERN_INVALID_TASK       The space is dead.
                    175:  *             KERN_NAME_EXISTS        The name already denotes a right.
                    176:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    177:  */
                    178: 
                    179: kern_return_t
                    180: ipc_object_alloc_dead_name(
                    181:        ipc_space_t     space,
                    182:        mach_port_t     name)
                    183: {
                    184:        ipc_entry_t entry;
                    185:        kern_return_t kr;
                    186: 
                    187: 
                    188:        kr = ipc_entry_alloc_name(space, name, &entry);
                    189:        if (kr != KERN_SUCCESS)
                    190:                return kr;
                    191:        /* space is write-locked */
                    192: 
                    193:        if (ipc_right_inuse(space, name, entry))
                    194:                return KERN_NAME_EXISTS;
                    195: 
                    196:        /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
                    197: 
                    198:        assert(entry->ie_object == IO_NULL);
                    199:        entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
                    200: 
                    201:        is_write_unlock(space);
                    202:        return KERN_SUCCESS;
                    203: }
                    204: 
                    205: /*
                    206:  *     Routine:        ipc_object_alloc
                    207:  *     Purpose:
                    208:  *             Allocate an object.
                    209:  *     Conditions:
                    210:  *             Nothing locked.  If successful, the object is returned locked.
                    211:  *             The caller doesn't get a reference for the object.
                    212:  *     Returns:
                    213:  *             KERN_SUCCESS            The object is allocated.
                    214:  *             KERN_INVALID_TASK       The space is dead.
                    215:  *             KERN_NO_SPACE           No room for an entry in the space.
                    216:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    217:  */
                    218: 
                    219: kern_return_t
                    220: ipc_object_alloc(
                    221:        ipc_space_t             space,
                    222:        ipc_object_type_t       otype,
                    223:        mach_port_type_t        type,
                    224:        mach_port_urefs_t       urefs,
                    225:        mach_port_t             *namep,
                    226:        ipc_object_t            *objectp)
                    227: {
                    228:        ipc_object_t object;
                    229:        ipc_entry_t entry;
                    230:        kern_return_t kr;
                    231: 
                    232:        assert(otype < IOT_NUMBER);
                    233:        assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
                    234:        assert(type != MACH_PORT_TYPE_NONE);
                    235:        assert(urefs <= MACH_PORT_UREFS_MAX);
                    236: 
                    237:        object = io_alloc(otype);
                    238:        if (object == IO_NULL)
                    239:                return KERN_RESOURCE_SHORTAGE;
                    240: 
                    241:        if (otype == IOT_PORT) {
                    242:                ipc_port_t port = (ipc_port_t)object;
                    243: 
                    244:                bzero((char *)port, sizeof(*port));
                    245:        } else if (otype == IOT_PORT_SET) {
                    246:                ipc_pset_t pset = (ipc_pset_t)object;
                    247: 
                    248:                bzero((char *)pset, sizeof(*pset));
                    249:        }
                    250:        *namep = (mach_port_t)object;
                    251:        kr = ipc_entry_alloc(space, namep, &entry);
                    252:        if (kr != KERN_SUCCESS) {
                    253:                io_free(otype, object);
                    254:                return kr;
                    255:        }
                    256:        /* space is write-locked */
                    257: 
                    258:        entry->ie_bits |= type | urefs;
                    259:        entry->ie_object = object;
                    260: 
                    261:        io_lock_init(object);
                    262:        io_lock(object);
                    263:        is_write_unlock(space);
                    264: 
                    265:        object->io_references = 1; /* for entry, not caller */
                    266:        object->io_bits = io_makebits(TRUE, otype, 0);
                    267: 
                    268:        *objectp = object;
                    269:        return KERN_SUCCESS;
                    270: }
                    271: 
                    272: /*
                    273:  *     Routine:        ipc_object_alloc_name
                    274:  *     Purpose:
                    275:  *             Allocate an object, with a specific name.
                    276:  *     Conditions:
                    277:  *             Nothing locked.  If successful, the object is returned locked.
                    278:  *             The caller doesn't get a reference for the object.
                    279:  *     Returns:
                    280:  *             KERN_SUCCESS            The object is allocated.
                    281:  *             KERN_INVALID_TASK       The space is dead.
                    282:  *             KERN_NAME_EXISTS        The name already denotes a right.
                    283:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    284:  */
                    285: 
                    286: kern_return_t
                    287: ipc_object_alloc_name(
                    288:        ipc_space_t             space,
                    289:        ipc_object_type_t       otype,
                    290:        mach_port_type_t        type,
                    291:        mach_port_urefs_t       urefs,
                    292:        mach_port_t             name,
                    293:        ipc_object_t            *objectp)
                    294: {
                    295:        ipc_object_t object;
                    296:        ipc_entry_t entry;
                    297:        kern_return_t kr;
                    298: 
                    299:        assert(otype < IOT_NUMBER);
                    300:        assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
                    301:        assert(type != MACH_PORT_TYPE_NONE);
                    302:        assert(urefs <= MACH_PORT_UREFS_MAX);
                    303: 
                    304:        object = io_alloc(otype);
                    305:        if (object == IO_NULL)
                    306:                return KERN_RESOURCE_SHORTAGE;
                    307: 
                    308:        if (otype == IOT_PORT) {
                    309:                ipc_port_t port = (ipc_port_t)object;
                    310: 
                    311:                bzero((char *)port, sizeof(*port));
                    312:        } else if (otype == IOT_PORT_SET) {
                    313:                ipc_pset_t pset = (ipc_pset_t)object;
                    314: 
                    315:                bzero((char *)pset, sizeof(*pset));
                    316:        }
                    317: 
                    318:        kr = ipc_entry_alloc_name(space, name, &entry);
                    319:        if (kr != KERN_SUCCESS) {
                    320:                io_free(otype, object);
                    321:                return kr;
                    322:        }
                    323:        /* space is write-locked */
                    324: 
                    325:        if (ipc_right_inuse(space, name, entry)) {
                    326:                io_free(otype, object);
                    327:                return KERN_NAME_EXISTS;
                    328:        }
                    329: 
                    330:        entry->ie_bits |= type | urefs;
                    331:        entry->ie_object = object;
                    332: 
                    333:        io_lock_init(object);
                    334:        io_lock(object);
                    335:        is_write_unlock(space);
                    336: 
                    337:        object->io_references = 1; /* for entry, not caller */
                    338:        object->io_bits = io_makebits(TRUE, otype, 0);
                    339: 
                    340:        *objectp = object;
                    341:        return KERN_SUCCESS;
                    342: }
                    343: 
                    344: /*
                    345:  *     Routine:        ipc_object_copyin_type
                    346:  *     Purpose:
                    347:  *             Convert a send type name to a received type name.
                    348:  */
                    349: 
                    350: mach_msg_type_name_t
                    351: ipc_object_copyin_type(
                    352:        mach_msg_type_name_t    msgt_name)
                    353: {
                    354:        switch (msgt_name) {
                    355:            case 0:
                    356:                return 0;
                    357: 
                    358:            case MACH_MSG_TYPE_MOVE_RECEIVE:
                    359:                return MACH_MSG_TYPE_PORT_RECEIVE;
                    360: 
                    361:            case MACH_MSG_TYPE_MOVE_SEND_ONCE:
                    362:            case MACH_MSG_TYPE_MAKE_SEND_ONCE:
                    363:                return MACH_MSG_TYPE_PORT_SEND_ONCE;
                    364: 
                    365:            case MACH_MSG_TYPE_MOVE_SEND:
                    366:            case MACH_MSG_TYPE_MAKE_SEND:
                    367:            case MACH_MSG_TYPE_COPY_SEND:
                    368:                return MACH_MSG_TYPE_PORT_SEND;
                    369: 
                    370: #if    MACH_IPC_COMPAT
                    371:            case MSG_TYPE_PORT:
                    372:                return MACH_MSG_TYPE_PORT_SEND;
                    373: 
                    374:            case MSG_TYPE_PORT_ALL:
                    375:                return MACH_MSG_TYPE_PORT_RECEIVE;
                    376: #endif MACH_IPC_COMPAT
                    377: 
                    378:            default:
                    379: #if MACH_ASSERT
                    380:                assert(!"ipc_object_copyin_type: strange rights");
                    381: #else
                    382:                panic("ipc_object_copyin_type: strange rights");
                    383: #endif
                    384:                return 0; /* in case assert/panic returns */
                    385:        }
                    386: }
                    387: 
                    388: /*
                    389:  *     Routine:        ipc_object_copyin
                    390:  *     Purpose:
                    391:  *             Copyin a capability from a space.
                    392:  *             If successful, the caller gets a ref
                    393:  *             for the resulting object, unless it is IO_DEAD.
                    394:  *     Conditions:
                    395:  *             Nothing locked.
                    396:  *     Returns:
                    397:  *             KERN_SUCCESS            Acquired an object, possibly IO_DEAD.
                    398:  *             KERN_INVALID_TASK       The space is dead.
                    399:  *             KERN_INVALID_NAME       Name doesn't exist in space.
                    400:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
                    401:  */
                    402: 
                    403: kern_return_t
                    404: ipc_object_copyin(
                    405:        ipc_space_t             space,
                    406:        mach_port_t             name,
                    407:        mach_msg_type_name_t    msgt_name,
                    408:        ipc_object_t            *objectp)
                    409: {
                    410:        ipc_entry_t entry;
                    411:        ipc_port_t soright;
                    412:        kern_return_t kr;
                    413: 
                    414:        /*
                    415:         *      Could first try a read lock when doing
                    416:         *      MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
                    417:         *      and MACH_MSG_TYPE_MAKE_SEND_ONCE.
                    418:         */
                    419: 
                    420:        kr = ipc_right_lookup_write(space, name, &entry);
                    421:        if (kr != KERN_SUCCESS)
                    422:                return kr;
                    423:        /* space is write-locked and active */
                    424: 
                    425:        kr = ipc_right_copyin(space, name, entry,
                    426:                              msgt_name, TRUE,
                    427:                              objectp, &soright);
                    428:        if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
                    429:                ipc_entry_dealloc(space, name, entry);
                    430:        is_write_unlock(space);
                    431: 
                    432:        if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
                    433:                ipc_notify_port_deleted(soright, name);
                    434: 
                    435:        return kr;
                    436: }
                    437: 
                    438: /*
                    439:  *     Routine:        ipc_object_copyin_from_kernel
                    440:  *     Purpose:
                    441:  *             Copyin a naked capability from the kernel.
                    442:  *
                    443:  *             MACH_MSG_TYPE_MOVE_RECEIVE
                    444:  *                     The receiver must be ipc_space_kernel.
                    445:  *                     Consumes the naked receive right.
                    446:  *             MACH_MSG_TYPE_COPY_SEND
                    447:  *                     A naked send right must be supplied.
                    448:  *                     The port gains a reference, and a send right
                    449:  *                     if the port is still active.
                    450:  *             MACH_MSG_TYPE_MAKE_SEND
                    451:  *                     The receiver must be ipc_space_kernel.
                    452:  *                     The port gains a reference and a send right.
                    453:  *             MACH_MSG_TYPE_MOVE_SEND
                    454:  *                     Consumes a naked send right.
                    455:  *             MACH_MSG_TYPE_MAKE_SEND_ONCE
                    456:  *                     The receiver must be ipc_space_kernel.
                    457:  *                     The port gains a reference and a send-once right.
                    458:  *             MACH_MSG_TYPE_MOVE_SEND_ONCE
                    459:  *                     Consumes a naked send-once right.
                    460:  *     Conditions:
                    461:  *             Nothing locked.
                    462:  */
                    463: 
                    464: void
                    465: ipc_object_copyin_from_kernel(
                    466:        ipc_object_t            object,
                    467:        mach_msg_type_name_t    msgt_name)
                    468: {
                    469:        assert(IO_VALID(object));
                    470: 
                    471:        switch (msgt_name) {
                    472:            case MACH_MSG_TYPE_MOVE_RECEIVE: {
                    473:                ipc_port_t port = (ipc_port_t) object;
                    474: 
                    475:                ip_lock(port);
                    476:                assert(ip_active(port));
                    477:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    478:                assert(port->ip_receiver == ipc_space_kernel);
                    479: 
                    480:                /* relevant part of ipc_port_clear_receiver */
                    481:                ipc_port_set_mscount(port, 0);
                    482: 
                    483:                port->ip_receiver_name = MACH_PORT_NULL;
                    484:                port->ip_destination = IP_NULL;
                    485:                ip_unlock(port);
                    486:                break;
                    487:            }
                    488: 
                    489:            case MACH_MSG_TYPE_COPY_SEND: {
                    490:                ipc_port_t port = (ipc_port_t) object;
                    491: 
                    492:                ip_lock(port);
                    493:                if (ip_active(port)) {
                    494:                        assert(port->ip_srights > 0);
                    495:                        port->ip_srights++;
                    496:                }
                    497:                ip_reference(port);
                    498:                ip_unlock(port);
                    499:                break;
                    500:            }
                    501: 
                    502:            case MACH_MSG_TYPE_MAKE_SEND: {
                    503:                ipc_port_t port = (ipc_port_t) object;
                    504: 
                    505:                ip_lock(port);
                    506:                assert(ip_active(port));
                    507:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    508:                assert(port->ip_receiver == ipc_space_kernel);
                    509: 
                    510:                ip_reference(port);
                    511:                port->ip_mscount++;
                    512:                port->ip_srights++;
                    513:                ip_unlock(port);
                    514:                break;
                    515:            }
                    516: 
                    517:            case MACH_MSG_TYPE_MOVE_SEND:
                    518:                /* move naked send right into the message */
                    519:                break;
                    520: 
                    521:            case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
                    522:                ipc_port_t port = (ipc_port_t) object;
                    523: 
                    524:                ip_lock(port);
                    525:                assert(ip_active(port));
                    526:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    527:                assert(port->ip_receiver == ipc_space_kernel);
                    528: 
                    529:                ip_reference(port);
                    530:                port->ip_sorights++;
                    531:                ip_unlock(port);
                    532:                break;
                    533:            }
                    534: 
                    535:            case MACH_MSG_TYPE_MOVE_SEND_ONCE:
                    536:                /* move naked send-once right into the message */
                    537:                break;
                    538: 
                    539:            default:
                    540: #if MACH_ASSERT
                    541:                assert(!"ipc_object_copyin_from_kernel: strange rights");
                    542: #else
                    543:                panic("ipc_object_copyin_from_kernel: strange rights");
                    544: #endif
                    545:        }
                    546: }
                    547: 
                    548: /*
                    549:  *     Routine:        ipc_object_destroy
                    550:  *     Purpose:
                    551:  *             Destroys a naked capability.
                    552:  *             Consumes a ref for the object.
                    553:  *
                    554:  *             A receive right should be in limbo or in transit.
                    555:  *     Conditions:
                    556:  *             Nothing locked.
                    557:  */
                    558: 
                    559: void
                    560: ipc_object_destroy(
                    561:        ipc_object_t            object,
                    562:        mach_msg_type_name_t    msgt_name)
                    563: {
                    564:        assert(IO_VALID(object));
                    565:        assert(io_otype(object) == IOT_PORT);
                    566: 
                    567:        switch (msgt_name) {
                    568:            case MACH_MSG_TYPE_PORT_SEND:
                    569:                ipc_port_release_send((ipc_port_t) object);
                    570:                break;
                    571: 
                    572:            case MACH_MSG_TYPE_PORT_SEND_ONCE:
                    573:                ipc_notify_send_once((ipc_port_t) object);
                    574:                break;
                    575: 
                    576:            case MACH_MSG_TYPE_PORT_RECEIVE:
                    577:                ipc_port_release_receive((ipc_port_t) object);
                    578:                break;
                    579: 
                    580:            default:
                    581:                panic("ipc_object_destroy: strange rights");
                    582:        }
                    583: }
                    584: 
                    585: /*
                    586:  *     Routine:        ipc_object_copyout
                    587:  *     Purpose:
                    588:  *             Copyout a capability, placing it into a space.
                    589:  *             If successful, consumes a ref for the object.
                    590:  *     Conditions:
                    591:  *             Nothing locked.
                    592:  *     Returns:
                    593:  *             KERN_SUCCESS            Copied out object, consumed ref.
                    594:  *             KERN_INVALID_TASK       The space is dead.
                    595:  *             KERN_INVALID_CAPABILITY The object is dead.
                    596:  *             KERN_NO_SPACE           No room in space for another right.
                    597:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                    598:  *             KERN_UREFS_OVERFLOW     Urefs limit exceeded
                    599:  *                     and overflow wasn't specified.
                    600:  */
                    601: 
                    602: kern_return_t
                    603: ipc_object_copyout(
                    604:        ipc_space_t             space,
                    605:        ipc_object_t            object,
                    606:        mach_msg_type_name_t    msgt_name,
                    607:        boolean_t               overflow,
                    608:        mach_port_t             *namep)
                    609: {
                    610:        mach_port_t name;
                    611:        ipc_entry_t entry;
                    612:        kern_return_t kr;
                    613: 
                    614:        assert(IO_VALID(object));
                    615:        assert(io_otype(object) == IOT_PORT);
                    616: 
                    617:        is_write_lock(space);
                    618: 
                    619:        for (;;) {
                    620:                if (!space->is_active) {
                    621:                        is_write_unlock(space);
                    622:                        return KERN_INVALID_TASK;
                    623:                }
                    624: 
                    625:                if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                    626:                    ipc_right_reverse(space, object, &name, &entry)) {
                    627:                        /* object is locked and active */
                    628: 
                    629:                        assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    630:                        break;
                    631:                }
                    632: 
                    633:                kr = ipc_entry_get(space, &name, &entry);
                    634:                if (kr != KERN_SUCCESS) {
                    635:                        /* unlocks/locks space, so must start again */
                    636: 
                    637:                        kr = ipc_entry_grow_table(space);
                    638:                        if (kr != KERN_SUCCESS)
                    639:                                return kr; /* space is unlocked */
                    640: 
                    641:                        continue;
                    642:                }
                    643: 
                    644:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    645:                assert(entry->ie_object == IO_NULL);
                    646: 
                    647:                io_lock(object);
                    648:                if (!io_active(object)) {
                    649:                        io_unlock(object);
                    650:                        ipc_entry_dealloc(space, name, entry);
                    651:                        is_write_unlock(space);
                    652:                        return KERN_INVALID_CAPABILITY;
                    653:                }
                    654: 
                    655:                entry->ie_object = object;
                    656:                break;
                    657:        }
                    658: 
                    659:        /* space is write-locked and active, object is locked and active */
                    660: 
                    661:        kr = ipc_right_copyout(space, name, entry,
                    662:                               msgt_name, overflow, object);
                    663:        /* object is unlocked */
                    664:        is_write_unlock(space);
                    665: 
                    666:        if (kr == KERN_SUCCESS)
                    667:                *namep = name;
                    668:        return kr;
                    669: }
                    670: 
                    671: #if 0
                    672: /* XXX same, but don't check for already-existing send rights */
                    673: kern_return_t
                    674: ipc_object_copyout_multiname(space, object, namep)
                    675:        ipc_space_t space;
                    676:        ipc_object_t object;
                    677:        mach_port_t *namep;
                    678: {
                    679:        mach_port_t name;
                    680:        ipc_entry_t entry;
                    681:        kern_return_t kr;
                    682: 
                    683:        assert(IO_VALID(object));
                    684:        assert(io_otype(object) == IOT_PORT);
                    685: 
                    686:        is_write_lock(space);
                    687: 
                    688:        for (;;) {
                    689:                if (!space->is_active) {
                    690:                        is_write_unlock(space);
                    691:                        return KERN_INVALID_TASK;
                    692:                }
                    693: 
                    694:                kr = ipc_entry_get(space, &name, &entry);
                    695:                if (kr != KERN_SUCCESS) {
                    696:                        /* unlocks/locks space, so must start again */
                    697: 
                    698:                        kr = ipc_entry_grow_table(space);
                    699:                        if (kr != KERN_SUCCESS)
                    700:                                return kr; /* space is unlocked */
                    701: 
                    702:                        continue;
                    703:                }
                    704: 
                    705:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    706:                assert(entry->ie_object == IO_NULL);
                    707: 
                    708:                io_lock(object);
                    709:                if (!io_active(object)) {
                    710:                        io_unlock(object);
                    711:                        ipc_entry_dealloc(space, name, entry);
                    712:                        is_write_unlock(space);
                    713:                        return KERN_INVALID_CAPABILITY;
                    714:                }
                    715: 
                    716:                entry->ie_object = object;
                    717:                break;
                    718:        }
                    719: 
                    720:        /* space is write-locked and active, object is locked and active */
                    721: 
                    722:        kr = ipc_right_copyout_multiname(space, name, entry, object);
                    723:        /* object is unlocked */
                    724:        is_write_unlock(space);
                    725: 
                    726:        if (kr == KERN_SUCCESS)
                    727:                *namep = name;
                    728:        return kr;
                    729: }
                    730: #endif 0
                    731: 
                    732: /*
                    733:  *     Routine:        ipc_object_copyout_name
                    734:  *     Purpose:
                    735:  *             Copyout a capability, placing it into a space.
                    736:  *             The specified name is used for the capability.
                    737:  *             If successful, consumes a ref for the object.
                    738:  *     Conditions:
                    739:  *             Nothing locked.
                    740:  *     Returns:
                    741:  *             KERN_SUCCESS            Copied out object, consumed ref.
                    742:  *             KERN_INVALID_TASK       The space is dead.
                    743:  *             KERN_INVALID_CAPABILITY The object is dead.
                    744:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                    745:  *             KERN_UREFS_OVERFLOW     Urefs limit exceeded
                    746:  *                     and overflow wasn't specified.
                    747:  *             KERN_RIGHT_EXISTS       Space has rights under another name.
                    748:  *             KERN_NAME_EXISTS        Name is already used.
                    749:  */
                    750: 
                    751: kern_return_t
                    752: ipc_object_copyout_name(
                    753:        ipc_space_t             space,
                    754:        ipc_object_t            object,
                    755:        mach_msg_type_name_t    msgt_name,
                    756:        boolean_t               overflow,
                    757:        mach_port_t             name)
                    758: {
                    759:        mach_port_t oname;
                    760:        ipc_entry_t oentry;
                    761:        ipc_entry_t entry;
                    762:        kern_return_t kr;
                    763: 
                    764:        assert(IO_VALID(object));
                    765:        assert(io_otype(object) == IOT_PORT);
                    766: 
                    767:        kr = ipc_entry_alloc_name(space, name, &entry);
                    768:        if (kr != KERN_SUCCESS)
                    769:                return kr;
                    770:        /* space is write-locked and active */
                    771: 
                    772:        if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                    773:            ipc_right_reverse(space, object, &oname, &oentry)) {
                    774:                /* object is locked and active */
                    775: 
                    776:                if (name != oname) {
                    777:                        io_unlock(object);
                    778: 
                    779:                        if (IE_BITS_TYPE(entry->ie_bits)
                    780:                                                == MACH_PORT_TYPE_NONE)
                    781:                                ipc_entry_dealloc(space, name, entry);
                    782: 
                    783:                        is_write_unlock(space);
                    784:                        return KERN_RIGHT_EXISTS;
                    785:                }
                    786: 
                    787:                assert(entry == oentry);
                    788:                assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    789:        } else {
                    790:                if (ipc_right_inuse(space, name, entry))
                    791:                        return KERN_NAME_EXISTS;
                    792: 
                    793:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    794:                assert(entry->ie_object == IO_NULL);
                    795: 
                    796:                io_lock(object);
                    797:                if (!io_active(object)) {
                    798:                        io_unlock(object);
                    799:                        ipc_entry_dealloc(space, name, entry);
                    800:                        is_write_unlock(space);
                    801:                        return KERN_INVALID_CAPABILITY;
                    802:                }
                    803: 
                    804:                entry->ie_object = object;
                    805:        }
                    806: 
                    807:        /* space is write-locked and active, object is locked and active */
                    808: 
                    809:        kr = ipc_right_copyout(space, name, entry,
                    810:                               msgt_name, overflow, object);
                    811:        /* object is unlocked */
                    812:        is_write_unlock(space);
                    813:        return kr;
                    814: }
                    815: 
                    816: /*
                    817:  *     Routine:        ipc_object_copyout_dest
                    818:  *     Purpose:
                    819:  *             Translates/consumes the destination right of a message.
                    820:  *             This is unlike normal copyout because the right is consumed
                    821:  *             in a funny way instead of being given to the receiving space.
                    822:  *             The receiver gets his name for the port, if he has receive
                    823:  *             rights, otherwise MACH_PORT_NULL.
                    824:  *     Conditions:
                    825:  *             The object is locked and active.  Nothing else locked.
                    826:  *             The object is unlocked and loses a reference.
                    827:  */
                    828: 
                    829: void
                    830: ipc_object_copyout_dest(
                    831:        ipc_space_t             space,
                    832:        ipc_object_t            object,
                    833:        mach_msg_type_name_t    msgt_name,
                    834:        mach_port_t             *namep)
                    835: {
                    836:        mach_port_t name;
                    837: 
                    838:        assert(IO_VALID(object));
                    839:        assert(io_active(object));
                    840: 
                    841:        io_release(object);
                    842: 
                    843:        /*
                    844:         *      If the space is the receiver/owner of the object,
                    845:         *      then we quietly consume the right and return
                    846:         *      the space's name for the object.  Otherwise
                    847:         *      we destroy the right and return MACH_PORT_NULL.
                    848:         */
                    849: 
                    850:        switch (msgt_name) {
                    851:            case MACH_MSG_TYPE_PORT_SEND: {
                    852:                ipc_port_t port = (ipc_port_t) object;
                    853:                ipc_port_t nsrequest = IP_NULL;
                    854:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
                    855: 
                    856:                assert(port->ip_srights > 0);
                    857:                if (--port->ip_srights == 0) {
                    858:                        nsrequest = port->ip_nsrequest;
                    859:                        if (nsrequest != IP_NULL) {
                    860:                                port->ip_nsrequest = IP_NULL;
                    861:                                mscount = port->ip_mscount;
                    862:                        }
                    863:                }
                    864: 
                    865:                if (port->ip_receiver == space)
                    866:                        name = port->ip_receiver_name;
                    867:                else
                    868:                        name = MACH_PORT_NULL;
                    869: 
                    870:                ip_unlock(port);
                    871: 
                    872:                if (nsrequest != IP_NULL)
                    873:                        ipc_notify_no_senders(nsrequest, mscount);
                    874: 
                    875:                break;
                    876:            }
                    877: 
                    878:            case MACH_MSG_TYPE_PORT_SEND_ONCE: {
                    879:                ipc_port_t port = (ipc_port_t) object;
                    880: 
                    881:                assert(port->ip_sorights > 0);
                    882: 
                    883:                if (port->ip_receiver == space) {
                    884:                        /* quietly consume the send-once right */
                    885: 
                    886:                        port->ip_sorights--;
                    887:                        name = port->ip_receiver_name;
                    888:                        ip_unlock(port);
                    889:                } else {
                    890:                        /*
                    891:                         *      A very bizarre case.  The message
                    892:                         *      was received, but before this copyout
                    893:                         *      happened the space lost receive rights.
                    894:                         *      We can't quietly consume the soright
                    895:                         *      out from underneath some other task,
                    896:                         *      so generate a send-once notification.
                    897:                         */
                    898: 
                    899:                        ip_reference(port); /* restore ref */
                    900:                        ip_unlock(port);
                    901: 
                    902:                        ipc_notify_send_once(port);
                    903:                        name = MACH_PORT_NULL;
                    904:                }
                    905: 
                    906:                break;
                    907:            }
                    908: 
                    909:            default:
                    910: #if MACH_ASSERT
                    911:                assert(!"ipc_object_copyout_dest: strange rights");
                    912: #else
                    913:                panic("ipc_object_copyout_dest: strange rights");
                    914: #endif
                    915: 
                    916:        }
                    917: 
                    918:        *namep = name;
                    919: }
                    920: 
                    921: /*
                    922:  *     Routine:        ipc_object_rename
                    923:  *     Purpose:
                    924:  *             Rename an entry in a space.
                    925:  *     Conditions:
                    926:  *             Nothing locked.
                    927:  *     Returns:
                    928:  *             KERN_SUCCESS            Renamed the entry.
                    929:  *             KERN_INVALID_TASK       The space was dead.
                    930:  *             KERN_INVALID_NAME       oname didn't denote an entry.
                    931:  *             KERN_NAME_EXISTS        nname already denoted an entry.
                    932:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate new entry.
                    933:  */
                    934: 
                    935: kern_return_t
                    936: ipc_object_rename(
                    937:        ipc_space_t     space,
                    938:        mach_port_t     oname,
                    939:        mach_port_t     nname)
                    940: {
                    941:        ipc_entry_t oentry, nentry;
                    942:        kern_return_t kr;
                    943: 
                    944:        kr = ipc_entry_alloc_name(space, nname, &nentry);
                    945:        if (kr != KERN_SUCCESS)
                    946:                return kr;
                    947:        /* space is write-locked and active */
                    948: 
                    949:        if (ipc_right_inuse(space, nname, nentry)) {
                    950:                /* space is unlocked */
                    951:                return KERN_NAME_EXISTS;
                    952:        }
                    953: 
                    954:        /* don't let ipc_entry_lookup see the uninitialized new entry */
                    955: 
                    956:        if ((oname == nname) ||
                    957:            ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
                    958:                ipc_entry_dealloc(space, nname, nentry);
                    959:                is_write_unlock(space);
                    960:                return KERN_INVALID_NAME;
                    961:        }
                    962: 
                    963:        kr = ipc_right_rename(space, oname, oentry, nname, nentry);
                    964:        /* space is unlocked */
                    965:        return kr;
                    966: }
                    967: 
                    968: #if    MACH_IPC_COMPAT
                    969: 
                    970: /*
                    971:  *     Routine:        ipc_object_copyout_type_compat
                    972:  *     Purpose:
                    973:  *             Convert a carried type name to an old type name.
                    974:  */
                    975: 
                    976: mach_msg_type_name_t
                    977: ipc_object_copyout_type_compat(msgt_name)
                    978:        mach_msg_type_name_t msgt_name;
                    979: {
                    980:        switch (msgt_name) {
                    981:            case MACH_MSG_TYPE_PORT_SEND:
                    982:            case MACH_MSG_TYPE_PORT_SEND_ONCE:
                    983:                return MSG_TYPE_PORT;
                    984: 
                    985:            case MACH_MSG_TYPE_PORT_RECEIVE:
                    986:                return MSG_TYPE_PORT_ALL;
                    987: 
                    988:            default:
                    989: #if MACH_ASSERT
                    990:                assert(!"ipc_object_copyout_type_compat: strange rights");
                    991: #else
                    992:                panic("ipc_object_copyout_type_compat: strange rights");
                    993: #endif
                    994:        }
                    995: }
                    996: 
                    997: /*
                    998:  *     Routine:        ipc_object_copyin_compat
                    999:  *     Purpose:
                   1000:  *             Copyin a capability from a space.
                   1001:  *             If successful, the caller gets a ref
                   1002:  *             for the resulting object, which is always valid.
                   1003:  *     Conditions:
                   1004:  *             Nothing locked.
                   1005:  *     Returns:
                   1006:  *             KERN_SUCCESS            Acquired a valid object.
                   1007:  *             KERN_INVALID_TASK       The space is dead.
                   1008:  *             KERN_INVALID_NAME       Name doesn't exist in space.
                   1009:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
                   1010:  */
                   1011: 
                   1012: kern_return_t
                   1013: ipc_object_copyin_compat(space, name, msgt_name, dealloc, objectp)
                   1014:        ipc_space_t space;
                   1015:        mach_port_t name;
                   1016:        mach_msg_type_name_t msgt_name;
                   1017:        boolean_t dealloc;
                   1018:        ipc_object_t *objectp;
                   1019: {
                   1020:        ipc_entry_t entry;
                   1021:        kern_return_t kr;
                   1022: 
                   1023:        kr = ipc_right_lookup_write(space, name, &entry);
                   1024:        if (kr != KERN_SUCCESS)
                   1025:                return kr;
                   1026:        /* space is write-locked and active */
                   1027: 
                   1028:        kr = ipc_right_copyin_compat(space, name, entry,
                   1029:                                     msgt_name, dealloc, objectp);
                   1030:        /* space is unlocked */
                   1031:        return kr;
                   1032: }
                   1033: 
                   1034: /*
                   1035:  *     Routine:        ipc_object_copyin_header
                   1036:  *     Purpose:
                   1037:  *             Copyin a capability from a space.
                   1038:  *             If successful, the caller gets a ref
                   1039:  *             for the resulting object, which is always valid.
                   1040:  *             The type of the acquired capability is returned.
                   1041:  *     Conditions:
                   1042:  *             Nothing locked.
                   1043:  *     Returns:
                   1044:  *             KERN_SUCCESS            Acquired a valid object.
                   1045:  *             KERN_INVALID_TASK       The space is dead.
                   1046:  *             KERN_INVALID_NAME       Name doesn't exist in space.
                   1047:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
                   1048:  */
                   1049: 
                   1050: kern_return_t
                   1051: ipc_object_copyin_header(space, name, objectp, msgt_namep)
                   1052:        ipc_space_t space;
                   1053:        mach_port_t name;
                   1054:        ipc_object_t *objectp;
                   1055:        mach_msg_type_name_t *msgt_namep;
                   1056: {
                   1057:        ipc_entry_t entry;
                   1058:        kern_return_t kr;
                   1059: 
                   1060:        kr = ipc_right_lookup_write(space, name, &entry);
                   1061:        if (kr != KERN_SUCCESS)
                   1062:                return kr;
                   1063:        /* space is write-locked and active */
                   1064: 
                   1065:        kr = ipc_right_copyin_header(space, name, entry,
                   1066:                                     objectp, msgt_namep);
                   1067:        /* space is unlocked */
                   1068:        return kr;
                   1069: }
                   1070: 
                   1071: /*
                   1072:  *     Routine:        ipc_object_copyout_compat
                   1073:  *     Purpose:
                   1074:  *             Copyout a capability, placing it into a space.
                   1075:  *             If successful, consumes a ref for the object.
                   1076:  *
                   1077:  *             Marks new entries with IE_BITS_COMPAT.
                   1078:  *     Conditions:
                   1079:  *             Nothing locked.
                   1080:  *     Returns:
                   1081:  *             KERN_SUCCESS            Copied out object, consumed ref.
                   1082:  *             KERN_INVALID_TASK       The space is dead.
                   1083:  *             KERN_INVALID_CAPABILITY The object is dead.
                   1084:  *             KERN_NO_SPACE           No room in space for another right.
                   1085:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                   1086:  */
                   1087: 
                   1088: kern_return_t
                   1089: ipc_object_copyout_compat(space, object, msgt_name, namep)
                   1090:        ipc_space_t space;
                   1091:        ipc_object_t object;
                   1092:        mach_msg_type_name_t msgt_name;
                   1093:        mach_port_t *namep;
                   1094: {
                   1095:        mach_port_t name;
                   1096:        ipc_entry_t entry;
                   1097:        ipc_port_t port;
                   1098:        kern_return_t kr;
                   1099: 
                   1100:        assert(IO_VALID(object));
                   1101:        assert(io_otype(object) == IOT_PORT);
                   1102:        port = (ipc_port_t) object;
                   1103: 
                   1104:        is_write_lock(space);
                   1105: 
                   1106:        for (;;) {
                   1107:                ipc_port_request_index_t request;
                   1108: 
                   1109:                if (!space->is_active) {
                   1110:                        is_write_unlock(space);
                   1111:                        return KERN_INVALID_TASK;
                   1112:                }
                   1113: 
                   1114:                if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                   1115:                    ipc_right_reverse(space, (ipc_object_t) port,
                   1116:                                      &name, &entry)) {
                   1117:                        /* port is locked and active */
                   1118: 
                   1119:                        assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                   1120:                        break;
                   1121:                }
                   1122: 
                   1123:                kr = ipc_entry_get(space, &name, &entry);
                   1124:                if (kr != KERN_SUCCESS) {
                   1125:                        /* unlocks/locks space, so must start again */
                   1126: 
                   1127:                        kr = ipc_entry_grow_table(space);
                   1128:                        if (kr != KERN_SUCCESS)
                   1129:                                return kr; /* space is unlocked */
                   1130: 
                   1131:                        continue;
                   1132:                }
                   1133: 
                   1134:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                   1135:                assert(entry->ie_object == IO_NULL);
                   1136: 
                   1137:                ip_lock(port);
                   1138:                if (!ip_active(port)) {
                   1139:                        ip_unlock(port);
                   1140:                        ipc_entry_dealloc(space, name, entry);
                   1141:                        is_write_unlock(space);
                   1142:                        return KERN_INVALID_CAPABILITY;
                   1143:                }
                   1144: 
                   1145:                kr = ipc_port_dnrequest(port, name, ipr_spacem(space),
                   1146:                                        &request);
                   1147:                if (kr != KERN_SUCCESS) {
                   1148:                        ipc_entry_dealloc(space, name, entry);
                   1149:                        is_write_unlock(space);
                   1150: 
                   1151:                        kr = ipc_port_dngrow(port);
                   1152:                        /* port is unlocked */
                   1153:                        if (kr != KERN_SUCCESS)
                   1154:                                return kr;
                   1155: 
                   1156:                        is_write_lock(space);
                   1157:                        continue;
                   1158:                }
                   1159: 
                   1160:                is_reference(space); /* for dnrequest */
                   1161:                entry->ie_object = (ipc_object_t) port;
                   1162:                entry->ie_request = request;
                   1163:                entry->ie_bits |= IE_BITS_COMPAT;
                   1164:                break;
                   1165:        }
                   1166: 
                   1167:        /* space is write-locked and active, port is locked and active */
                   1168: 
                   1169:        kr = ipc_right_copyout(space, name, entry,
                   1170:                               msgt_name, TRUE, (ipc_object_t) port);
                   1171:        /* object is unlocked */
                   1172:        is_write_unlock(space);
                   1173: 
                   1174:        if (kr == KERN_SUCCESS)
                   1175:                *namep = name;
                   1176:        return kr;
                   1177: }
                   1178: 
                   1179: /*
                   1180:  *     Routine:        ipc_object_copyout_name_compat
                   1181:  *     Purpose:
                   1182:  *             Copyout a capability, placing it into a space.
                   1183:  *             The specified name is used for the capability.
                   1184:  *             If successful, consumes a ref for the object.
                   1185:  *
                   1186:  *             Like ipc_object_copyout_name, except that
                   1187:  *             the name can't be in use at all, even for the same
                   1188:  *             port, and IE_BITS_COMPAT gets turned on.
                   1189:  *     Conditions:
                   1190:  *             Nothing locked.
                   1191:  *     Returns:
                   1192:  *             KERN_SUCCESS            Copied out object, consumed ref.
                   1193:  *             KERN_INVALID_TASK       The space is dead.
                   1194:  *             KERN_INVALID_CAPABILITY The object is dead.
                   1195:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                   1196:  *             KERN_RIGHT_EXISTS       Space has rights under another name.
                   1197:  *             KERN_NAME_EXISTS        Name is already used.
                   1198:  */
                   1199: 
                   1200: kern_return_t
                   1201: ipc_object_copyout_name_compat(space, object, msgt_name, name)
                   1202:        ipc_space_t space;
                   1203:        ipc_object_t object;
                   1204:        mach_msg_type_name_t msgt_name;
                   1205:        mach_port_t name;
                   1206: {
                   1207:        ipc_entry_t entry;
                   1208:        ipc_port_t port;
                   1209:        kern_return_t kr;
                   1210: 
                   1211:        assert(IO_VALID(object));
                   1212:        assert(io_otype(object) == IOT_PORT);
                   1213:        port = (ipc_port_t) object;
                   1214: 
                   1215:        for (;;) {
                   1216:                mach_port_t oname;
                   1217:                ipc_entry_t oentry;
                   1218:                ipc_port_request_index_t request;
                   1219: 
                   1220:                kr = ipc_entry_alloc_name(space, name, &entry);
                   1221:                if (kr != KERN_SUCCESS)
                   1222:                        return kr;
                   1223:                /* space is write-locked and active */
                   1224: 
                   1225:                if (ipc_right_inuse(space, name, entry))
                   1226:                        return KERN_NAME_EXISTS; /* space is unlocked */
                   1227: 
                   1228:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                   1229:                assert(entry->ie_object == IO_NULL);
                   1230: 
                   1231:                if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                   1232:                    ipc_right_reverse(space, (ipc_object_t) port,
                   1233:                                      &oname, &oentry)) {
                   1234:                        /* port is locked and active */
                   1235: 
                   1236:                        ip_unlock(port);
                   1237:                        ipc_entry_dealloc(space, name, entry);
                   1238:                        is_write_unlock(space);
                   1239:                        return KERN_RIGHT_EXISTS;
                   1240:                }
                   1241: 
                   1242:                ip_lock(port);
                   1243:                if (!ip_active(port)) {
                   1244:                        ip_unlock(port);
                   1245:                        ipc_entry_dealloc(space, name, entry);
                   1246:                        is_write_unlock(space);
                   1247:                        return KERN_INVALID_CAPABILITY;
                   1248:                }
                   1249: 
                   1250:                kr = ipc_port_dnrequest(port, name, ipr_spacem(space),
                   1251:                                        &request);
                   1252:                if (kr != KERN_SUCCESS) {
                   1253:                        ipc_entry_dealloc(space, name, entry);
                   1254:                        is_write_unlock(space);
                   1255: 
                   1256:                        kr = ipc_port_dngrow(port);
                   1257:                        /* port is unlocked */
                   1258:                        if (kr != KERN_SUCCESS)
                   1259:                                return kr;
                   1260: 
                   1261:                        continue;
                   1262:                }
                   1263: 
                   1264:                is_reference(space); /* for dnrequest */
                   1265:                entry->ie_object = (ipc_object_t) port;
                   1266:                entry->ie_request = request;
                   1267:                entry->ie_bits |= IE_BITS_COMPAT;
                   1268:                break;
                   1269:        }
                   1270: 
                   1271:        /* space is write-locked and active, port is locked and active */
                   1272: 
                   1273:        kr = ipc_right_copyout(space, name, entry,
                   1274:                               msgt_name, TRUE, (ipc_object_t) port);
                   1275:        /* object is unlocked */
                   1276:        is_write_unlock(space);
                   1277: 
                   1278:        assert(kr == KERN_SUCCESS);
                   1279:        return kr;
                   1280: }
                   1281: 
                   1282: #endif MACH_IPC_COMPAT
                   1283: 
                   1284: #include <mach_kdb.h>
                   1285: 
                   1286: 
                   1287: #if    MACH_KDB
                   1288: #define        printf  kdbprintf
                   1289: 
                   1290: /*
                   1291:  *     Routine:        ipc_object_print
                   1292:  *     Purpose:
                   1293:  *             Pretty-print an object for kdb.
                   1294:  */
                   1295: 
                   1296: char *ikot_print_array[IKOT_MAX_TYPE] = {
                   1297:        "(NONE)             ",
                   1298:        "(THREAD)           ",
                   1299:        "(TASK)             ",
                   1300:        "(HOST)             ",
                   1301:        "(HOST_PRIV)        ",
                   1302:        "(PROCESSOR)        ",
                   1303:        "(PSET)             ",
                   1304:        "(PSET_NAME)        ",
                   1305:        "(PAGER)            ",
                   1306:        "(PAGER_REQUEST)    ",
                   1307:        "(DEVICE)           ",  /* 10 */
                   1308:        "(XMM_OBJECT)       ",
                   1309:        "(XMM_PAGER)        ",
                   1310:        "(XMM_KERNEL)       ",
                   1311:        "(XMM_REPLY)        ",
                   1312:        "(PAGER_TERMINATING)",
                   1313:        "(PAGING_NAME)      ",
                   1314:        "(HOST_SECURITY)    ",
                   1315:        "(LEDGER)           ",
                   1316:        "(MASTER_DEVICE)    ",
                   1317:        "(ACTIVATION)       ",  /* 20 */
                   1318:        "(SUBSYSTEM)        ",
                   1319:        "(IO_DONE_QUEUE)    ",
                   1320:        "(SEMAPHORE)        ",
                   1321:        "(LOCK_SET)         ",
                   1322:        "(CLOCK)            ",
                   1323:        "(CLOCK_CTRL)       ",  /* 26 */
                   1324:                                /* << new entries here  */
                   1325:        "(UNKNOWN)     "        /* magic catchall       */
                   1326: };     /* Please keep in sync with kern/ipc_kobject.h  */
                   1327: 
                   1328: void
                   1329: ipc_object_print(
                   1330:        ipc_object_t    object)
                   1331: {
                   1332:        int kotype;
                   1333: 
                   1334:        iprintf("%s", io_active(object) ? "active" : "dead");
                   1335:        printf(", refs=%d", object->io_references);
                   1336:        printf(", otype=%d", io_otype(object));
                   1337:        kotype = io_kotype(object);
                   1338:        if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
                   1339:                printf(", kotype=%d %s\n", io_kotype(object),
                   1340:                       ikot_print_array[kotype]);
                   1341:        else
                   1342:                printf(", kotype=0x%x %s\n", io_kotype(object),
                   1343:                       ikot_print_array[IKOT_UNKNOWN]);
                   1344: }
                   1345: 
                   1346: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

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