|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: ipc/ipc_space.c ! 54: * Author: Rich Draves ! 55: * Date: 1989 ! 56: * ! 57: * Functions to manipulate IPC capability spaces. ! 58: */ ! 59: ! 60: #include <dipc.h> ! 61: #include <mach_kdb.h> ! 62: ! 63: #include <mach/boolean.h> ! 64: #include <mach/kern_return.h> ! 65: #include <mach/port.h> ! 66: #include <kern/assert.h> ! 67: #include <kern/sched_prim.h> ! 68: #include <kern/zalloc.h> ! 69: #include <ipc/port.h> ! 70: #include <ipc/ipc_entry.h> ! 71: #include <ipc/ipc_splay.h> ! 72: #include <ipc/ipc_object.h> ! 73: #include <ipc/ipc_hash.h> ! 74: #include <ipc/ipc_table.h> ! 75: #include <ipc/ipc_port.h> ! 76: #include <ipc/ipc_space.h> ! 77: #include <ipc/ipc_right.h> ! 78: #include <string.h> ! 79: ! 80: zone_t ipc_space_zone; ! 81: ipc_space_t ipc_space_kernel; ! 82: ipc_space_t ipc_space_reply; ! 83: #if DIPC ! 84: ipc_space_t ipc_space_remote; ! 85: #endif /* DIPC */ ! 86: #if DIPC || MACH_KDB ! 87: ipc_space_t default_pager_space; ! 88: #endif /* DIPC || MACH_KDB */ ! 89: ! 90: /* ! 91: * Routine: ipc_space_reference ! 92: * Routine: ipc_space_release ! 93: * Purpose: ! 94: * Function versions of the IPC space macros. ! 95: * The "is_" cover macros can be defined to use the ! 96: * macros or the functions, as desired. ! 97: */ ! 98: ! 99: void ! 100: ipc_space_reference( ! 101: ipc_space_t space) ! 102: { ! 103: ipc_space_reference_macro(space); ! 104: } ! 105: ! 106: void ! 107: ipc_space_release( ! 108: ipc_space_t space) ! 109: { ! 110: ipc_space_release_macro(space); ! 111: } ! 112: ! 113: /* ! 114: * Routine: ipc_space_create ! 115: * Purpose: ! 116: * Creates a new IPC space. ! 117: * ! 118: * The new space has two references, one for the caller ! 119: * and one because it is active. ! 120: * Conditions: ! 121: * Nothing locked. Allocates memory. ! 122: * Returns: ! 123: * KERN_SUCCESS Created a space. ! 124: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 125: */ ! 126: ! 127: kern_return_t ! 128: ipc_space_create( ! 129: ipc_table_size_t initial, ! 130: ipc_space_t *spacep) ! 131: { ! 132: ipc_space_t space; ! 133: ipc_entry_t table; ! 134: ipc_entry_num_t new_size; ! 135: mach_port_index_t index; ! 136: ! 137: space = is_alloc(); ! 138: if (space == IS_NULL) ! 139: return KERN_RESOURCE_SHORTAGE; ! 140: ! 141: table = it_entries_alloc(initial); ! 142: if (table == IE_NULL) { ! 143: is_free(space); ! 144: return KERN_RESOURCE_SHORTAGE; ! 145: } ! 146: ! 147: new_size = initial->its_size; ! 148: memset((void *) table, 0, new_size * sizeof(struct ipc_entry)); ! 149: ! 150: /* ! 151: * Initialize the free list in the table. ! 152: * Add the entries in reverse order, and ! 153: * set the generation number to -1, so that ! 154: * initial allocations produce "natural" names. ! 155: */ ! 156: for (index = 0; index < new_size; index++) { ! 157: ipc_entry_t entry = &table[index]; ! 158: ! 159: entry->ie_bits = IE_BITS_GEN_MASK; ! 160: entry->ie_next = index+1; ! 161: } ! 162: table[new_size-1].ie_next = 0; ! 163: ! 164: is_ref_lock_init(space); ! 165: space->is_references = 2; ! 166: ! 167: is_lock_init(space); ! 168: space->is_active = TRUE; ! 169: space->is_growing = FALSE; ! 170: space->is_table = table; ! 171: space->is_table_size = new_size; ! 172: space->is_table_next = initial+1; ! 173: ! 174: ipc_splay_tree_init(&space->is_tree); ! 175: space->is_tree_total = 0; ! 176: space->is_tree_small = 0; ! 177: space->is_tree_hash = 0; ! 178: ! 179: *spacep = space; ! 180: return KERN_SUCCESS; ! 181: } ! 182: ! 183: /* ! 184: * Routine: ipc_space_create_special ! 185: * Purpose: ! 186: * Create a special space. A special space ! 187: * doesn't hold rights in the normal way. ! 188: * Instead it is place-holder for holding ! 189: * disembodied (naked) receive rights. ! 190: * See ipc_port_alloc_special/ipc_port_dealloc_special. ! 191: * Conditions: ! 192: * Nothing locked. ! 193: * Returns: ! 194: * KERN_SUCCESS Created a space. ! 195: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 196: */ ! 197: ! 198: kern_return_t ! 199: ipc_space_create_special( ! 200: ipc_space_t *spacep) ! 201: { ! 202: ipc_space_t space; ! 203: ! 204: space = is_alloc(); ! 205: if (space == IS_NULL) ! 206: return KERN_RESOURCE_SHORTAGE; ! 207: ! 208: is_ref_lock_init(space); ! 209: space->is_references = 1; ! 210: ! 211: is_lock_init(space); ! 212: space->is_active = FALSE; ! 213: ! 214: *spacep = space; ! 215: return KERN_SUCCESS; ! 216: } ! 217: ! 218: /* ! 219: * ipc_space_clean - remove all port references from an ipc space. ! 220: * ! 221: * In order to follow the traditional semantic, ipc_space_destroy ! 222: * will not destroy the entire port table of a shared space. Instead ! 223: * it will simply clear its own sub-space. ! 224: */ ! 225: void ! 226: ipc_space_clean( ! 227: ipc_space_t space) ! 228: { ! 229: ipc_tree_entry_t tentry; ! 230: ipc_entry_t table; ! 231: ipc_entry_num_t size; ! 232: mach_port_index_t index; ! 233: ! 234: /* ! 235: * If somebody is trying to grow the table, ! 236: * we must wait until they finish and figure ! 237: * out the space died. ! 238: */ ! 239: is_write_lock(space); ! 240: while (space->is_growing) { ! 241: assert_wait((event_t) space, THREAD_UNINT); ! 242: is_write_unlock(space); ! 243: thread_block((void (*)(void)) 0); ! 244: is_write_lock(space); ! 245: } ! 246: ! 247: /* ! 248: * Now we can futz with it since we have the write lock. ! 249: */ ! 250: #if DIPC || MACH_KDB ! 251: if (space == default_pager_space) ! 252: default_pager_space = IS_NULL; ! 253: #endif /* DIPC || MACH_KDB */ ! 254: ! 255: table = space->is_table; ! 256: size = space->is_table_size; ! 257: ! 258: for (index = 0; index < size; index++) { ! 259: ipc_entry_t entry = &table[index]; ! 260: mach_port_type_t type; ! 261: ! 262: type = IE_BITS_TYPE(entry->ie_bits); ! 263: if (type != MACH_PORT_TYPE_NONE) { ! 264: mach_port_name_t name = MACH_PORT_MAKE(index, ! 265: IE_BITS_GEN(entry->ie_bits)); ! 266: ipc_right_destroy(space, name, entry); ! 267: } ! 268: } ! 269: ! 270: /* ! 271: * JMM - Now the table is cleaned out. We don't bother shrinking the ! 272: * size of the table at this point, but we probably should if it is ! 273: * really large. Lets just clean up the splay tree. ! 274: */ ! 275: start_splay: ! 276: for (tentry = ipc_splay_traverse_start(&space->is_tree); ! 277: tentry != ITE_NULL; ! 278: tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) { ! 279: int i; ! 280: mach_port_type_t type; ! 281: mach_port_name_t name = tentry->ite_name; ! 282: ! 283: type = IE_BITS_TYPE(tentry->ite_bits); ! 284: /* ! 285: * If it is a real right, then destroy it. This will have the ! 286: * side effect of removing it from the splay, so start over. ! 287: */ ! 288: if(type != MACH_PORT_TYPE_NONE) { ! 289: ipc_splay_traverse_finish(&space->is_tree); ! 290: ipc_right_destroy(space, name, &tentry->ite_entry); ! 291: goto start_splay; ! 292: } ! 293: } ! 294: ipc_splay_traverse_finish(&space->is_tree); ! 295: is_write_unlock(space); ! 296: } ! 297: ! 298: ! 299: /* ! 300: * Routine: ipc_space_destroy ! 301: * Purpose: ! 302: * Marks the space as dead and cleans up the entries. ! 303: * Does nothing if the space is already dead. ! 304: * Conditions: ! 305: * Nothing locked. ! 306: */ ! 307: ! 308: void ! 309: ipc_space_destroy( ! 310: ipc_space_t space) ! 311: { ! 312: boolean_t active; ! 313: ipc_tree_entry_t tentry; ! 314: ipc_entry_t table; ! 315: ipc_entry_num_t size; ! 316: mach_port_index_t index; ! 317: ! 318: assert(space != IS_NULL); ! 319: ! 320: is_write_lock(space); ! 321: active = space->is_active; ! 322: space->is_active = FALSE; ! 323: is_write_unlock(space); ! 324: ! 325: if (!active) ! 326: return; ! 327: ! 328: ! 329: /* ! 330: * If somebody is trying to grow the table, ! 331: * we must wait until they finish and figure ! 332: * out the space died. ! 333: */ ! 334: is_read_lock(space); ! 335: while (space->is_growing) { ! 336: assert_wait((event_t) space, THREAD_UNINT); ! 337: is_read_unlock(space); ! 338: thread_block((void (*)(void)) 0); ! 339: is_read_lock(space); ! 340: } ! 341: ! 342: is_read_unlock(space); ! 343: /* ! 344: * Now we can futz with it unlocked. ! 345: */ ! 346: #if DIPC || MACH_KDB ! 347: if (space == default_pager_space) ! 348: default_pager_space = IS_NULL; ! 349: #endif /* DIPC || MACH_KDB */ ! 350: ! 351: table = space->is_table; ! 352: size = space->is_table_size; ! 353: ! 354: for (index = 0; index < size; index++) { ! 355: ipc_entry_t entry = &table[index]; ! 356: mach_port_type_t type; ! 357: ! 358: type = IE_BITS_TYPE(entry->ie_bits); ! 359: if (type != MACH_PORT_TYPE_NONE) { ! 360: mach_port_name_t name; ! 361: ! 362: name = MACH_PORT_MAKE(index, ! 363: IE_BITS_GEN(entry->ie_bits)); ! 364: ipc_right_clean(space, name, entry); ! 365: } ! 366: } ! 367: ! 368: it_entries_free(space->is_table_next-1, table); ! 369: space->is_table_size = 0; ! 370: ! 371: for (tentry = ipc_splay_traverse_start(&space->is_tree); ! 372: tentry != ITE_NULL; ! 373: tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) { ! 374: mach_port_type_t type; ! 375: mach_port_name_t name = tentry->ite_name; ! 376: ! 377: type = IE_BITS_TYPE(tentry->ite_bits); ! 378: assert(type != MACH_PORT_TYPE_NONE); ! 379: ! 380: ipc_right_clean(space, name, &tentry->ite_entry); ! 381: ! 382: if(type == MACH_PORT_TYPE_SEND) ! 383: ipc_hash_global_delete(space, tentry->ite_object, ! 384: name, tentry); ! 385: } ! 386: ipc_splay_traverse_finish(&space->is_tree); ! 387: ! 388: /* ! 389: * Because the space is now dead, ! 390: * we must release the "active" reference for it. ! 391: * Our caller still has his reference. ! 392: */ ! 393: is_release(space); ! 394: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.