|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.