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

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: 
1.1.1.3 ! root       39: #include <string.h>
1.1       root       40: 
                     41: #include <mach/boolean.h>
                     42: #include <mach/kern_return.h>
                     43: #include <mach/port.h>
                     44: #include <kern/assert.h>
                     45: #include <kern/sched_prim.h>
1.1.1.3 ! root       46: #include <kern/slab.h>
1.1       root       47: #include <ipc/port.h>
                     48: #include <ipc/ipc_entry.h>
                     49: #include <ipc/ipc_splay.h>
                     50: #include <ipc/ipc_hash.h>
                     51: #include <ipc/ipc_table.h>
                     52: #include <ipc/ipc_port.h>
                     53: #include <ipc/ipc_space.h>
                     54: #include <ipc/ipc_right.h>
                     55: 
                     56: 
                     57: 
1.1.1.3 ! root       58: struct kmem_cache ipc_space_cache;
1.1       root       59: ipc_space_t ipc_space_kernel;
                     60: ipc_space_t ipc_space_reply;
                     61: 
                     62: /*
                     63:  *     Routine:        ipc_space_reference
                     64:  *     Routine:        ipc_space_release
                     65:  *     Purpose:
                     66:  *             Function versions of the IPC space macros.
                     67:  *             The "is_" cover macros can be defined to use the
                     68:  *             macros or the functions, as desired.
                     69:  */
                     70: 
                     71: void
                     72: ipc_space_reference(
                     73:        ipc_space_t     space)
                     74: {
                     75:        ipc_space_reference_macro(space);
                     76: }
                     77: 
                     78: void
                     79: ipc_space_release(
                     80:        ipc_space_t     space)
                     81: {
                     82:        ipc_space_release_macro(space);
                     83: }
                     84: 
                     85: /*
                     86:  *     Routine:        ipc_space_create
                     87:  *     Purpose:
                     88:  *             Creates a new IPC space.
                     89:  *
                     90:  *             The new space has two references, one for the caller
                     91:  *             and one because it is active.
                     92:  *     Conditions:
                     93:  *             Nothing locked.  Allocates memory.
                     94:  *     Returns:
                     95:  *             KERN_SUCCESS            Created a space.
                     96:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                     97:  */
                     98: 
                     99: kern_return_t
                    100: ipc_space_create(
                    101:        ipc_table_size_t        initial,
                    102:        ipc_space_t             *spacep)
                    103: {
                    104:        ipc_space_t space;
                    105:        ipc_entry_t table;
                    106:        ipc_entry_num_t new_size;
                    107:        mach_port_index_t index;
                    108: 
                    109:        space = is_alloc();
                    110:        if (space == IS_NULL)
                    111:                return KERN_RESOURCE_SHORTAGE;
                    112: 
                    113:        table = it_entries_alloc(initial);
                    114:        if (table == IE_NULL) {
                    115:                is_free(space);
                    116:                return KERN_RESOURCE_SHORTAGE;
                    117:        }
                    118: 
                    119:        new_size = initial->its_size;
                    120:        memset((void *) table, 0, new_size * sizeof(struct ipc_entry));
                    121: 
                    122:        /*
                    123:         *      Initialize the free list in the table.
                    124:         *      Add the entries in reverse order, and
                    125:         *      set the generation number to -1, so that
                    126:         *      initial allocations produce "natural" names.
                    127:         */
                    128: 
                    129:        for (index = 0; index < new_size; index++) {
                    130:                ipc_entry_t entry = &table[index];
                    131: 
                    132:                entry->ie_bits = IE_BITS_GEN_MASK;
                    133:                entry->ie_next = index+1;
                    134:        }
                    135:        table[new_size-1].ie_next = 0;
                    136: 
                    137:        is_ref_lock_init(space);
                    138:        space->is_references = 2;
                    139: 
                    140:        is_lock_init(space);
                    141:        space->is_active = TRUE;
                    142:        space->is_growing = FALSE;
                    143:        space->is_table = table;
                    144:        space->is_table_size = new_size;
                    145:        space->is_table_next = initial+1;
                    146: 
                    147:        ipc_splay_tree_init(&space->is_tree);
                    148:        space->is_tree_total = 0;
                    149:        space->is_tree_small = 0;
                    150:        space->is_tree_hash = 0;
                    151: 
                    152:        *spacep = space;
                    153:        return KERN_SUCCESS;
                    154: }
                    155: 
                    156: /*
                    157:  *     Routine:        ipc_space_create_special
                    158:  *     Purpose:
                    159:  *             Create a special space.  A special space
                    160:  *             doesn't hold rights in the normal way.
                    161:  *             Instead it is place-holder for holding
                    162:  *             disembodied (naked) receive rights.
                    163:  *             See ipc_port_alloc_special/ipc_port_dealloc_special.
                    164:  *     Conditions:
                    165:  *             Nothing locked.
                    166:  *     Returns:
                    167:  *             KERN_SUCCESS            Created a space.
                    168:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    169:  */
                    170: 
                    171: kern_return_t
                    172: ipc_space_create_special(
                    173:        ipc_space_t     *spacep)
                    174: {
                    175:        ipc_space_t space;
                    176: 
                    177:        space = is_alloc();
                    178:        if (space == IS_NULL)
                    179:                return KERN_RESOURCE_SHORTAGE;
                    180: 
                    181:        is_ref_lock_init(space);
                    182:        space->is_references = 1;
                    183: 
                    184:        is_lock_init(space);
                    185:        space->is_active = FALSE;
                    186: 
                    187:        *spacep = space;
                    188:        return KERN_SUCCESS;
                    189: }
                    190: 
                    191: /*
                    192:  *     Routine:        ipc_space_destroy
                    193:  *     Purpose:
                    194:  *             Marks the space as dead and cleans up the entries.
                    195:  *             Does nothing if the space is already dead.
                    196:  *     Conditions:
                    197:  *             Nothing locked.
                    198:  */
                    199: 
                    200: void
                    201: ipc_space_destroy(
                    202:        ipc_space_t     space)
                    203: {
                    204:        ipc_tree_entry_t tentry;
                    205:        ipc_entry_t table;
                    206:        ipc_entry_num_t size;
                    207:        mach_port_index_t index;
                    208:        boolean_t active;
                    209: 
                    210:        assert(space != IS_NULL);
                    211: 
                    212:        is_write_lock(space);
                    213:        active = space->is_active;
                    214:        space->is_active = FALSE;
                    215:        is_write_unlock(space);
                    216: 
                    217:        if (!active)
                    218:                return;
                    219: 
                    220:        /*
                    221:         *      If somebody is trying to grow the table,
                    222:         *      we must wait until they finish and figure
                    223:         *      out the space died.
                    224:         */
                    225: 
                    226:        is_read_lock(space);
                    227:        while (space->is_growing) {
                    228:                assert_wait((event_t) space, FALSE);
                    229:                is_read_unlock(space);
                    230:                thread_block((void (*)(void)) 0);
                    231:                is_read_lock(space);
                    232:        }
                    233:        is_read_unlock(space);
                    234: 
                    235:        /*
                    236:         *      Now we can futz with it without having it locked.
                    237:         */
                    238: 
                    239:        table = space->is_table;
                    240:        size = space->is_table_size;
                    241: 
                    242:        for (index = 0; index < size; index++) {
                    243:                ipc_entry_t entry = &table[index];
                    244:                mach_port_type_t type = IE_BITS_TYPE(entry->ie_bits);
                    245: 
                    246:                if (type != MACH_PORT_TYPE_NONE) {
                    247:                        mach_port_t name =
                    248:                                MACH_PORT_MAKEB(index, entry->ie_bits);
                    249: 
                    250:                        ipc_right_clean(space, name, entry);
                    251:                }
                    252:        }
                    253: 
                    254:        it_entries_free(space->is_table_next-1, table);
                    255: 
                    256:        for (tentry = ipc_splay_traverse_start(&space->is_tree);
                    257:             tentry != ITE_NULL;
                    258:             tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
                    259:                mach_port_type_t type = IE_BITS_TYPE(tentry->ite_bits);
                    260:                mach_port_t name = tentry->ite_name;
                    261: 
                    262:                assert(type != MACH_PORT_TYPE_NONE);
                    263: 
                    264:                /* use object before ipc_right_clean releases ref */
                    265: 
                    266:                if (type == MACH_PORT_TYPE_SEND)
                    267:                        ipc_hash_global_delete(space, tentry->ite_object,
                    268:                                               name, tentry);
                    269: 
                    270:                ipc_right_clean(space, name, &tentry->ite_entry);
                    271:        }
                    272:        ipc_splay_traverse_finish(&space->is_tree);
                    273: 
                    274:        /*
                    275:         *      Because the space is now dead,
                    276:         *      we must release the "active" reference for it.
                    277:         *      Our caller still has his reference.
                    278:         */
                    279: 
                    280:        is_release(space);
                    281: }

unix.superglobalmegacorp.com

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