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