Annotation of kernel/ipc/ipc_object.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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