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