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

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_right.h>
                     45: #include <ipc/ipc_notify.h>
                     46: #include <ipc/ipc_pset.h>
1.1.1.3   root       47: #include <kern/debug.h>
                     48: #include <kern/printf.h>
                     49: #include <kern/slab.h>
1.1       root       50: 
1.1.1.3   root       51: #if    MACH_KDB
                     52: #include <ddb/db_output.h>
                     53: #endif /* MACH_KDB */
                     54: 
                     55: 
                     56: struct kmem_cache ipc_object_caches[IOT_NUMBER];
1.1       root       57: 
                     58: 
                     59: 
                     60: /*
                     61:  *     Routine:        ipc_object_reference
                     62:  *     Purpose:
                     63:  *             Take a reference to an object.
                     64:  */
                     65: 
                     66: void
                     67: ipc_object_reference(
                     68:        ipc_object_t    object)
                     69: {
                     70:        io_lock(object);
                     71:        assert(object->io_references > 0);
                     72:        io_reference(object);
                     73:        io_unlock(object);
                     74: }
                     75: 
                     76: /*
                     77:  *     Routine:        ipc_object_release
                     78:  *     Purpose:
                     79:  *             Release a reference to an object.
                     80:  */
                     81: 
                     82: void
                     83: ipc_object_release(
                     84:        ipc_object_t    object)
                     85: {
                     86:        io_lock(object);
                     87:        assert(object->io_references > 0);
                     88:        io_release(object);
                     89:        io_check_unlock(object);
                     90: }
                     91: 
                     92: /*
                     93:  *     Routine:        ipc_object_translate
                     94:  *     Purpose:
                     95:  *             Look up an object in a space.
                     96:  *     Conditions:
                     97:  *             Nothing locked before.  If successful, the object
                     98:  *             is returned locked.  The caller doesn't get a ref.
                     99:  *     Returns:
                    100:  *             KERN_SUCCESS            Objected returned locked.
                    101:  *             KERN_INVALID_TASK       The space is dead.
                    102:  *             KERN_INVALID_NAME       The name doesn't denote a right.
                    103:  *             KERN_INVALID_RIGHT      Name doesn't denote the correct right.
                    104:  */
                    105: 
                    106: kern_return_t
                    107: ipc_object_translate(
                    108:        ipc_space_t             space,
                    109:        mach_port_t             name,
                    110:        mach_port_right_t       right,
                    111:        ipc_object_t            *objectp)
                    112: {
                    113:        ipc_entry_t entry;
                    114:        ipc_object_t object;
                    115:        kern_return_t kr;
                    116: 
                    117:        kr = ipc_right_lookup_read(space, name, &entry);
                    118:        if (kr != KERN_SUCCESS)
                    119:                return kr;
                    120:        /* space is read-locked and active */
                    121: 
                    122:        if ((entry->ie_bits & MACH_PORT_TYPE(right)) == (mach_port_right_t) 0) {
                    123:                is_read_unlock(space);
                    124:                return KERN_INVALID_RIGHT;
                    125:        }
                    126: 
                    127:        object = entry->ie_object;
                    128:        assert(object != IO_NULL);
                    129: 
                    130:        io_lock(object);
                    131:        is_read_unlock(space);
                    132: 
                    133:        *objectp = object;
                    134:        return KERN_SUCCESS;
                    135: }
                    136: 
                    137: /*
                    138:  *     Routine:        ipc_object_alloc_dead
                    139:  *     Purpose:
                    140:  *             Allocate a dead-name entry.
                    141:  *     Conditions:
                    142:  *             Nothing locked.
                    143:  *     Returns:
                    144:  *             KERN_SUCCESS            The dead name is allocated.
                    145:  *             KERN_INVALID_TASK       The space is dead.
                    146:  *             KERN_NO_SPACE           No room for an entry in the space.
                    147:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    148:  */
                    149: 
                    150: kern_return_t
                    151: ipc_object_alloc_dead(
                    152:        ipc_space_t     space,
                    153:        mach_port_t     *namep)
                    154: {
                    155:        ipc_entry_t entry;
                    156:        kern_return_t kr;
                    157: 
1.1.1.5   root      158:        is_write_lock(space);
1.1       root      159:        kr = ipc_entry_alloc(space, namep, &entry);
1.1.1.5   root      160:        if (kr != KERN_SUCCESS) {
                    161:                is_write_unlock(space);
1.1       root      162:                return kr;
1.1.1.5   root      163:        }
1.1       root      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: 
1.1.1.5   root      195:        is_write_lock(space);
1.1       root      196:        kr = ipc_entry_alloc_name(space, name, &entry);
1.1.1.5   root      197:        if (kr != KERN_SUCCESS) {
                    198:                is_write_unlock(space);
1.1       root      199:                return kr;
1.1.1.5   root      200:        }
1.1       root      201: 
                    202:        if (ipc_right_inuse(space, name, entry))
                    203:                return KERN_NAME_EXISTS;
                    204: 
                    205:        /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
                    206: 
                    207:        assert(entry->ie_object == IO_NULL);
                    208:        entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
                    209: 
                    210:        is_write_unlock(space);
                    211:        return KERN_SUCCESS;
                    212: }
                    213: 
                    214: /*
                    215:  *     Routine:        ipc_object_alloc
                    216:  *     Purpose:
                    217:  *             Allocate an object.
                    218:  *     Conditions:
                    219:  *             Nothing locked.  If successful, the object is returned locked.
                    220:  *             The caller doesn't get a reference for the object.
                    221:  *     Returns:
                    222:  *             KERN_SUCCESS            The object is allocated.
                    223:  *             KERN_INVALID_TASK       The space is dead.
                    224:  *             KERN_NO_SPACE           No room for an entry in the space.
                    225:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    226:  */
                    227: 
                    228: kern_return_t
                    229: ipc_object_alloc(
                    230:        ipc_space_t             space,
                    231:        ipc_object_type_t       otype,
                    232:        mach_port_type_t        type,
                    233:        mach_port_urefs_t       urefs,
                    234:        mach_port_t             *namep,
                    235:        ipc_object_t            *objectp)
                    236: {
                    237:        ipc_object_t object;
                    238:        ipc_entry_t entry;
                    239:        kern_return_t kr;
                    240: 
                    241:        assert(otype < IOT_NUMBER);
                    242:        assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
                    243:        assert(type != MACH_PORT_TYPE_NONE);
                    244:        assert(urefs <= MACH_PORT_UREFS_MAX);
                    245: 
                    246:        object = io_alloc(otype);
                    247:        if (object == IO_NULL)
                    248:                return KERN_RESOURCE_SHORTAGE;
                    249: 
                    250:        if (otype == IOT_PORT) {
                    251:                ipc_port_t port = (ipc_port_t)object;
                    252: 
1.1.1.3   root      253:                memset(port, 0, sizeof(*port));
1.1       root      254:        } else if (otype == IOT_PORT_SET) {
                    255:                ipc_pset_t pset = (ipc_pset_t)object;
                    256: 
1.1.1.3   root      257:                memset(pset, 0, sizeof(*pset));
1.1       root      258:        }
1.1.1.5   root      259:        is_write_lock(space);
1.1       root      260:        kr = ipc_entry_alloc(space, namep, &entry);
                    261:        if (kr != KERN_SUCCESS) {
1.1.1.5   root      262:                is_write_unlock(space);
1.1       root      263:                io_free(otype, object);
                    264:                return kr;
                    265:        }
                    266: 
                    267:        entry->ie_bits |= type | urefs;
                    268:        entry->ie_object = object;
                    269: 
                    270:        io_lock_init(object);
                    271:        io_lock(object);
                    272:        is_write_unlock(space);
                    273: 
                    274:        object->io_references = 1; /* for entry, not caller */
                    275:        object->io_bits = io_makebits(TRUE, otype, 0);
                    276: 
                    277:        *objectp = object;
                    278:        return KERN_SUCCESS;
                    279: }
                    280: 
                    281: /*
                    282:  *     Routine:        ipc_object_alloc_name
                    283:  *     Purpose:
                    284:  *             Allocate an object, with a specific name.
                    285:  *     Conditions:
                    286:  *             Nothing locked.  If successful, the object is returned locked.
                    287:  *             The caller doesn't get a reference for the object.
                    288:  *     Returns:
                    289:  *             KERN_SUCCESS            The object is allocated.
                    290:  *             KERN_INVALID_TASK       The space is dead.
                    291:  *             KERN_NAME_EXISTS        The name already denotes a right.
                    292:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    293:  */
                    294: 
                    295: kern_return_t
                    296: ipc_object_alloc_name(
                    297:        ipc_space_t             space,
                    298:        ipc_object_type_t       otype,
                    299:        mach_port_type_t        type,
                    300:        mach_port_urefs_t       urefs,
                    301:        mach_port_t             name,
                    302:        ipc_object_t            *objectp)
                    303: {
                    304:        ipc_object_t object;
                    305:        ipc_entry_t entry;
                    306:        kern_return_t kr;
                    307: 
                    308:        assert(otype < IOT_NUMBER);
                    309:        assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
                    310:        assert(type != MACH_PORT_TYPE_NONE);
                    311:        assert(urefs <= MACH_PORT_UREFS_MAX);
                    312: 
                    313:        object = io_alloc(otype);
                    314:        if (object == IO_NULL)
                    315:                return KERN_RESOURCE_SHORTAGE;
                    316: 
                    317:        if (otype == IOT_PORT) {
                    318:                ipc_port_t port = (ipc_port_t)object;
                    319: 
1.1.1.3   root      320:                memset(port, 0, sizeof(*port));
1.1       root      321:        } else if (otype == IOT_PORT_SET) {
                    322:                ipc_pset_t pset = (ipc_pset_t)object;
                    323: 
1.1.1.3   root      324:                memset(pset, 0, sizeof(*pset));
1.1       root      325:        }
                    326: 
1.1.1.5   root      327:        is_write_lock(space);
1.1       root      328:        kr = ipc_entry_alloc_name(space, name, &entry);
                    329:        if (kr != KERN_SUCCESS) {
1.1.1.5   root      330:                is_write_unlock(space);
1.1       root      331:                io_free(otype, object);
                    332:                return kr;
                    333:        }
                    334: 
                    335:        if (ipc_right_inuse(space, name, entry)) {
                    336:                io_free(otype, object);
                    337:                return KERN_NAME_EXISTS;
                    338:        }
                    339: 
                    340:        entry->ie_bits |= type | urefs;
                    341:        entry->ie_object = object;
                    342: 
                    343:        io_lock_init(object);
                    344:        io_lock(object);
                    345:        is_write_unlock(space);
                    346: 
                    347:        object->io_references = 1; /* for entry, not caller */
                    348:        object->io_bits = io_makebits(TRUE, otype, 0);
                    349: 
                    350:        *objectp = object;
                    351:        return KERN_SUCCESS;
                    352: }
                    353: 
                    354: /*
                    355:  *     Routine:        ipc_object_copyin_type
                    356:  *     Purpose:
                    357:  *             Convert a send type name to a received type name.
                    358:  */
                    359: 
                    360: mach_msg_type_name_t
                    361: ipc_object_copyin_type(
                    362:        mach_msg_type_name_t    msgt_name)
                    363: {
                    364:        switch (msgt_name) {
                    365:            case 0:
                    366:                return 0;
                    367: 
                    368:            case MACH_MSG_TYPE_MOVE_RECEIVE:
                    369:                return MACH_MSG_TYPE_PORT_RECEIVE;
                    370: 
                    371:            case MACH_MSG_TYPE_MOVE_SEND_ONCE:
                    372:            case MACH_MSG_TYPE_MAKE_SEND_ONCE:
                    373:                return MACH_MSG_TYPE_PORT_SEND_ONCE;
                    374: 
                    375:            case MACH_MSG_TYPE_MOVE_SEND:
                    376:            case MACH_MSG_TYPE_MAKE_SEND:
                    377:            case MACH_MSG_TYPE_COPY_SEND:
                    378:                return MACH_MSG_TYPE_PORT_SEND;
                    379: 
                    380:            default:
                    381: #if MACH_ASSERT
                    382:                assert(!"ipc_object_copyin_type: strange rights");
                    383: #else
                    384:                panic("ipc_object_copyin_type: strange rights");
                    385: #endif
                    386:                return 0; /* in case assert/panic returns */
                    387:        }
                    388: }
                    389: 
                    390: /*
                    391:  *     Routine:        ipc_object_copyin
                    392:  *     Purpose:
                    393:  *             Copyin a capability from a space.
                    394:  *             If successful, the caller gets a ref
                    395:  *             for the resulting object, unless it is IO_DEAD.
                    396:  *     Conditions:
                    397:  *             Nothing locked.
                    398:  *     Returns:
                    399:  *             KERN_SUCCESS            Acquired an object, possibly IO_DEAD.
                    400:  *             KERN_INVALID_TASK       The space is dead.
                    401:  *             KERN_INVALID_NAME       Name doesn't exist in space.
                    402:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
                    403:  */
                    404: 
                    405: kern_return_t
                    406: ipc_object_copyin(
                    407:        ipc_space_t             space,
                    408:        mach_port_t             name,
                    409:        mach_msg_type_name_t    msgt_name,
                    410:        ipc_object_t            *objectp)
                    411: {
                    412:        ipc_entry_t entry;
                    413:        ipc_port_t soright;
                    414:        kern_return_t kr;
                    415: 
                    416:        /*
                    417:         *      Could first try a read lock when doing
                    418:         *      MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
                    419:         *      and MACH_MSG_TYPE_MAKE_SEND_ONCE.
                    420:         */
                    421: 
                    422:        kr = ipc_right_lookup_write(space, name, &entry);
                    423:        if (kr != KERN_SUCCESS)
                    424:                return kr;
                    425:        /* space is write-locked and active */
                    426: 
                    427:        kr = ipc_right_copyin(space, name, entry,
                    428:                              msgt_name, TRUE,
                    429:                              objectp, &soright);
                    430:        if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
                    431:                ipc_entry_dealloc(space, name, entry);
                    432:        is_write_unlock(space);
                    433: 
                    434:        if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
                    435:                ipc_notify_port_deleted(soright, name);
                    436: 
                    437:        return kr;
                    438: }
                    439: 
                    440: /*
                    441:  *     Routine:        ipc_object_copyin_from_kernel
                    442:  *     Purpose:
                    443:  *             Copyin a naked capability from the kernel.
                    444:  *
                    445:  *             MACH_MSG_TYPE_MOVE_RECEIVE
                    446:  *                     The receiver must be ipc_space_kernel.
                    447:  *                     Consumes the naked receive right.
                    448:  *             MACH_MSG_TYPE_COPY_SEND
                    449:  *                     A naked send right must be supplied.
                    450:  *                     The port gains a reference, and a send right
                    451:  *                     if the port is still active.
                    452:  *             MACH_MSG_TYPE_MAKE_SEND
                    453:  *                     The receiver must be ipc_space_kernel.
                    454:  *                     The port gains a reference and a send right.
                    455:  *             MACH_MSG_TYPE_MOVE_SEND
                    456:  *                     Consumes a naked send right.
                    457:  *             MACH_MSG_TYPE_MAKE_SEND_ONCE
                    458:  *                     The receiver must be ipc_space_kernel.
                    459:  *                     The port gains a reference and a send-once right.
                    460:  *             MACH_MSG_TYPE_MOVE_SEND_ONCE
                    461:  *                     Consumes a naked send-once right.
                    462:  *     Conditions:
                    463:  *             Nothing locked.
                    464:  */
                    465: 
                    466: void
                    467: ipc_object_copyin_from_kernel(
                    468:        ipc_object_t            object,
                    469:        mach_msg_type_name_t    msgt_name)
                    470: {
                    471:        assert(IO_VALID(object));
                    472: 
                    473:        switch (msgt_name) {
                    474:            case MACH_MSG_TYPE_MOVE_RECEIVE: {
                    475:                ipc_port_t port = (ipc_port_t) object;
                    476: 
                    477:                ip_lock(port);
                    478:                assert(ip_active(port));
                    479:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    480:                assert(port->ip_receiver == ipc_space_kernel);
                    481: 
                    482:                /* relevant part of ipc_port_clear_receiver */
                    483:                ipc_port_set_mscount(port, 0);
                    484: 
                    485:                port->ip_receiver_name = MACH_PORT_NULL;
                    486:                port->ip_destination = IP_NULL;
1.1.1.4   root      487:                ipc_port_flag_protected_payload_clear(port);
1.1       root      488:                ip_unlock(port);
                    489:                break;
                    490:            }
                    491: 
                    492:            case MACH_MSG_TYPE_COPY_SEND: {
                    493:                ipc_port_t port = (ipc_port_t) object;
                    494: 
                    495:                ip_lock(port);
                    496:                if (ip_active(port)) {
                    497:                        assert(port->ip_srights > 0);
                    498:                        port->ip_srights++;
                    499:                }
                    500:                ip_reference(port);
                    501:                ip_unlock(port);
                    502:                break;
                    503:            }
                    504: 
                    505:            case MACH_MSG_TYPE_MAKE_SEND: {
                    506:                ipc_port_t port = (ipc_port_t) object;
                    507: 
                    508:                ip_lock(port);
                    509:                assert(ip_active(port));
                    510:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    511:                assert(port->ip_receiver == ipc_space_kernel);
                    512: 
                    513:                ip_reference(port);
                    514:                port->ip_mscount++;
                    515:                port->ip_srights++;
                    516:                ip_unlock(port);
                    517:                break;
                    518:            }
                    519: 
                    520:            case MACH_MSG_TYPE_MOVE_SEND:
                    521:                /* move naked send right into the message */
                    522:                break;
                    523: 
                    524:            case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
                    525:                ipc_port_t port = (ipc_port_t) object;
                    526: 
                    527:                ip_lock(port);
                    528:                assert(ip_active(port));
                    529:                assert(port->ip_receiver_name != MACH_PORT_NULL);
                    530:                assert(port->ip_receiver == ipc_space_kernel);
                    531: 
                    532:                ip_reference(port);
                    533:                port->ip_sorights++;
                    534:                ip_unlock(port);
                    535:                break;
                    536:            }
                    537: 
                    538:            case MACH_MSG_TYPE_MOVE_SEND_ONCE:
                    539:                /* move naked send-once right into the message */
                    540:                break;
                    541: 
                    542:            default:
                    543: #if MACH_ASSERT
                    544:                assert(!"ipc_object_copyin_from_kernel: strange rights");
                    545: #else
                    546:                panic("ipc_object_copyin_from_kernel: strange rights");
                    547: #endif
                    548:        }
                    549: }
                    550: 
                    551: /*
                    552:  *     Routine:        ipc_object_destroy
                    553:  *     Purpose:
                    554:  *             Destroys a naked capability.
                    555:  *             Consumes a ref for the object.
                    556:  *
                    557:  *             A receive right should be in limbo or in transit.
                    558:  *     Conditions:
                    559:  *             Nothing locked.
                    560:  */
                    561: 
                    562: void
                    563: ipc_object_destroy(
                    564:        ipc_object_t            object,
                    565:        mach_msg_type_name_t    msgt_name)
                    566: {
                    567:        assert(IO_VALID(object));
                    568:        assert(io_otype(object) == IOT_PORT);
                    569: 
                    570:        switch (msgt_name) {
                    571:            case MACH_MSG_TYPE_PORT_SEND:
                    572:                ipc_port_release_send((ipc_port_t) object);
                    573:                break;
                    574: 
                    575:            case MACH_MSG_TYPE_PORT_SEND_ONCE:
                    576:                ipc_notify_send_once((ipc_port_t) object);
                    577:                break;
                    578: 
                    579:            case MACH_MSG_TYPE_PORT_RECEIVE:
                    580:                ipc_port_release_receive((ipc_port_t) object);
                    581:                break;
                    582: 
                    583:            default:
                    584:                panic("ipc_object_destroy: strange rights");
                    585:        }
                    586: }
                    587: 
                    588: /*
                    589:  *     Routine:        ipc_object_copyout
                    590:  *     Purpose:
                    591:  *             Copyout a capability, placing it into a space.
                    592:  *             If successful, consumes a ref for the object.
                    593:  *     Conditions:
                    594:  *             Nothing locked.
                    595:  *     Returns:
                    596:  *             KERN_SUCCESS            Copied out object, consumed ref.
                    597:  *             KERN_INVALID_TASK       The space is dead.
                    598:  *             KERN_INVALID_CAPABILITY The object is dead.
                    599:  *             KERN_NO_SPACE           No room in space for another right.
                    600:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                    601:  *             KERN_UREFS_OVERFLOW     Urefs limit exceeded
                    602:  *                     and overflow wasn't specified.
                    603:  */
                    604: 
                    605: kern_return_t
                    606: ipc_object_copyout(
                    607:        ipc_space_t             space,
                    608:        ipc_object_t            object,
                    609:        mach_msg_type_name_t    msgt_name,
                    610:        boolean_t               overflow,
                    611:        mach_port_t             *namep)
                    612: {
                    613:        mach_port_t name;
                    614:        ipc_entry_t entry;
                    615:        kern_return_t kr;
                    616: 
                    617:        assert(IO_VALID(object));
                    618:        assert(io_otype(object) == IOT_PORT);
                    619: 
                    620:        is_write_lock(space);
                    621: 
                    622:        for (;;) {
                    623:                if (!space->is_active) {
                    624:                        is_write_unlock(space);
                    625:                        return KERN_INVALID_TASK;
                    626:                }
                    627: 
                    628:                if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                    629:                    ipc_right_reverse(space, object, &name, &entry)) {
                    630:                        /* object is locked and active */
                    631: 
                    632:                        assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    633:                        break;
                    634:                }
                    635: 
1.1.1.5   root      636:                kr = ipc_entry_alloc(space, &name, &entry);
1.1       root      637:                if (kr != KERN_SUCCESS) {
1.1.1.5   root      638:                        is_write_unlock(space);
                    639:                        return kr;
1.1       root      640:                }
                    641: 
                    642:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    643:                assert(entry->ie_object == IO_NULL);
                    644: 
                    645:                io_lock(object);
                    646:                if (!io_active(object)) {
                    647:                        io_unlock(object);
                    648:                        ipc_entry_dealloc(space, name, entry);
                    649:                        is_write_unlock(space);
                    650:                        return KERN_INVALID_CAPABILITY;
                    651:                }
                    652: 
                    653:                entry->ie_object = object;
                    654:                break;
                    655:        }
                    656: 
                    657:        /* space is write-locked and active, object is locked and active */
                    658: 
                    659:        kr = ipc_right_copyout(space, name, entry,
                    660:                               msgt_name, overflow, object);
                    661:        /* object is unlocked */
                    662:        is_write_unlock(space);
                    663: 
                    664:        if (kr == KERN_SUCCESS)
                    665:                *namep = name;
                    666:        return kr;
                    667: }
                    668: 
                    669: #if 0
                    670: /* XXX same, but don't check for already-existing send rights */
                    671: kern_return_t
                    672: ipc_object_copyout_multiname(space, object, namep)
                    673:        ipc_space_t space;
                    674:        ipc_object_t object;
                    675:        mach_port_t *namep;
                    676: {
                    677:        mach_port_t name;
                    678:        ipc_entry_t entry;
                    679:        kern_return_t kr;
                    680: 
                    681:        assert(IO_VALID(object));
                    682:        assert(io_otype(object) == IOT_PORT);
                    683: 
                    684:        is_write_lock(space);
                    685: 
                    686:        for (;;) {
                    687:                if (!space->is_active) {
                    688:                        is_write_unlock(space);
                    689:                        return KERN_INVALID_TASK;
                    690:                }
                    691: 
1.1.1.5   root      692:                kr = ipc_entry_alloc(space, &name, &entry);
1.1       root      693:                if (kr != KERN_SUCCESS) {
1.1.1.5   root      694:                        is_write_unlock(space);
                    695:                        return kr; /* space is unlocked */
1.1       root      696:                }
                    697: 
                    698:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    699:                assert(entry->ie_object == IO_NULL);
                    700: 
                    701:                io_lock(object);
                    702:                if (!io_active(object)) {
                    703:                        io_unlock(object);
                    704:                        ipc_entry_dealloc(space, name, entry);
                    705:                        is_write_unlock(space);
                    706:                        return KERN_INVALID_CAPABILITY;
                    707:                }
                    708: 
                    709:                entry->ie_object = object;
                    710:                break;
                    711:        }
                    712: 
                    713:        /* space is write-locked and active, object is locked and active */
                    714: 
                    715:        kr = ipc_right_copyout_multiname(space, name, entry, object);
                    716:        /* object is unlocked */
                    717:        is_write_unlock(space);
                    718: 
                    719:        if (kr == KERN_SUCCESS)
                    720:                *namep = name;
                    721:        return kr;
                    722: }
1.1.1.2   root      723: #endif /* 0 */
1.1       root      724: 
                    725: /*
                    726:  *     Routine:        ipc_object_copyout_name
                    727:  *     Purpose:
                    728:  *             Copyout a capability, placing it into a space.
                    729:  *             The specified name is used for the capability.
                    730:  *             If successful, consumes a ref for the object.
                    731:  *     Conditions:
                    732:  *             Nothing locked.
                    733:  *     Returns:
                    734:  *             KERN_SUCCESS            Copied out object, consumed ref.
                    735:  *             KERN_INVALID_TASK       The space is dead.
                    736:  *             KERN_INVALID_CAPABILITY The object is dead.
                    737:  *             KERN_RESOURCE_SHORTAGE  No memory available.
                    738:  *             KERN_UREFS_OVERFLOW     Urefs limit exceeded
                    739:  *                     and overflow wasn't specified.
                    740:  *             KERN_RIGHT_EXISTS       Space has rights under another name.
                    741:  *             KERN_NAME_EXISTS        Name is already used.
                    742:  */
                    743: 
                    744: kern_return_t
                    745: ipc_object_copyout_name(
                    746:        ipc_space_t             space,
                    747:        ipc_object_t            object,
                    748:        mach_msg_type_name_t    msgt_name,
                    749:        boolean_t               overflow,
                    750:        mach_port_t             name)
                    751: {
                    752:        mach_port_t oname;
                    753:        ipc_entry_t oentry;
                    754:        ipc_entry_t entry;
                    755:        kern_return_t kr;
                    756: 
                    757:        assert(IO_VALID(object));
                    758:        assert(io_otype(object) == IOT_PORT);
                    759: 
1.1.1.5   root      760:        is_write_lock(space);
1.1       root      761:        kr = ipc_entry_alloc_name(space, name, &entry);
1.1.1.5   root      762:        if (kr != KERN_SUCCESS) {
                    763:                is_write_unlock(space);
1.1       root      764:                return kr;
1.1.1.5   root      765:        }
1.1       root      766: 
                    767:        if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
                    768:            ipc_right_reverse(space, object, &oname, &oentry)) {
                    769:                /* object is locked and active */
                    770: 
                    771:                if (name != oname) {
                    772:                        io_unlock(object);
                    773: 
                    774:                        if (IE_BITS_TYPE(entry->ie_bits)
                    775:                                                == MACH_PORT_TYPE_NONE)
                    776:                                ipc_entry_dealloc(space, name, entry);
                    777: 
                    778:                        is_write_unlock(space);
                    779:                        return KERN_RIGHT_EXISTS;
                    780:                }
                    781: 
                    782:                assert(entry == oentry);
                    783:                assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    784:        } else {
                    785:                if (ipc_right_inuse(space, name, entry))
                    786:                        return KERN_NAME_EXISTS;
                    787: 
                    788:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
                    789:                assert(entry->ie_object == IO_NULL);
                    790: 
                    791:                io_lock(object);
                    792:                if (!io_active(object)) {
                    793:                        io_unlock(object);
                    794:                        ipc_entry_dealloc(space, name, entry);
                    795:                        is_write_unlock(space);
                    796:                        return KERN_INVALID_CAPABILITY;
                    797:                }
                    798: 
                    799:                entry->ie_object = object;
                    800:        }
                    801: 
                    802:        /* space is write-locked and active, object is locked and active */
                    803: 
                    804:        kr = ipc_right_copyout(space, name, entry,
                    805:                               msgt_name, overflow, object);
                    806:        /* object is unlocked */
                    807:        is_write_unlock(space);
                    808:        return kr;
                    809: }
                    810: 
                    811: /*
                    812:  *     Routine:        ipc_object_copyout_dest
                    813:  *     Purpose:
                    814:  *             Translates/consumes the destination right of a message.
                    815:  *             This is unlike normal copyout because the right is consumed
                    816:  *             in a funny way instead of being given to the receiving space.
                    817:  *             The receiver gets his name for the port, if he has receive
                    818:  *             rights, otherwise MACH_PORT_NULL.
                    819:  *     Conditions:
                    820:  *             The object is locked and active.  Nothing else locked.
                    821:  *             The object is unlocked and loses a reference.
                    822:  */
                    823: 
                    824: void
                    825: ipc_object_copyout_dest(
                    826:        ipc_space_t             space,
                    827:        ipc_object_t            object,
                    828:        mach_msg_type_name_t    msgt_name,
                    829:        mach_port_t             *namep)
                    830: {
                    831:        mach_port_t name;
                    832: 
                    833:        assert(IO_VALID(object));
                    834:        assert(io_active(object));
                    835: 
                    836:        io_release(object);
                    837: 
                    838:        /*
                    839:         *      If the space is the receiver/owner of the object,
                    840:         *      then we quietly consume the right and return
                    841:         *      the space's name for the object.  Otherwise
                    842:         *      we destroy the right and return MACH_PORT_NULL.
                    843:         */
                    844: 
                    845:        switch (msgt_name) {
                    846:            case MACH_MSG_TYPE_PORT_SEND: {
                    847:                ipc_port_t port = (ipc_port_t) object;
                    848:                ipc_port_t nsrequest = IP_NULL;
                    849:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
                    850: 
                    851:                assert(port->ip_srights > 0);
                    852:                if (--port->ip_srights == 0) {
                    853:                        nsrequest = port->ip_nsrequest;
                    854:                        if (nsrequest != IP_NULL) {
                    855:                                port->ip_nsrequest = IP_NULL;
                    856:                                mscount = port->ip_mscount;
                    857:                        }
                    858:                }
                    859: 
                    860:                if (port->ip_receiver == space)
                    861:                        name = port->ip_receiver_name;
                    862:                else
                    863:                        name = MACH_PORT_NULL;
                    864: 
                    865:                ip_unlock(port);
                    866: 
                    867:                if (nsrequest != IP_NULL)
                    868:                        ipc_notify_no_senders(nsrequest, mscount);
                    869: 
                    870:                break;
                    871:            }
                    872: 
                    873:            case MACH_MSG_TYPE_PORT_SEND_ONCE: {
                    874:                ipc_port_t port = (ipc_port_t) object;
                    875: 
                    876:                assert(port->ip_sorights > 0);
                    877: 
                    878:                if (port->ip_receiver == space) {
                    879:                        /* quietly consume the send-once right */
                    880: 
                    881:                        port->ip_sorights--;
                    882:                        name = port->ip_receiver_name;
                    883:                        ip_unlock(port);
                    884:                } else {
                    885:                        /*
                    886:                         *      A very bizarre case.  The message
                    887:                         *      was received, but before this copyout
                    888:                         *      happened the space lost receive rights.
                    889:                         *      We can't quietly consume the soright
                    890:                         *      out from underneath some other task,
                    891:                         *      so generate a send-once notification.
                    892:                         */
                    893: 
                    894:                        ip_reference(port); /* restore ref */
                    895:                        ip_unlock(port);
                    896: 
                    897:                        ipc_notify_send_once(port);
                    898:                        name = MACH_PORT_NULL;
                    899:                }
                    900: 
                    901:                break;
                    902:            }
                    903: 
                    904:            default:
                    905: #if MACH_ASSERT
                    906:                assert(!"ipc_object_copyout_dest: strange rights");
                    907: #else
                    908:                panic("ipc_object_copyout_dest: strange rights");
                    909: #endif
                    910: 
                    911:        }
                    912: 
                    913:        *namep = name;
                    914: }
                    915: 
                    916: /*
                    917:  *     Routine:        ipc_object_rename
                    918:  *     Purpose:
                    919:  *             Rename an entry in a space.
                    920:  *     Conditions:
                    921:  *             Nothing locked.
                    922:  *     Returns:
                    923:  *             KERN_SUCCESS            Renamed the entry.
                    924:  *             KERN_INVALID_TASK       The space was dead.
                    925:  *             KERN_INVALID_NAME       oname didn't denote an entry.
                    926:  *             KERN_NAME_EXISTS        nname already denoted an entry.
                    927:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate new entry.
                    928:  */
                    929: 
                    930: kern_return_t
                    931: ipc_object_rename(
                    932:        ipc_space_t     space,
                    933:        mach_port_t     oname,
                    934:        mach_port_t     nname)
                    935: {
                    936:        ipc_entry_t oentry, nentry;
                    937:        kern_return_t kr;
                    938: 
1.1.1.5   root      939:        is_write_lock(space);
1.1       root      940:        kr = ipc_entry_alloc_name(space, nname, &nentry);
1.1.1.5   root      941:        if (kr != KERN_SUCCESS) {
                    942:                is_write_unlock(space);
1.1       root      943:                return kr;
1.1.1.5   root      944:        }
1.1       root      945: 
                    946:        if (ipc_right_inuse(space, nname, nentry)) {
                    947:                /* space is unlocked */
                    948:                return KERN_NAME_EXISTS;
                    949:        }
                    950: 
                    951:        /* don't let ipc_entry_lookup see the uninitialized new entry */
                    952: 
                    953:        if ((oname == nname) ||
                    954:            ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
                    955:                ipc_entry_dealloc(space, nname, nentry);
                    956:                is_write_unlock(space);
                    957:                return KERN_INVALID_NAME;
                    958:        }
                    959: 
                    960:        kr = ipc_right_rename(space, oname, oentry, nname, nentry);
                    961:        /* space is unlocked */
                    962:        return kr;
                    963: }
                    964: 
                    965: #if    MACH_KDB
                    966: #define        printf  kdbprintf
                    967: 
                    968: /*
                    969:  *     Routine:        ipc_object_print
                    970:  *     Purpose:
                    971:  *             Pretty-print an object for kdb.
                    972:  */
                    973: 
                    974: char *ikot_print_array[IKOT_MAX_TYPE] = {
                    975:        "(NONE)             ",
                    976:        "(THREAD)           ",
                    977:        "(TASK)             ",
                    978:        "(HOST)             ",
                    979:        "(HOST_PRIV)        ",
                    980:        "(PROCESSOR)        ",
                    981:        "(PSET)             ",
                    982:        "(PSET_NAME)        ",
                    983:        "(PAGER)            ",
                    984:        "(PAGER_REQUEST)    ",
                    985:        "(DEVICE)           ",  /* 10 */
                    986:        "(XMM_OBJECT)       ",
                    987:        "(XMM_PAGER)        ",
                    988:        "(XMM_KERNEL)       ",
                    989:        "(XMM_REPLY)        ",
                    990:        "(PAGER_TERMINATING)",
                    991:        "(PAGING_NAME)      ",
                    992:        "(HOST_SECURITY)    ",
                    993:        "(LEDGER)           ",
                    994:        "(MASTER_DEVICE)    ",
                    995:        "(ACTIVATION)       ",  /* 20 */
                    996:        "(SUBSYSTEM)        ",
                    997:        "(IO_DONE_QUEUE)    ",
                    998:        "(SEMAPHORE)        ",
                    999:        "(LOCK_SET)         ",
                   1000:        "(CLOCK)            ",
1.1.1.6 ! root     1001:        "(CLOCK_CTRL)       ",
        !          1002:        "(PAGER_PROXY)      ",  /* 27 */
1.1       root     1003:                                /* << new entries here  */
                   1004:        "(UNKNOWN)     "        /* magic catchall       */
                   1005: };     /* Please keep in sync with kern/ipc_kobject.h  */
                   1006: 
                   1007: void
                   1008: ipc_object_print(
1.1.1.4   root     1009:        const ipc_object_t object)
1.1       root     1010: {
                   1011:        int kotype;
                   1012: 
                   1013:        iprintf("%s", io_active(object) ? "active" : "dead");
                   1014:        printf(", refs=%d", object->io_references);
                   1015:        printf(", otype=%d", io_otype(object));
                   1016:        kotype = io_kotype(object);
                   1017:        if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
                   1018:                printf(", kotype=%d %s\n", io_kotype(object),
                   1019:                       ikot_print_array[kotype]);
                   1020:        else
                   1021:                printf(", kotype=0x%x %s\n", io_kotype(object),
                   1022:                       ikot_print_array[IKOT_UNKNOWN]);
                   1023: }
                   1024: 
                   1025: #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.