xref: /trueos/sys/compat/mach/ipc/ipc_space.c (revision c618297218800e84f1cdd1070cad32c285e84a86)
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