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

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 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;
1.1.1.4 ! root      484:                ipc_port_flag_protected_payload_clear(port);
1.1       root      485:                ip_unlock(port);
                    486:                break;
                    487:            }
                    488: 
                    489:            case MACH_MSG_TYPE_COPY_SEND: {
                    490:                ipc_port_t port = (ipc_port_t) object;
                    491: 
                    492:                ip_lock(port);
                    493:                if (ip_active(port)) {
                    494:                        assert(port->ip_srights > 0);
                    495:                        port->ip_srights++;
                    496:                }
                    497:                ip_reference(port);
                    498:                ip_unlock(port);
                    499:                break;
                    500:            }
                    501: 
                    502:            case MACH_MSG_TYPE_MAKE_SEND: {
                    503:                ipc_port_t port = (ipc_port_t) object;
                    504: 
                    505:                ip_lock(port);
                    506:                assert(ip_active(port));
                    507:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    508:                assert(port->ip_receiver == ipc_space_kernel);
                    509: 
                    510:                ip_reference(port);
                    511:                port->ip_mscount++;
                    512:                port->ip_srights++;
                    513:                ip_unlock(port);
                    514:                break;
                    515:            }
                    516: 
                    517:            case MACH_MSG_TYPE_MOVE_SEND:
                    518:                /* move naked send right into the message */
                    519:                break;
                    520: 
                    521:            case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
                    522:                ipc_port_t port = (ipc_port_t) object;
                    523: 
                    524:                ip_lock(port);
                    525:                assert(ip_active(port));
                    526:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    527:                assert(port->ip_receiver == ipc_space_kernel);
                    528: 
                    529:                ip_reference(port);
                    530:                port->ip_sorights++;
                    531:                ip_unlock(port);
                    532:                break;
                    533:            }
                    534: 
                    535:            case MACH_MSG_TYPE_MOVE_SEND_ONCE:
                    536:                /* move naked send-once right into the message */
                    537:                break;
                    538: 
                    539:            default:
                    540: #if MACH_ASSERT
                    541:                assert(!"ipc_object_copyin_from_kernel: strange rights");
                    542: #else
                    543:                panic("ipc_object_copyin_from_kernel: strange rights");
                    544: #endif
                    545:        }
                    546: }
                    547: 
                    548: /*
                    549:  *     Routine:        ipc_object_destroy
                    550:  *     Purpose:
                    551:  *             Destroys a naked capability.
                    552:  *             Consumes a ref for the object.
                    553:  *
                    554:  *             A receive right should be in limbo or in transit.
                    555:  *     Conditions:
                    556:  *             Nothing locked.
                    557:  */
                    558: 
                    559: void
                    560: ipc_object_destroy(
                    561:        ipc_object_t            object,
                    562:        mach_msg_type_name_t    msgt_name)
                    563: {
                    564:        assert(IO_VALID(object));
                    565:        assert(io_otype(object) == IOT_PORT);
                    566: 
                    567:        switch (msgt_name) {
                    568:            case MACH_MSG_TYPE_PORT_SEND:
                    569:                ipc_port_release_send((ipc_port_t) object);
                    570:                break;
                    571: 
                    572:            case MACH_MSG_TYPE_PORT_SEND_ONCE:
                    573:                ipc_notify_send_once((ipc_port_t) object);
                    574:                break;
                    575: 
                    576:            case MACH_MSG_TYPE_PORT_RECEIVE:
                    577:                ipc_port_release_receive((ipc_port_t) object);
                    578:                break;
                    579: 
                    580:            default:
                    581:                panic("ipc_object_destroy: strange rights");
                    582:        }
                    583: }
                    584: 
                    585: /*
                    586:  *     Routine:        ipc_object_copyout
                    587:  *     Purpose:
                    588:  *             Copyout a capability, placing it into a space.
                    589:  *             If successful, consumes a ref for the object.
                    590:  *     Conditions:
                    591:  *             Nothing locked.
                    592:  *     Returns:
                    593:  *             KERN_SUCCESS            Copied out object, consumed ref.
                    594:  *             KERN_INVALID_TASK       The space is dead.
                    595:  *             KERN_INVALID_CAPABILITY The object is dead.
                    596:  *             KERN_NO_SPACE           No room in space for another right.
                    597:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                    598:  *             KERN_UREFS_OVERFLOW     Urefs limit exceeded
                    599:  *                     and overflow wasn't specified.
                    600:  */
                    601: 
                    602: kern_return_t
                    603: ipc_object_copyout(
                    604:        ipc_space_t             space,
                    605:        ipc_object_t            object,
                    606:        mach_msg_type_name_t    msgt_name,
                    607:        boolean_t               overflow,
                    608:        mach_port_t             *namep)
                    609: {
                    610:        mach_port_t name;
                    611:        ipc_entry_t entry;
                    612:        kern_return_t kr;
                    613: 
                    614:        assert(IO_VALID(object));
                    615:        assert(io_otype(object) == IOT_PORT);
                    616: 
                    617:        is_write_lock(space);
                    618: 
                    619:        for (;;) {
                    620:                if (!space->is_active) {
                    621:                        is_write_unlock(space);
                    622:                        return KERN_INVALID_TASK;
                    623:                }
                    624: 
                    625:                if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                    626:                    ipc_right_reverse(space, object, &name, &entry)) {
                    627:                        /* object is locked and active */
                    628: 
                    629:                        assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    630:                        break;
                    631:                }
                    632: 
                    633:                kr = ipc_entry_get(space, &name, &entry);
                    634:                if (kr != KERN_SUCCESS) {
                    635:                        /* unlocks/locks space, so must start again */
                    636: 
                    637:                        kr = ipc_entry_grow_table(space);
                    638:                        if (kr != KERN_SUCCESS)
                    639:                                return kr; /* space is unlocked */
                    640: 
                    641:                        continue;
                    642:                }
                    643: 
                    644:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    645:                assert(entry->ie_object == IO_NULL);
                    646: 
                    647:                io_lock(object);
                    648:                if (!io_active(object)) {
                    649:                        io_unlock(object);
                    650:                        ipc_entry_dealloc(space, name, entry);
                    651:                        is_write_unlock(space);
                    652:                        return KERN_INVALID_CAPABILITY;
                    653:                }
                    654: 
                    655:                entry->ie_object = object;
                    656:                break;
                    657:        }
                    658: 
                    659:        /* space is write-locked and active, object is locked and active */
                    660: 
                    661:        kr = ipc_right_copyout(space, name, entry,
                    662:                               msgt_name, overflow, object);
                    663:        /* object is unlocked */
                    664:        is_write_unlock(space);
                    665: 
                    666:        if (kr == KERN_SUCCESS)
                    667:                *namep = name;
                    668:        return kr;
                    669: }
                    670: 
                    671: #if 0
                    672: /* XXX same, but don't check for already-existing send rights */
                    673: kern_return_t
                    674: ipc_object_copyout_multiname(space, object, namep)
                    675:        ipc_space_t space;
                    676:        ipc_object_t object;
                    677:        mach_port_t *namep;
                    678: {
                    679:        mach_port_t name;
                    680:        ipc_entry_t entry;
                    681:        kern_return_t kr;
                    682: 
                    683:        assert(IO_VALID(object));
                    684:        assert(io_otype(object) == IOT_PORT);
                    685: 
                    686:        is_write_lock(space);
                    687: 
                    688:        for (;;) {
                    689:                if (!space->is_active) {
                    690:                        is_write_unlock(space);
                    691:                        return KERN_INVALID_TASK;
                    692:                }
                    693: 
                    694:                kr = ipc_entry_get(space, &name, &entry);
                    695:                if (kr != KERN_SUCCESS) {
                    696:                        /* unlocks/locks space, so must start again */
                    697: 
                    698:                        kr = ipc_entry_grow_table(space);
                    699:                        if (kr != KERN_SUCCESS)
                    700:                                return kr; /* space is unlocked */
                    701: 
                    702:                        continue;
                    703:                }
                    704: 
                    705:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    706:                assert(entry->ie_object == IO_NULL);
                    707: 
                    708:                io_lock(object);
                    709:                if (!io_active(object)) {
                    710:                        io_unlock(object);
                    711:                        ipc_entry_dealloc(space, name, entry);
                    712:                        is_write_unlock(space);
                    713:                        return KERN_INVALID_CAPABILITY;
                    714:                }
                    715: 
                    716:                entry->ie_object = object;
                    717:                break;
                    718:        }
                    719: 
                    720:        /* space is write-locked and active, object is locked and active */
                    721: 
                    722:        kr = ipc_right_copyout_multiname(space, name, entry, object);
                    723:        /* object is unlocked */
                    724:        is_write_unlock(space);
                    725: 
                    726:        if (kr == KERN_SUCCESS)
                    727:                *namep = name;
                    728:        return kr;
                    729: }
1.1.1.2   root      730: #endif /* 0 */
1.1       root      731: 
                    732: /*
                    733:  *     Routine:        ipc_object_copyout_name
                    734:  *     Purpose:
                    735:  *             Copyout a capability, placing it into a space.
                    736:  *             The specified name is used for the capability.
                    737:  *             If successful, consumes a ref for the object.
                    738:  *     Conditions:
                    739:  *             Nothing locked.
                    740:  *     Returns:
                    741:  *             KERN_SUCCESS            Copied out object, consumed ref.
                    742:  *             KERN_INVALID_TASK       The space is dead.
                    743:  *             KERN_INVALID_CAPABILITY The object is dead.
                    744:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                    745:  *             KERN_UREFS_OVERFLOW     Urefs limit exceeded
                    746:  *                     and overflow wasn't specified.
                    747:  *             KERN_RIGHT_EXISTS       Space has rights under another name.
                    748:  *             KERN_NAME_EXISTS        Name is already used.
                    749:  */
                    750: 
                    751: kern_return_t
                    752: ipc_object_copyout_name(
                    753:        ipc_space_t             space,
                    754:        ipc_object_t            object,
                    755:        mach_msg_type_name_t    msgt_name,
                    756:        boolean_t               overflow,
                    757:        mach_port_t             name)
                    758: {
                    759:        mach_port_t oname;
                    760:        ipc_entry_t oentry;
                    761:        ipc_entry_t entry;
                    762:        kern_return_t kr;
                    763: 
                    764:        assert(IO_VALID(object));
                    765:        assert(io_otype(object) == IOT_PORT);
                    766: 
                    767:        kr = ipc_entry_alloc_name(space, name, &entry);
                    768:        if (kr != KERN_SUCCESS)
                    769:                return kr;
                    770:        /* space is write-locked and active */
                    771: 
                    772:        if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                    773:            ipc_right_reverse(space, object, &oname, &oentry)) {
                    774:                /* object is locked and active */
                    775: 
                    776:                if (name != oname) {
                    777:                        io_unlock(object);
                    778: 
                    779:                        if (IE_BITS_TYPE(entry->ie_bits)
                    780:                                                == MACH_PORT_TYPE_NONE)
                    781:                                ipc_entry_dealloc(space, name, entry);
                    782: 
                    783:                        is_write_unlock(space);
                    784:                        return KERN_RIGHT_EXISTS;
                    785:                }
                    786: 
                    787:                assert(entry == oentry);
                    788:                assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    789:        } else {
                    790:                if (ipc_right_inuse(space, name, entry))
                    791:                        return KERN_NAME_EXISTS;
                    792: 
                    793:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    794:                assert(entry->ie_object == IO_NULL);
                    795: 
                    796:                io_lock(object);
                    797:                if (!io_active(object)) {
                    798:                        io_unlock(object);
                    799:                        ipc_entry_dealloc(space, name, entry);
                    800:                        is_write_unlock(space);
                    801:                        return KERN_INVALID_CAPABILITY;
                    802:                }
                    803: 
                    804:                entry->ie_object = object;
                    805:        }
                    806: 
                    807:        /* space is write-locked and active, object is locked and active */
                    808: 
                    809:        kr = ipc_right_copyout(space, name, entry,
                    810:                               msgt_name, overflow, object);
                    811:        /* object is unlocked */
                    812:        is_write_unlock(space);
                    813:        return kr;
                    814: }
                    815: 
                    816: /*
                    817:  *     Routine:        ipc_object_copyout_dest
                    818:  *     Purpose:
                    819:  *             Translates/consumes the destination right of a message.
                    820:  *             This is unlike normal copyout because the right is consumed
                    821:  *             in a funny way instead of being given to the receiving space.
                    822:  *             The receiver gets his name for the port, if he has receive
                    823:  *             rights, otherwise MACH_PORT_NULL.
                    824:  *     Conditions:
                    825:  *             The object is locked and active.  Nothing else locked.
                    826:  *             The object is unlocked and loses a reference.
                    827:  */
                    828: 
                    829: void
                    830: ipc_object_copyout_dest(
                    831:        ipc_space_t             space,
                    832:        ipc_object_t            object,
                    833:        mach_msg_type_name_t    msgt_name,
                    834:        mach_port_t             *namep)
                    835: {
                    836:        mach_port_t name;
                    837: 
                    838:        assert(IO_VALID(object));
                    839:        assert(io_active(object));
                    840: 
                    841:        io_release(object);
                    842: 
                    843:        /*
                    844:         *      If the space is the receiver/owner of the object,
                    845:         *      then we quietly consume the right and return
                    846:         *      the space's name for the object.  Otherwise
                    847:         *      we destroy the right and return MACH_PORT_NULL.
                    848:         */
                    849: 
                    850:        switch (msgt_name) {
                    851:            case MACH_MSG_TYPE_PORT_SEND: {
                    852:                ipc_port_t port = (ipc_port_t) object;
                    853:                ipc_port_t nsrequest = IP_NULL;
                    854:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
                    855: 
                    856:                assert(port->ip_srights > 0);
                    857:                if (--port->ip_srights == 0) {
                    858:                        nsrequest = port->ip_nsrequest;
                    859:                        if (nsrequest != IP_NULL) {
                    860:                                port->ip_nsrequest = IP_NULL;
                    861:                                mscount = port->ip_mscount;
                    862:                        }
                    863:                }
                    864: 
                    865:                if (port->ip_receiver == space)
                    866:                        name = port->ip_receiver_name;
                    867:                else
                    868:                        name = MACH_PORT_NULL;
                    869: 
                    870:                ip_unlock(port);
                    871: 
                    872:                if (nsrequest != IP_NULL)
                    873:                        ipc_notify_no_senders(nsrequest, mscount);
                    874: 
                    875:                break;
                    876:            }
                    877: 
                    878:            case MACH_MSG_TYPE_PORT_SEND_ONCE: {
                    879:                ipc_port_t port = (ipc_port_t) object;
                    880: 
                    881:                assert(port->ip_sorights > 0);
                    882: 
                    883:                if (port->ip_receiver == space) {
                    884:                        /* quietly consume the send-once right */
                    885: 
                    886:                        port->ip_sorights--;
                    887:                        name = port->ip_receiver_name;
                    888:                        ip_unlock(port);
                    889:                } else {
                    890:                        /*
                    891:                         *      A very bizarre case.  The message
                    892:                         *      was received, but before this copyout
                    893:                         *      happened the space lost receive rights.
                    894:                         *      We can't quietly consume the soright
                    895:                         *      out from underneath some other task,
                    896:                         *      so generate a send-once notification.
                    897:                         */
                    898: 
                    899:                        ip_reference(port); /* restore ref */
                    900:                        ip_unlock(port);
                    901: 
                    902:                        ipc_notify_send_once(port);
                    903:                        name = MACH_PORT_NULL;
                    904:                }
                    905: 
                    906:                break;
                    907:            }
                    908: 
                    909:            default:
                    910: #if MACH_ASSERT
                    911:                assert(!"ipc_object_copyout_dest: strange rights");
                    912: #else
                    913:                panic("ipc_object_copyout_dest: strange rights");
                    914: #endif
                    915: 
                    916:        }
                    917: 
                    918:        *namep = name;
                    919: }
                    920: 
                    921: /*
                    922:  *     Routine:        ipc_object_rename
                    923:  *     Purpose:
                    924:  *             Rename an entry in a space.
                    925:  *     Conditions:
                    926:  *             Nothing locked.
                    927:  *     Returns:
                    928:  *             KERN_SUCCESS            Renamed the entry.
                    929:  *             KERN_INVALID_TASK       The space was dead.
                    930:  *             KERN_INVALID_NAME       oname didn't denote an entry.
                    931:  *             KERN_NAME_EXISTS        nname already denoted an entry.
                    932:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate new entry.
                    933:  */
                    934: 
                    935: kern_return_t
                    936: ipc_object_rename(
                    937:        ipc_space_t     space,
                    938:        mach_port_t     oname,
                    939:        mach_port_t     nname)
                    940: {
                    941:        ipc_entry_t oentry, nentry;
                    942:        kern_return_t kr;
                    943: 
                    944:        kr = ipc_entry_alloc_name(space, nname, &nentry);
                    945:        if (kr != KERN_SUCCESS)
                    946:                return kr;
                    947:        /* space is write-locked and active */
                    948: 
                    949:        if (ipc_right_inuse(space, nname, nentry)) {
                    950:                /* space is unlocked */
                    951:                return KERN_NAME_EXISTS;
                    952:        }
                    953: 
                    954:        /* don't let ipc_entry_lookup see the uninitialized new entry */
                    955: 
                    956:        if ((oname == nname) ||
                    957:            ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
                    958:                ipc_entry_dealloc(space, nname, nentry);
                    959:                is_write_unlock(space);
                    960:                return KERN_INVALID_NAME;
                    961:        }
                    962: 
                    963:        kr = ipc_right_rename(space, oname, oentry, nname, nentry);
                    964:        /* space is unlocked */
                    965:        return kr;
                    966: }
                    967: 
                    968: #if    MACH_KDB
                    969: #define        printf  kdbprintf
                    970: 
                    971: /*
                    972:  *     Routine:        ipc_object_print
                    973:  *     Purpose:
                    974:  *             Pretty-print an object for kdb.
                    975:  */
                    976: 
                    977: char *ikot_print_array[IKOT_MAX_TYPE] = {
                    978:        "(NONE)             ",
                    979:        "(THREAD)           ",
                    980:        "(TASK)             ",
                    981:        "(HOST)             ",
                    982:        "(HOST_PRIV)        ",
                    983:        "(PROCESSOR)        ",
                    984:        "(PSET)             ",
                    985:        "(PSET_NAME)        ",
                    986:        "(PAGER)            ",
                    987:        "(PAGER_REQUEST)    ",
                    988:        "(DEVICE)           ",  /* 10 */
                    989:        "(XMM_OBJECT)       ",
                    990:        "(XMM_PAGER)        ",
                    991:        "(XMM_KERNEL)       ",
                    992:        "(XMM_REPLY)        ",
                    993:        "(PAGER_TERMINATING)",
                    994:        "(PAGING_NAME)      ",
                    995:        "(HOST_SECURITY)    ",
                    996:        "(LEDGER)           ",
                    997:        "(MASTER_DEVICE)    ",
                    998:        "(ACTIVATION)       ",  /* 20 */
                    999:        "(SUBSYSTEM)        ",
                   1000:        "(IO_DONE_QUEUE)    ",
                   1001:        "(SEMAPHORE)        ",
                   1002:        "(LOCK_SET)         ",
                   1003:        "(CLOCK)            ",
                   1004:        "(CLOCK_CTRL)       ",  /* 26 */
                   1005:                                /* << new entries here  */
                   1006:        "(UNKNOWN)     "        /* magic catchall       */
                   1007: };     /* Please keep in sync with kern/ipc_kobject.h  */
                   1008: 
                   1009: void
                   1010: ipc_object_print(
1.1.1.4 ! root     1011:        const ipc_object_t object)
1.1       root     1012: {
                   1013:        int kotype;
                   1014: 
                   1015:        iprintf("%s", io_active(object) ? "active" : "dead");
                   1016:        printf(", refs=%d", object->io_references);
                   1017:        printf(", otype=%d", io_otype(object));
                   1018:        kotype = io_kotype(object);
                   1019:        if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
                   1020:                printf(", kotype=%d %s\n", io_kotype(object),
                   1021:                       ikot_print_array[kotype]);
                   1022:        else
                   1023:                printf(", kotype=0x%x %s\n", io_kotype(object),
                   1024:                       ikot_print_array[IKOT_UNKNOWN]);
                   1025: }
                   1026: 
                   1027: #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.