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

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.2   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File:   ipc/ipc_object.c
                     28:  *     Author: Rich Draves
                     29:  *     Date:   1989
                     30:  *
                     31:  *     Functions to manipulate IPC objects.
                     32:  */
                     33: 
1.1.1.3 ! root       34: #include <string.h>
1.1       root       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>
1.1.1.3 ! root       48: #include <kern/debug.h>
        !            49: #include <kern/printf.h>
        !            50: #include <kern/slab.h>
1.1       root       51: 
1.1.1.3 ! root       52: #if    MACH_KDB
        !            53: #include <ddb/db_output.h>
        !            54: #endif /* MACH_KDB */
        !            55: 
        !            56: 
        !            57: struct kmem_cache ipc_object_caches[IOT_NUMBER];
1.1       root       58: 
                     59: 
                     60: 
                     61: /*
                     62:  *     Routine:        ipc_object_reference
                     63:  *     Purpose:
                     64:  *             Take a reference to an object.
                     65:  */
                     66: 
                     67: void
                     68: ipc_object_reference(
                     69:        ipc_object_t    object)
                     70: {
                     71:        io_lock(object);
                     72:        assert(object->io_references > 0);
                     73:        io_reference(object);
                     74:        io_unlock(object);
                     75: }
                     76: 
                     77: /*
                     78:  *     Routine:        ipc_object_release
                     79:  *     Purpose:
                     80:  *             Release a reference to an object.
                     81:  */
                     82: 
                     83: void
                     84: ipc_object_release(
                     85:        ipc_object_t    object)
                     86: {
                     87:        io_lock(object);
                     88:        assert(object->io_references > 0);
                     89:        io_release(object);
                     90:        io_check_unlock(object);
                     91: }
                     92: 
                     93: /*
                     94:  *     Routine:        ipc_object_translate
                     95:  *     Purpose:
                     96:  *             Look up an object in a space.
                     97:  *     Conditions:
                     98:  *             Nothing locked before.  If successful, the object
                     99:  *             is returned locked.  The caller doesn't get a ref.
                    100:  *     Returns:
                    101:  *             KERN_SUCCESS            Objected returned locked.
                    102:  *             KERN_INVALID_TASK       The space is dead.
                    103:  *             KERN_INVALID_NAME       The name doesn't denote a right.
                    104:  *             KERN_INVALID_RIGHT      Name doesn't denote the correct right.
                    105:  */
                    106: 
                    107: kern_return_t
                    108: ipc_object_translate(
                    109:        ipc_space_t             space,
                    110:        mach_port_t             name,
                    111:        mach_port_right_t       right,
                    112:        ipc_object_t            *objectp)
                    113: {
                    114:        ipc_entry_t entry;
                    115:        ipc_object_t object;
                    116:        kern_return_t kr;
                    117: 
                    118:        kr = ipc_right_lookup_read(space, name, &entry);
                    119:        if (kr != KERN_SUCCESS)
                    120:                return kr;
                    121:        /* space is read-locked and active */
                    122: 
                    123:        if ((entry->ie_bits & MACH_PORT_TYPE(right)) == (mach_port_right_t) 0) {
                    124:                is_read_unlock(space);
                    125:                return KERN_INVALID_RIGHT;
                    126:        }
                    127: 
                    128:        object = entry->ie_object;
                    129:        assert(object != IO_NULL);
                    130: 
                    131:        io_lock(object);
                    132:        is_read_unlock(space);
                    133: 
                    134:        *objectp = object;
                    135:        return KERN_SUCCESS;
                    136: }
                    137: 
                    138: /*
                    139:  *     Routine:        ipc_object_alloc_dead
                    140:  *     Purpose:
                    141:  *             Allocate a dead-name entry.
                    142:  *     Conditions:
                    143:  *             Nothing locked.
                    144:  *     Returns:
                    145:  *             KERN_SUCCESS            The dead name is allocated.
                    146:  *             KERN_INVALID_TASK       The space is dead.
                    147:  *             KERN_NO_SPACE           No room for an entry in the space.
                    148:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    149:  */
                    150: 
                    151: kern_return_t
                    152: ipc_object_alloc_dead(
                    153:        ipc_space_t     space,
                    154:        mach_port_t     *namep)
                    155: {
                    156:        ipc_entry_t entry;
                    157:        kern_return_t kr;
                    158: 
                    159: 
                    160:        kr = ipc_entry_alloc(space, namep, &entry);
                    161:        if (kr != KERN_SUCCESS)
                    162:                return kr;
                    163:        /* space is write-locked */
                    164: 
                    165:        /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
                    166: 
                    167:        assert(entry->ie_object == IO_NULL);
                    168:        entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
                    169: 
                    170:        is_write_unlock(space);
                    171:        return KERN_SUCCESS;
                    172: }
                    173: 
                    174: /*
                    175:  *     Routine:        ipc_object_alloc_dead_name
                    176:  *     Purpose:
                    177:  *             Allocate a dead-name entry, with a specific name.
                    178:  *     Conditions:
                    179:  *             Nothing locked.
                    180:  *     Returns:
                    181:  *             KERN_SUCCESS            The dead name is allocated.
                    182:  *             KERN_INVALID_TASK       The space is dead.
                    183:  *             KERN_NAME_EXISTS        The name already denotes a right.
                    184:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    185:  */
                    186: 
                    187: kern_return_t
                    188: ipc_object_alloc_dead_name(
                    189:        ipc_space_t     space,
                    190:        mach_port_t     name)
                    191: {
                    192:        ipc_entry_t entry;
                    193:        kern_return_t kr;
                    194: 
                    195: 
                    196:        kr = ipc_entry_alloc_name(space, name, &entry);
                    197:        if (kr != KERN_SUCCESS)
                    198:                return kr;
                    199:        /* space is write-locked */
                    200: 
                    201:        if (ipc_right_inuse(space, name, entry))
                    202:                return KERN_NAME_EXISTS;
                    203: 
                    204:        /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
                    205: 
                    206:        assert(entry->ie_object == IO_NULL);
                    207:        entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
                    208: 
                    209:        is_write_unlock(space);
                    210:        return KERN_SUCCESS;
                    211: }
                    212: 
                    213: /*
                    214:  *     Routine:        ipc_object_alloc
                    215:  *     Purpose:
                    216:  *             Allocate an object.
                    217:  *     Conditions:
                    218:  *             Nothing locked.  If successful, the object is returned locked.
                    219:  *             The caller doesn't get a reference for the object.
                    220:  *     Returns:
                    221:  *             KERN_SUCCESS            The object is allocated.
                    222:  *             KERN_INVALID_TASK       The space is dead.
                    223:  *             KERN_NO_SPACE           No room for an entry in the space.
                    224:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    225:  */
                    226: 
                    227: kern_return_t
                    228: ipc_object_alloc(
                    229:        ipc_space_t             space,
                    230:        ipc_object_type_t       otype,
                    231:        mach_port_type_t        type,
                    232:        mach_port_urefs_t       urefs,
                    233:        mach_port_t             *namep,
                    234:        ipc_object_t            *objectp)
                    235: {
                    236:        ipc_object_t object;
                    237:        ipc_entry_t entry;
                    238:        kern_return_t kr;
                    239: 
                    240:        assert(otype < IOT_NUMBER);
                    241:        assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
                    242:        assert(type != MACH_PORT_TYPE_NONE);
                    243:        assert(urefs <= MACH_PORT_UREFS_MAX);
                    244: 
                    245:        object = io_alloc(otype);
                    246:        if (object == IO_NULL)
                    247:                return KERN_RESOURCE_SHORTAGE;
                    248: 
                    249:        if (otype == IOT_PORT) {
                    250:                ipc_port_t port = (ipc_port_t)object;
                    251: 
1.1.1.3 ! root      252:                memset(port, 0, sizeof(*port));
1.1       root      253:        } else if (otype == IOT_PORT_SET) {
                    254:                ipc_pset_t pset = (ipc_pset_t)object;
                    255: 
1.1.1.3 ! root      256:                memset(pset, 0, sizeof(*pset));
1.1       root      257:        }
                    258:        kr = ipc_entry_alloc(space, namep, &entry);
                    259:        if (kr != KERN_SUCCESS) {
                    260:                io_free(otype, object);
                    261:                return kr;
                    262:        }
                    263:        /* space is write-locked */
                    264: 
                    265:        entry->ie_bits |= type | urefs;
                    266:        entry->ie_object = object;
                    267: 
                    268:        io_lock_init(object);
                    269:        io_lock(object);
                    270:        is_write_unlock(space);
                    271: 
                    272:        object->io_references = 1; /* for entry, not caller */
                    273:        object->io_bits = io_makebits(TRUE, otype, 0);
                    274: 
                    275:        *objectp = object;
                    276:        return KERN_SUCCESS;
                    277: }
                    278: 
                    279: /*
                    280:  *     Routine:        ipc_object_alloc_name
                    281:  *     Purpose:
                    282:  *             Allocate an object, with a specific name.
                    283:  *     Conditions:
                    284:  *             Nothing locked.  If successful, the object is returned locked.
                    285:  *             The caller doesn't get a reference for the object.
                    286:  *     Returns:
                    287:  *             KERN_SUCCESS            The object is allocated.
                    288:  *             KERN_INVALID_TASK       The space is dead.
                    289:  *             KERN_NAME_EXISTS        The name already denotes a right.
                    290:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    291:  */
                    292: 
                    293: kern_return_t
                    294: ipc_object_alloc_name(
                    295:        ipc_space_t             space,
                    296:        ipc_object_type_t       otype,
                    297:        mach_port_type_t        type,
                    298:        mach_port_urefs_t       urefs,
                    299:        mach_port_t             name,
                    300:        ipc_object_t            *objectp)
                    301: {
                    302:        ipc_object_t object;
                    303:        ipc_entry_t entry;
                    304:        kern_return_t kr;
                    305: 
                    306:        assert(otype < IOT_NUMBER);
                    307:        assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
                    308:        assert(type != MACH_PORT_TYPE_NONE);
                    309:        assert(urefs <= MACH_PORT_UREFS_MAX);
                    310: 
                    311:        object = io_alloc(otype);
                    312:        if (object == IO_NULL)
                    313:                return KERN_RESOURCE_SHORTAGE;
                    314: 
                    315:        if (otype == IOT_PORT) {
                    316:                ipc_port_t port = (ipc_port_t)object;
                    317: 
1.1.1.3 ! root      318:                memset(port, 0, sizeof(*port));
1.1       root      319:        } else if (otype == IOT_PORT_SET) {
                    320:                ipc_pset_t pset = (ipc_pset_t)object;
                    321: 
1.1.1.3 ! root      322:                memset(pset, 0, sizeof(*pset));
1.1       root      323:        }
                    324: 
                    325:        kr = ipc_entry_alloc_name(space, name, &entry);
                    326:        if (kr != KERN_SUCCESS) {
                    327:                io_free(otype, object);
                    328:                return kr;
                    329:        }
                    330:        /* space is write-locked */
                    331: 
                    332:        if (ipc_right_inuse(space, name, entry)) {
                    333:                io_free(otype, object);
                    334:                return KERN_NAME_EXISTS;
                    335:        }
                    336: 
                    337:        entry->ie_bits |= type | urefs;
                    338:        entry->ie_object = object;
                    339: 
                    340:        io_lock_init(object);
                    341:        io_lock(object);
                    342:        is_write_unlock(space);
                    343: 
                    344:        object->io_references = 1; /* for entry, not caller */
                    345:        object->io_bits = io_makebits(TRUE, otype, 0);
                    346: 
                    347:        *objectp = object;
                    348:        return KERN_SUCCESS;
                    349: }
                    350: 
                    351: /*
                    352:  *     Routine:        ipc_object_copyin_type
                    353:  *     Purpose:
                    354:  *             Convert a send type name to a received type name.
                    355:  */
                    356: 
                    357: mach_msg_type_name_t
                    358: ipc_object_copyin_type(
                    359:        mach_msg_type_name_t    msgt_name)
                    360: {
                    361:        switch (msgt_name) {
                    362:            case 0:
                    363:                return 0;
                    364: 
                    365:            case MACH_MSG_TYPE_MOVE_RECEIVE:
                    366:                return MACH_MSG_TYPE_PORT_RECEIVE;
                    367: 
                    368:            case MACH_MSG_TYPE_MOVE_SEND_ONCE:
                    369:            case MACH_MSG_TYPE_MAKE_SEND_ONCE:
                    370:                return MACH_MSG_TYPE_PORT_SEND_ONCE;
                    371: 
                    372:            case MACH_MSG_TYPE_MOVE_SEND:
                    373:            case MACH_MSG_TYPE_MAKE_SEND:
                    374:            case MACH_MSG_TYPE_COPY_SEND:
                    375:                return MACH_MSG_TYPE_PORT_SEND;
                    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: }
1.1.1.2   root      729: #endif /* 0 */
1.1       root      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_KDB
                    968: #define        printf  kdbprintf
                    969: 
                    970: /*
                    971:  *     Routine:        ipc_object_print
                    972:  *     Purpose:
                    973:  *             Pretty-print an object for kdb.
                    974:  */
                    975: 
                    976: char *ikot_print_array[IKOT_MAX_TYPE] = {
                    977:        "(NONE)             ",
                    978:        "(THREAD)           ",
                    979:        "(TASK)             ",
                    980:        "(HOST)             ",
                    981:        "(HOST_PRIV)        ",
                    982:        "(PROCESSOR)        ",
                    983:        "(PSET)             ",
                    984:        "(PSET_NAME)        ",
                    985:        "(PAGER)            ",
                    986:        "(PAGER_REQUEST)    ",
                    987:        "(DEVICE)           ",  /* 10 */
                    988:        "(XMM_OBJECT)       ",
                    989:        "(XMM_PAGER)        ",
                    990:        "(XMM_KERNEL)       ",
                    991:        "(XMM_REPLY)        ",
                    992:        "(PAGER_TERMINATING)",
                    993:        "(PAGING_NAME)      ",
                    994:        "(HOST_SECURITY)    ",
                    995:        "(LEDGER)           ",
                    996:        "(MASTER_DEVICE)    ",
                    997:        "(ACTIVATION)       ",  /* 20 */
                    998:        "(SUBSYSTEM)        ",
                    999:        "(IO_DONE_QUEUE)    ",
                   1000:        "(SEMAPHORE)        ",
                   1001:        "(LOCK_SET)         ",
                   1002:        "(CLOCK)            ",
                   1003:        "(CLOCK_CTRL)       ",  /* 26 */
                   1004:                                /* << new entries here  */
                   1005:        "(UNKNOWN)     "        /* magic catchall       */
                   1006: };     /* Please keep in sync with kern/ipc_kobject.h  */
                   1007: 
                   1008: void
                   1009: ipc_object_print(
                   1010:        ipc_object_t    object)
                   1011: {
                   1012:        int kotype;
                   1013: 
                   1014:        iprintf("%s", io_active(object) ? "active" : "dead");
                   1015:        printf(", refs=%d", object->io_references);
                   1016:        printf(", otype=%d", io_otype(object));
                   1017:        kotype = io_kotype(object);
                   1018:        if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
                   1019:                printf(", kotype=%d %s\n", io_kotype(object),
                   1020:                       ikot_print_array[kotype]);
                   1021:        else
                   1022:                printf(", kotype=0x%x %s\n", io_kotype(object),
                   1023:                       ikot_print_array[IKOT_UNKNOWN]);
                   1024: }
                   1025: 
                   1026: #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.