Annotation of OSKit-Mach/ipc/ipc_space.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
                      4:  * Copyright (c) 1993,1994 The University of Utah and
                      5:  * the Computer Systems Laboratory (CSL).
                      6:  * All rights reserved.
                      7:  *
                      8:  * Permission to use, copy, modify and distribute this software and its
                      9:  * documentation is hereby granted, provided that both the copyright
                     10:  * notice and this permission notice appear in all copies of the
                     11:  * software, derivative works or modified versions, and any portions
                     12:  * thereof, and that both notices appear in supporting documentation.
                     13:  *
                     14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
                     15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
                     16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
                     17:  * THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  [email protected]
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29: /*
                     30:  */
                     31: /*
                     32:  *     File:   ipc/ipc_space.c
                     33:  *     Author: Rich Draves
                     34:  *     Date:   1989
                     35:  *
                     36:  *     Functions to manipulate IPC capability spaces.
                     37:  */
                     38: 
                     39: #include <mach_ipc_compat.h>
                     40: #include <norma_ipc.h>
                     41: 
                     42: #include <mach/boolean.h>
                     43: #include <mach/kern_return.h>
                     44: #include <mach/port.h>
                     45: #include <kern/assert.h>
                     46: #include <kern/sched_prim.h>
                     47: #include <kern/zalloc.h>
                     48: #include <ipc/port.h>
                     49: #include <ipc/ipc_entry.h>
                     50: #include <ipc/ipc_splay.h>
                     51: #include <ipc/ipc_hash.h>
                     52: #include <ipc/ipc_table.h>
                     53: #include <ipc/ipc_port.h>
                     54: #include <ipc/ipc_space.h>
                     55: #include <ipc/ipc_right.h>
                     56: 
                     57: 
                     58: 
                     59: zone_t ipc_space_zone;
                     60: ipc_space_t ipc_space_kernel;
                     61: ipc_space_t ipc_space_reply;
                     62: #if    NORMA_IPC
                     63: ipc_space_t ipc_space_remote;
                     64: #endif /* NORMA_IPC */
                     65: 
                     66: /*
                     67:  *     Routine:        ipc_space_reference
                     68:  *     Routine:        ipc_space_release
                     69:  *     Purpose:
                     70:  *             Function versions of the IPC space macros.
                     71:  *             The "is_" cover macros can be defined to use the
                     72:  *             macros or the functions, as desired.
                     73:  */
                     74: 
                     75: void
                     76: ipc_space_reference(
                     77:        ipc_space_t     space)
                     78: {
                     79:        ipc_space_reference_macro(space);
                     80: }
                     81: 
                     82: void
                     83: ipc_space_release(
                     84:        ipc_space_t     space)
                     85: {
                     86:        ipc_space_release_macro(space);
                     87: }
                     88: 
                     89: /*
                     90:  *     Routine:        ipc_space_create
                     91:  *     Purpose:
                     92:  *             Creates a new IPC space.
                     93:  *
                     94:  *             The new space has two references, one for the caller
                     95:  *             and one because it is active.
                     96:  *     Conditions:
                     97:  *             Nothing locked.  Allocates memory.
                     98:  *     Returns:
                     99:  *             KERN_SUCCESS            Created a space.
                    100:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    101:  */
                    102: 
                    103: kern_return_t
                    104: ipc_space_create(
                    105:        ipc_table_size_t        initial,
                    106:        ipc_space_t             *spacep)
                    107: {
                    108:        ipc_space_t space;
                    109:        ipc_entry_t table;
                    110:        ipc_entry_num_t new_size;
                    111:        mach_port_index_t index;
                    112: 
                    113:        space = is_alloc();
                    114:        if (space == IS_NULL)
                    115:                return KERN_RESOURCE_SHORTAGE;
                    116: 
                    117:        table = it_entries_alloc(initial);
                    118:        if (table == IE_NULL) {
                    119:                is_free(space);
                    120:                return KERN_RESOURCE_SHORTAGE;
                    121:        }
                    122: 
                    123:        new_size = initial->its_size;
                    124:        memset((void *) table, 0, new_size * sizeof(struct ipc_entry));
                    125: 
                    126:        /*
                    127:         *      Initialize the free list in the table.
                    128:         *      Add the entries in reverse order, and
                    129:         *      set the generation number to -1, so that
                    130:         *      initial allocations produce "natural" names.
                    131:         */
                    132: 
                    133:        for (index = 0; index < new_size; index++) {
                    134:                ipc_entry_t entry = &table[index];
                    135: 
                    136:                entry->ie_bits = IE_BITS_GEN_MASK;
                    137:                entry->ie_next = index+1;
                    138:        }
                    139:        table[new_size-1].ie_next = 0;
                    140: 
                    141:        is_ref_lock_init(space);
                    142:        space->is_references = 2;
                    143: 
                    144:        is_lock_init(space);
                    145:        space->is_active = TRUE;
                    146:        space->is_growing = FALSE;
                    147:        space->is_table = table;
                    148:        space->is_table_size = new_size;
                    149:        space->is_table_next = initial+1;
                    150: 
                    151:        ipc_splay_tree_init(&space->is_tree);
                    152:        space->is_tree_total = 0;
                    153:        space->is_tree_small = 0;
                    154:        space->is_tree_hash = 0;
                    155: 
                    156: #if    MACH_IPC_COMPAT
                    157:     {
                    158:        mach_port_t name;
                    159:        ipc_port_t port;
                    160:        kern_return_t kr;
                    161: 
                    162:        /*
                    163:         *      ipc_port_alloc_compat probably won't look at is_notify,
                    164:         *      but make sure all fields have sane values anyway.
                    165:         */
                    166: 
                    167:        space->is_notify = IP_NULL;
                    168: 
                    169:        kr = ipc_port_alloc_compat(space, &name, &port);
                    170:        if (kr != KERN_SUCCESS) {
                    171:                ipc_space_destroy(space);
                    172:                is_release(space);
                    173:                return kr;
                    174:        }
                    175: 
                    176:        ip_reference(port);
                    177:        port->ip_srights++;
                    178:        ip_unlock(port);
                    179:        space->is_notify = port;
                    180:     }
                    181: #endif /* MACH_IPC_COMPAT */
                    182: 
                    183:        *spacep = space;
                    184:        return KERN_SUCCESS;
                    185: }
                    186: 
                    187: /*
                    188:  *     Routine:        ipc_space_create_special
                    189:  *     Purpose:
                    190:  *             Create a special space.  A special space
                    191:  *             doesn't hold rights in the normal way.
                    192:  *             Instead it is place-holder for holding
                    193:  *             disembodied (naked) receive rights.
                    194:  *             See ipc_port_alloc_special/ipc_port_dealloc_special.
                    195:  *     Conditions:
                    196:  *             Nothing locked.
                    197:  *     Returns:
                    198:  *             KERN_SUCCESS            Created a space.
                    199:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    200:  */
                    201: 
                    202: kern_return_t
                    203: ipc_space_create_special(
                    204:        ipc_space_t     *spacep)
                    205: {
                    206:        ipc_space_t space;
                    207: 
                    208:        space = is_alloc();
                    209:        if (space == IS_NULL)
                    210:                return KERN_RESOURCE_SHORTAGE;
                    211: 
                    212:        is_ref_lock_init(space);
                    213:        space->is_references = 1;
                    214: 
                    215:        is_lock_init(space);
                    216:        space->is_active = FALSE;
                    217: 
                    218:        *spacep = space;
                    219:        return KERN_SUCCESS;
                    220: }
                    221: 
                    222: /*
                    223:  *     Routine:        ipc_space_destroy
                    224:  *     Purpose:
                    225:  *             Marks the space as dead and cleans up the entries.
                    226:  *             Does nothing if the space is already dead.
                    227:  *     Conditions:
                    228:  *             Nothing locked.
                    229:  */
                    230: 
                    231: void
                    232: ipc_space_destroy(
                    233:        ipc_space_t     space)
                    234: {
                    235:        ipc_tree_entry_t tentry;
                    236:        ipc_entry_t table;
                    237:        ipc_entry_num_t size;
                    238:        mach_port_index_t index;
                    239:        boolean_t active;
                    240: 
                    241:        assert(space != IS_NULL);
                    242: 
                    243:        is_write_lock(space);
                    244:        active = space->is_active;
                    245:        space->is_active = FALSE;
                    246:        is_write_unlock(space);
                    247: 
                    248:        if (!active)
                    249:                return;
                    250: 
                    251:        /*
                    252:         *      If somebody is trying to grow the table,
                    253:         *      we must wait until they finish and figure
                    254:         *      out the space died.
                    255:         */
                    256: 
                    257:        is_read_lock(space);
                    258:        while (space->is_growing) {
                    259:                assert_wait((event_t) space, FALSE);
                    260:                is_read_unlock(space);
                    261:                thread_block((void (*)(void)) 0);
                    262:                is_read_lock(space);
                    263:        }
                    264:        is_read_unlock(space);
                    265: 
                    266:        /*
                    267:         *      Now we can futz with it without having it locked.
                    268:         */
                    269: 
                    270:        table = space->is_table;
                    271:        size = space->is_table_size;
                    272: 
                    273:        for (index = 0; index < size; index++) {
                    274:                ipc_entry_t entry = &table[index];
                    275:                mach_port_type_t type = IE_BITS_TYPE(entry->ie_bits);
                    276: 
                    277:                if (type != MACH_PORT_TYPE_NONE) {
                    278:                        mach_port_t name =
                    279:                                MACH_PORT_MAKEB(index, entry->ie_bits);
                    280: 
                    281:                        ipc_right_clean(space, name, entry);
                    282:                }
                    283:        }
                    284: 
                    285:        it_entries_free(space->is_table_next-1, table);
                    286: 
                    287:        for (tentry = ipc_splay_traverse_start(&space->is_tree);
                    288:             tentry != ITE_NULL;
                    289:             tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
                    290:                mach_port_type_t type = IE_BITS_TYPE(tentry->ite_bits);
                    291:                mach_port_t name = tentry->ite_name;
                    292: 
                    293:                assert(type != MACH_PORT_TYPE_NONE);
                    294: 
                    295:                /* use object before ipc_right_clean releases ref */
                    296: 
                    297:                if (type == MACH_PORT_TYPE_SEND)
                    298:                        ipc_hash_global_delete(space, tentry->ite_object,
                    299:                                               name, tentry);
                    300: 
                    301:                ipc_right_clean(space, name, &tentry->ite_entry);
                    302:        }
                    303:        ipc_splay_traverse_finish(&space->is_tree);
                    304: 
                    305: #if    MACH_IPC_COMPAT
                    306:        if (IP_VALID(space->is_notify))
                    307:                ipc_port_release_send(space->is_notify);
                    308: #endif /* MACH_IPC_COMPAT */
                    309: 
                    310:        /*
                    311:         *      Because the space is now dead,
                    312:         *      we must release the "active" reference for it.
                    313:         *      Our caller still has his reference.
                    314:         */
                    315: 
                    316:        is_release(space);
                    317: }

unix.superglobalmegacorp.com

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