|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * File: ipc/ipc_pset.c
54: * Author: Rich Draves
55: * Date: 1989
56: *
57: * Functions to manipulate IPC port sets.
58: */
59:
60: #include <mach/port.h>
61: #include <mach/kern_return.h>
62: #include <mach/message.h>
63: #include <ipc/ipc_mqueue.h>
64: #include <ipc/ipc_object.h>
65: #include <ipc/ipc_pset.h>
66: #include <ipc/ipc_right.h>
67: #include <ipc/ipc_space.h>
68: #include <ipc/ipc_port.h>
69: #include <ipc/ipc_print.h>
70: #include <kern/thread_pool.h>
71:
72: /*
73: * Routine: ipc_pset_alloc
74: * Purpose:
75: * Allocate a port set.
76: * Conditions:
77: * Nothing locked. If successful, the port set is returned
78: * locked. (The caller doesn't have a reference.)
79: * Returns:
80: * KERN_SUCCESS The port set is allocated.
81: * KERN_INVALID_TASK The space is dead.
82: * KERN_NO_SPACE No room for an entry in the space.
83: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
84: */
85:
86: kern_return_t
87: ipc_pset_alloc(
88: ipc_space_t space,
89: mach_port_name_t *namep,
90: ipc_pset_t *psetp)
91: {
92: ipc_pset_t pset;
93: mach_port_name_t name;
94: kern_return_t kr;
95:
96: kr = ipc_object_alloc(space, IOT_PORT_SET,
97: MACH_PORT_TYPE_PORT_SET, 0,
98: &name, (ipc_object_t *) &pset);
99: if (kr != KERN_SUCCESS)
100: return kr;
101: /* pset is locked */
102:
103: pset->ips_local_name = name;
104: pset->ips_pset_self = pset;
105: ipc_mqueue_init(&pset->ips_messages, TRUE /* set */);
106: thread_pool_init(&pset->ips_thread_pool);
107:
108: *namep = name;
109: *psetp = pset;
110: return KERN_SUCCESS;
111: }
112:
113: /*
114: * Routine: ipc_pset_alloc_name
115: * Purpose:
116: * Allocate a port set, with a specific name.
117: * Conditions:
118: * Nothing locked. If successful, the port set is returned
119: * locked. (The caller doesn't have a reference.)
120: * Returns:
121: * KERN_SUCCESS The port set is allocated.
122: * KERN_INVALID_TASK The space is dead.
123: * KERN_NAME_EXISTS The name already denotes a right.
124: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
125: */
126:
127: kern_return_t
128: ipc_pset_alloc_name(
129: ipc_space_t space,
130: mach_port_name_t name,
131: ipc_pset_t *psetp)
132: {
133: ipc_pset_t pset;
134: kern_return_t kr;
135:
136:
137: kr = ipc_object_alloc_name(space, IOT_PORT_SET,
138: MACH_PORT_TYPE_PORT_SET, 0,
139: name, (ipc_object_t *) &pset);
140: if (kr != KERN_SUCCESS)
141: return kr;
142: /* pset is locked */
143:
144: pset->ips_local_name = name;
145: pset->ips_pset_self = pset;
146: ipc_mqueue_init(&pset->ips_messages, TRUE /* set */);
147: thread_pool_init(&pset->ips_thread_pool);
148:
149: *psetp = pset;
150: return KERN_SUCCESS;
151: }
152:
153: /*
154: * Routine: ipc_pset_member
155: * Purpose:
156: * Checks to see if a port is a member of a pset
157: * Conditions:
158: * Both port and port set are locked.
159: * The port must be active.
160: */
161: boolean_t
162: ipc_pset_member(
163: ipc_pset_t pset,
164: ipc_port_t port)
165: {
166: assert(ip_active(port));
167:
168: return (ipc_mqueue_member(&port->ip_messages, &pset->ips_messages));
169: }
170:
171:
172: /*
173: * Routine: ipc_pset_add
174: * Purpose:
175: * Puts a port into a port set.
176: * The port set gains a reference.
177: * Conditions:
178: * Both port and port set are locked and active.
179: * The owner of the port set is also receiver for the port.
180: */
181:
182: kern_return_t
183: ipc_pset_add(
184: ipc_pset_t pset,
185: ipc_port_t port)
186: {
187: assert(ips_active(pset));
188: assert(ip_active(port));
189:
190: if (ipc_pset_member(pset, port))
191: return KERN_ALREADY_IN_SET;
192:
193: ips_reference(pset);
194: port->ip_pset_count++;
195:
196: ipc_mqueue_add(&port->ip_messages, &pset->ips_messages);
197:
198: return KERN_SUCCESS;
199: }
200:
201:
202:
203: /*
204: * Routine: ipc_pset_remove
205: * Purpose:
206: * Removes a port from a port set.
207: * The port set loses a reference.
208: * Conditions:
209: * Both port and port set are locked.
210: * The port must be active.
211: */
212:
213: kern_return_t
214: ipc_pset_remove(
215: ipc_pset_t pset,
216: ipc_port_t port)
217: {
218: mach_msg_return_t mr;
219:
220: assert(ip_active(port));
221:
222: if (port->ip_pset_count == 0)
223: return KERN_NOT_IN_SET;
224:
225: mr = ipc_mqueue_remove(&port->ip_messages, &pset->ips_messages);
226:
227: if (mr == MACH_MSG_SUCCESS) {
228: port->ip_pset_count--;
229: ips_release(pset);
230: }
231: return mr;
232: }
233:
234: /*
235: * Routine: ipc_pset_remove_all
236: * Purpose:
237: * Removes a port from all it's port sets.
238: * Each port set loses a reference.
239: * Conditions:
240: * port is locked and active.
241: */
242:
243: kern_return_t
244: ipc_pset_remove_all(
245: ipc_port_t port)
246: {
247: ipc_pset_mqueue_t pset_mqueue;
248: ipc_pset_t pset;
249:
250: assert(ip_active(port));
251:
252: if (port->ip_pset_count == 0)
253: return KERN_NOT_IN_SET;
254:
255: /*
256: * Remove each port set's mqueue from the port's (one at a time).
257: */
258: for (;;) {
259: ipc_mqueue_remove_one(&port->ip_messages,
260: (ipc_mqueue_t)&pset_mqueue);
261: if (pset_mqueue == (ipc_pset_mqueue_t)0)
262: break;
263:
264: pset = pset_mqueue->ipsm_pset;
265: ips_release(pset);
266:
267: port->ip_pset_count--;
268: }
269:
270: assert(port->ip_pset_count == 0);
271: return KERN_SUCCESS;
272: }
273:
274:
275: /*
276: * Routine: ipc_pset_destroy
277: * Purpose:
278: * Destroys a port_set.
279: *
280: * Doesn't remove members from the port set;
281: * that happens lazily.
282: * Conditions:
283: * The port_set is locked and alive.
284: * The caller has a reference, which is consumed.
285: * Afterwards, the port_set is unlocked and dead.
286: */
287:
288: void
289: ipc_pset_destroy(
290: ipc_pset_t pset)
291: {
292: assert(ips_active(pset));
293:
294: pset->ips_object.io_bits &= ~IO_BITS_ACTIVE;
295:
296: imq_lock(&pset->ips_messages);
297: ipc_mqueue_changed(&pset->ips_messages);
298: imq_unlock(&pset->ips_messages);
299:
300: /* XXXX Perhaps ought to verify ips_thread_pool is empty */
301:
302: ips_release(pset); /* consume the ref our caller gave us */
303: ips_check_unlock(pset);
304: }
305:
306: #include <mach_kdb.h>
307: #if MACH_KDB
308:
309: #include <ddb/db_output.h>
310:
311: #define printf kdbprintf
312:
313: int
314: ipc_list_count(
315: struct ipc_kmsg *base)
316: {
317: register int count = 0;
318:
319: if (base) {
320: struct ipc_kmsg *kmsg = base;
321:
322: ++count;
323: while (kmsg && kmsg->ikm_next != base
324: && kmsg->ikm_next != IKM_BOGUS){
325: kmsg = kmsg->ikm_next;
326: ++count;
327: }
328: }
329: return(count);
330: }
331:
332: /*
333: * Routine: ipc_pset_print
334: * Purpose:
335: * Pretty-print a port set for kdb.
336: */
337:
338: void
339: ipc_pset_print(
340: ipc_pset_t pset)
341: {
342: extern int db_indent;
343:
344: printf("pset 0x%x\n", pset);
345:
346: db_indent += 2;
347:
348: ipc_object_print(&pset->ips_object);
349: iprintf("local_name = 0x%x\n", pset->ips_local_name);
350: iprintf("%d kmsgs => 0x%x",
351: ipc_list_count(pset->ips_messages.imq_messages.ikmq_base),
352: pset->ips_messages.imq_messages.ikmq_base);
353: printf(",rcvrs queue= 0x%x\n", &pset->ips_messages.imq_wait_queue);
354:
355: db_indent -=2;
356: }
357:
358: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.