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