|
|
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.