1 /*
2 * Copyright 1991-1998 by Open Software Foundation, Inc.
3 * All Rights Reserved
4 *
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby granted,
7 * provided that the above copyright notice appears in all copies and
8 * that both the copyright notice and this permission notice appear in
9 * supporting documentation.
10 *
11 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21 /*
22 * MkLinux
23 */
24 /* CMU_HIST */
25 /*
26 * Revision 2.8.2.1 92/01/03 16:35:55 jsb
27 * NORMA_IPC: declare ipc_space_remote.
28 * [91/12/24 14:00:40 jsb]
29 *
30 * Revision 2.8 91/10/09 16:10:26 af
31 * Revision 2.7.2.1 91/09/16 10:15:57 rpd
32 * Added <ipc/ipc_hash.h>.
33 * [91/09/02 rpd]
34 *
35 * Revision 2.7.2.1 91/09/16 10:15:57 rpd
36 * Added <ipc/ipc_hash.h>.
37 * [91/09/02 rpd]
38 *
39 * Revision 2.7 91/05/14 16:36:44 mrt
40 * Correcting copyright
41 *
42 * Revision 2.6 91/03/16 14:48:37 rpd
43 * Added is_growing.
44 * [91/03/07 16:38:42 rpd]
45 *
46 * Revision 2.5 91/02/05 17:23:43 mrt
47 * Changed to new Mach copyright
48 * [91/02/01 15:51:18 mrt]
49 *
50 * Revision 2.4 91/01/08 15:14:48 rpd
51 * Removed MACH_IPC_GENNOS.
52 * [90/11/08 rpd]
53 *
54 * Revision 2.3 90/11/05 14:30:20 rpd
55 * Use new ip_reference and ip_release.
56 * [90/10/29 rpd]
57 *
58 * Revision 2.2 90/06/02 14:51:39 rpd
59 * Created for new IPC.
60 * [90/03/26 21:03:12 rpd]
61 *
62 */
63 /* CMU_ENDHIST */
64 /*
65 * Mach Operating System
66 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
67 * All Rights Reserved.
68 *
69 * Permission to use, copy, modify and distribute this software and its
70 * documentation is hereby granted, provided that both the copyright
71 * notice and this permission notice appear in all copies of the
72 * software, derivative works or modified versions, and any portions
73 * thereof, and that both notices appear in supporting documentation.
74 *
75 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
76 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
77 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
78 *
79 * Carnegie Mellon requests users of this software to return to
80 *
81 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
82 * School of Computer Science
83 * Carnegie Mellon University
84 * Pittsburgh PA 15213-3890
85 *
86 * any improvements or extensions that they make and grant Carnegie Mellon
87 * the rights to redistribute these changes.
88 */
89 /*
90 */
91 /*
92 * File: ipc/ipc_space.c
93 * Author: Rich Draves
94 * Date: 1989
95 *
96 * Functions to manipulate IPC capability spaces.
97 */
98 #if 0
99 #include <dipc.h>
100 #include <mach_kdb.h>
101
102 #include <mach/boolean.h>
103 #endif
104 #include <sys/cdefs.h>
105 #include <sys/types.h>
106 #include <sys/param.h>
107 #include <sys/lock.h>
108 #include <sys/mutex.h>
109
110 #include <sys/mach/kern_return.h>
111 #include <sys/mach/port.h>
112 #if 0
113 #include <kern/assert.h>
114 #endif
115
116 #include <vm/uma.h>
117 #include <sys/mach/ipc/port.h>
118 #include <sys/mach/ipc/ipc_entry.h>
119 #include <sys/mach/ipc/ipc_object.h>
120 #include <sys/mach/ipc/ipc_hash.h>
121 #include <sys/mach/ipc/ipc_table.h>
122 #include <sys/mach/ipc/ipc_port.h>
123 #include <sys/mach/ipc/ipc_space.h>
124 #include <sys/mach/ipc/ipc_right.h>
125 #include <sys/mach/thread.h>
126
127
128 uma_zone_t ipc_space_zone;
129 ipc_space_t ipc_space_kernel;
130 ipc_space_t ipc_space_reply;
131
132 /*
133 * Routine: ipc_space_reference
134 * Routine: ipc_space_release
135 * Purpose:
136 * Function versions of the IPC space macros.
137 * The "is_" cover macros can be defined to use the
138 * macros or the functions, as desired.
139 */
140
141 void
ipc_space_reference(ipc_space_t space)142 ipc_space_reference(
143 ipc_space_t space)
144 {
145 ipc_space_reference_macro(space);
146 }
147
148 void
ipc_space_release(ipc_space_t space)149 ipc_space_release(
150 ipc_space_t space)
151 {
152 ipc_space_release_macro(space);
153 }
154
155 /*
156 * Routine: ipc_space_create
157 * Purpose:
158 * Creates a new IPC space.
159 *
160 * The new space has two references, one for the caller
161 * and one because it is active.
162 * Conditions:
163 * Nothing locked. Allocates memory.
164 * Returns:
165 * KERN_SUCCESS Created a space.
166 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
167 */
168
169 kern_return_t
ipc_space_create(ipc_table_size_t initial,ipc_space_t * spacep)170 ipc_space_create(
171 ipc_table_size_t initial,
172 ipc_space_t *spacep)
173 {
174 ipc_space_t space;
175 ipc_entry_t *table;
176 ipc_entry_num_t new_size;
177
178 space = is_alloc();
179 if (space == IS_NULL)
180 return KERN_RESOURCE_SHORTAGE;
181
182 table = it_entries_alloc(initial);
183 if (table == NULL) {
184 is_free(space);
185 return KERN_RESOURCE_SHORTAGE;
186 }
187
188 new_size = initial->its_size;
189 memset((void *) table, 0, new_size * sizeof(struct ipc_entry *));
190
191
192 is_ref_lock_init(space);
193 space->is_references = 2;
194
195 is_lock_init(space);
196 space->is_active = TRUE;
197 space->is_growing = FALSE;
198 space->is_table = table;
199 space->is_table_size = new_size;
200 space->is_table_next = initial+1;
201 LIST_INIT(&space->is_entry_list);
202
203 space->is_tree_total = 0;
204 space->is_tree_small = 0;
205 space->is_tree_hash = 0;
206
207 *spacep = space;
208 return KERN_SUCCESS;
209 }
210
211 /*
212 * Routine: ipc_space_create_special
213 * Purpose:
214 * Create a special space. A special space
215 * doesn't hold rights in the normal way.
216 * Instead it is place-holder for holding
217 * disembodied (naked) receive rights.
218 * See ipc_port_alloc_special/ipc_port_dealloc_special.
219 * Conditions:
220 * Nothing locked.
221 * Returns:
222 * KERN_SUCCESS Created a space.
223 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
224 */
225
226 kern_return_t
ipc_space_create_special(ipc_space_t * spacep)227 ipc_space_create_special(
228 ipc_space_t *spacep)
229 {
230 ipc_space_t space;
231
232 space = is_alloc();
233 if (space == IS_NULL)
234 return KERN_RESOURCE_SHORTAGE;
235
236 is_ref_lock_init(space);
237 space->is_references = 1;
238
239 is_lock_init(space);
240 space->is_active = FALSE;
241 space->is_task = current_task();
242 LIST_INIT(&space->is_entry_list);
243
244 *spacep = space;
245 return KERN_SUCCESS;
246 }
247
248 /*
249 * Routine: ipc_space_destroy
250 * Purpose:
251 * Marks the space as dead and cleans up the entries.
252 * Does nothing if the space is already dead.
253 * Conditions:
254 * Nothing locked.
255 */
256
257 void
ipc_space_destroy(ipc_space_t space)258 ipc_space_destroy(
259 ipc_space_t space)
260 {
261 ipc_entry_t *table;
262 ipc_entry_num_t size;
263 mach_port_index_t index;
264 boolean_t active;
265
266 assert(space != IS_NULL);
267
268 is_write_lock(space);
269 active = space->is_active;
270 space->is_active = FALSE;
271 is_write_unlock(space);
272
273 if (!active)
274 return;
275
276 /*
277 * If somebody is trying to grow the table,
278 * we must wait until they finish and figure
279 * out the space died.
280 */
281
282 is_read_lock(space);
283 while (space->is_growing) {
284 assert_wait((event_t) space, FALSE);
285 is_read_unlock(space);
286 thread_block();
287 is_read_lock(space);
288 }
289 is_read_unlock(space);
290
291 /*
292 * Now we can futz with it without having it locked.
293 */
294
295 table = space->is_table;
296 size = space->is_table_size;
297
298 for (index = 0; index < size; index++) {
299 ipc_entry_t entry = table[index];
300
301 if (entry == NULL)
302 continue;
303 while (entry != NULL) {
304 mach_port_type_t type = IE_BITS_TYPE(entry->ie_bits);
305
306 if (type != MACH_PORT_TYPE_NONE)
307 ipc_right_clean(space, entry->ie_name, entry);
308 entry = entry->ie_link;
309 }
310 }
311
312 it_entries_free(space->is_table_next-1, table);
313
314 /*
315 * Because the space is now dead,
316 * we must release the "active" reference for it.
317 * Our caller still has his reference.
318 */
319
320 is_release(space);
321 }
322