|
|
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) 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_port.h
75: * Author: Rich Draves
76: * Date: 1989
77: *
78: * Definitions for ports.
79: */
80:
81: #ifndef _IPC_IPC_PORT_H_
82: #define _IPC_IPC_PORT_H_
83:
84: #import <mach/features.h>
85:
86: #include <mach/boolean.h>
87: #include <mach/kern_return.h>
88: #include <mach/port.h>
89: #include <kern/lock.h>
90: #include <kern/macro_help.h>
91: #include <kern/ipc_kobject.h>
92: #include <ipc/ipc_object.h>
93: #include <ipc/ipc_mqueue.h>
94: #include <ipc/ipc_table.h>
95: #include <ipc/ipc_thread.h>
96:
97: /*
98: * A receive right (port) can be in four states:
99: * 1) dead (not active, ip_timestamp has death time)
100: * 2) in a space (ip_receiver_name != 0, ip_receiver points
101: * to the space but doesn't hold a ref for it)
102: * 3) in transit (ip_receiver_name == 0, ip_destination points
103: * to the destination port and holds a ref for it)
104: * 4) in limbo (ip_receiver_name == 0, ip_destination == IP_NULL)
105: *
106: * If the port is active, and ip_receiver points to some space,
107: * then ip_receiver_name != 0, and that space holds receive rights.
108: * If the port is not active, then ip_timestamp contains a timestamp
109: * taken when the port was destroyed.
110: */
111:
112: typedef unsigned int ipc_port_timestamp_t;
113:
114: struct ipc_port {
115: struct ipc_object ip_object;
116:
117: union {
118: struct ipc_space *receiver;
119: struct ipc_port *destination;
120: ipc_port_timestamp_t timestamp;
121: } data;
122: mach_port_t ip_receiver_name;
123:
124: ipc_kobject_t ip_kobject;
125:
126: mach_port_mscount_t ip_mscount;
127: mach_port_rights_t ip_srights;
128: mach_port_rights_t ip_sorights;
129:
130: struct ipc_port *ip_nsrequest;
131: struct ipc_port *ip_pdrequest;
132: struct ipc_port_request *ip_dnrequests;
133:
134: struct ipc_pset *ip_pset;
135: mach_port_seqno_t ip_seqno; /* locked by message queue */
136: mach_port_msgcount_t ip_msgcount;
137: mach_port_msgcount_t ip_qlimit;
138: struct ipc_mqueue ip_messages;
139: struct ipc_thread_queue ip_blocked;
140: };
141:
142: #define ip_references ip_object.io_references
143: #define ip_bits ip_object.io_bits
144: #define ip_receiver data.receiver
145: #define ip_destination data.destination
146: #define ip_timestamp data.timestamp
147:
148: #define IP_NULL ((ipc_port_t) IO_NULL)
149: #define IP_DEAD ((ipc_port_t) IO_DEAD)
150:
151: #define IP_VALID(port) IO_VALID(&(port)->ip_object)
152:
153: #define ip_active(port) io_active(&(port)->ip_object)
154: #define ip_lock_init(port) io_lock_init(&(port)->ip_object)
155: #define ip_lock(port) io_lock(&(port)->ip_object)
156: #define ip_lock_try(port) io_lock_try(&(port)->ip_object)
157: #define ip_unlock(port) io_unlock(&(port)->ip_object)
158: #define ip_check_unlock(port) io_check_unlock(&(port)->ip_object)
159: #define ip_reference(port) io_reference(&(port)->ip_object)
160: #define ip_release(port) io_release(&(port)->ip_object)
161:
162: #define ip_alloc() ((ipc_port_t) io_alloc(IOT_PORT))
163: #define ip_free(port) io_free(IOT_PORT, &(port)->ip_object)
164:
165: #define ip_kotype(port) io_kotype(&(port)->ip_object)
166:
167: typedef ipc_table_index_t ipc_port_request_index_t;
168:
169: typedef struct ipc_port_request {
170: union {
171: struct ipc_port *port;
172: ipc_port_request_index_t index;
173: } notify;
174:
175: union {
176: mach_port_t name;
177: struct ipc_table_size *size;
178: } name;
179: } *ipc_port_request_t;
180:
181: #define ipr_next notify.index
182: #define ipr_size name.size
183:
184: #define ipr_soright notify.port
185: #define ipr_name name.name
186:
187: #define IPR_NULL ((ipc_port_request_t) 0)
188:
189: #if MACH_IPC_COMPAT
190: /*
191: * For backwards compatibility, the ip_pdrequest field can hold a
192: * send right instead of a send-once right. This is indicated by
193: * the low bit of the pointer. This works because the zone package
194: * guarantees that the two low bits of port pointers are zero.
195: */
196:
197: #define ip_pdsendp(soright) ((unsigned int)(soright) & 1)
198: #define ip_pdsend(soright) ((ipc_port_t)((unsigned int)(soright) &~ 1))
199: #define ip_pdsendm(sright) ((ipc_port_t)((unsigned int)(sright) | 1))
200:
201: /*
202: * For backwards compatibility, the ipr_soright field can hold
203: * a space pointer. This is indicated by the low bit of the pointer.
204: * This works because the zone package guarantees that the two low
205: * bits of port and space pointers are zero.
206: */
207:
208: #define ipr_spacep(soright) ((unsigned int)(soright) & 1)
209: #define ipr_space(soright) ((ipc_space_t)((unsigned int)(soright) &~ 1))
210: #define ipr_spacem(space) ((ipc_port_t)((unsigned int)(space) | 1))
211: #endif /* MACH_IPC_COMPAT */
212:
213: /*
214: * Taking the ipc_port_multiple lock grants the privilege
215: * to lock multiple ports at once. No ports must locked
216: * when it is taken.
217: */
218:
219: decl_simple_lock_data(extern, ipc_port_multiple_lock_data)
220:
221: #define ipc_port_multiple_lock_init() \
222: simple_lock_init(&ipc_port_multiple_lock_data)
223:
224: #define ipc_port_multiple_lock() \
225: simple_lock(&ipc_port_multiple_lock_data)
226:
227: #define ipc_port_multiple_unlock() \
228: simple_unlock(&ipc_port_multiple_lock_data)
229:
230: /*
231: * The port timestamp facility provides timestamps
232: * for port destruction. It is used to serialize
233: * mach_port_names with port death.
234: */
235:
236: decl_simple_lock_data(extern, ipc_port_timestamp_lock_data)
237: extern ipc_port_timestamp_t ipc_port_timestamp_data;
238:
239: #define ipc_port_timestamp_lock_init() \
240: simple_lock_init(&ipc_port_timestamp_lock_data)
241:
242: #define ipc_port_timestamp_lock() \
243: simple_lock(&ipc_port_timestamp_lock_data)
244:
245: #define ipc_port_timestamp_unlock() \
246: simple_unlock(&ipc_port_timestamp_lock_data)
247:
248: /* Retrieve a port timestamp value */
249: extern ipc_port_timestamp_t ipc_port_timestamp(void);
250:
251: /*
252: * Compares two timestamps, and returns TRUE if one
253: * happened before two. Note that this formulation
254: * works when the timestamp wraps around at 2^32,
255: * as long as one and two aren't too far apart.
256: */
257:
258: #define IP_TIMESTAMP_ORDER(one, two) ((int) ((one) - (two)) < 0)
259:
260: #define ipc_port_translate_receive(space, name, portp) \
261: ipc_object_translate((space), (name), \
262: MACH_PORT_RIGHT_RECEIVE, \
263: (ipc_object_t *) (portp))
264:
265: #define ipc_port_translate_send(space, name, portp) \
266: ipc_object_translate((space), (name), \
267: MACH_PORT_RIGHT_SEND, \
268: (ipc_object_t *) (portp))
269:
270: /* Allocate a dead-name request slot */
271: extern kern_return_t
272: ipc_port_dnrequest(
273: ipc_port_t port,
274: mach_port_t name,
275: ipc_port_t soright,
276: ipc_port_request_index_t *indexp);
277:
278: /* Grow a port's table of dead-name requests */
279: extern kern_return_t ipc_port_dngrow(
280: ipc_port_t port,
281: int target_size);
282:
283: /* Cancel a dead-name request and return the send-once right */
284: extern ipc_port_t ipc_port_dncancel(
285: ipc_port_t port,
286: mach_port_t name,
287: ipc_port_request_index_t index);
288:
289: #define ipc_port_dnrename(port, index, oname, nname) \
290: MACRO_BEGIN \
291: ipc_port_request_t ipr, table; \
292: \
293: assert(ip_active(port)); \
294: \
295: table = port->ip_dnrequests; \
296: assert(table != IPR_NULL); \
297: \
298: ipr = &table[index]; \
299: assert(ipr->ipr_name == oname); \
300: \
301: ipr->ipr_name = nname; \
302: MACRO_END
303:
304: /* Make a port-deleted request */
305: extern void ipc_port_pdrequest(
306: ipc_port_t port,
307: ipc_port_t notify,
308: ipc_port_t *previousp);
309:
310: /* Make a no-senders request */
311: extern void ipc_port_nsrequest(
312: ipc_port_t port,
313: mach_port_mscount_t sync,
314: ipc_port_t notify,
315: ipc_port_t *previousp);
316:
317: /* Change a port's queue limit */
318: extern void ipc_port_set_qlimit(
319: ipc_port_t port,
320: mach_port_msgcount_t qlimit);
321:
322: #define ipc_port_set_mscount(port, mscount) \
323: MACRO_BEGIN \
324: assert(ip_active(port)); \
325: \
326: (port)->ip_mscount = (mscount); \
327: MACRO_END
328:
329: /* Change a port's sequence number */
330: extern void ipc_port_set_seqno(
331: ipc_port_t port,
332: mach_port_seqno_t seqno);
333:
334: /* Prepare a receive right for transmission/destruction */
335: extern void ipc_port_clear_receiver(
336: ipc_port_t port);
337:
338: /* Initialize a newly-allocated port */
339: extern void ipc_port_init(
340: ipc_port_t port,
341: ipc_space_t space,
342: mach_port_t name);
343:
344: /* Allocate a port */
345: extern kern_return_t ipc_port_alloc(
346: ipc_space_t space,
347: mach_port_t *namep,
348: ipc_port_t *portp);
349:
350: /* Allocate a port, with a specific name */
351: extern kern_return_t ipc_port_alloc_name(
352: ipc_space_t space,
353: mach_port_t name,
354: ipc_port_t *portp);
355:
356: /* Destroy a port */
357: extern void ipc_port_destroy(
358: ipc_port_t port);
359:
360: /* Check if queueing "port" in a message for "dest" would create a circular
361: group of ports and messages */
362: extern boolean_t
363: ipc_port_check_circularity(
364: ipc_port_t port,
365: ipc_port_t dest);
366:
367: /* Make a send-once notify port from a receive right */
368: extern ipc_port_t ipc_port_lookup_notify(
369: ipc_space_t space,
370: mach_port_t name);
371:
372: /* Make a naked send right from a receive right */
373: extern ipc_port_t ipc_port_make_send(
374: ipc_port_t port);
375:
376: /* Make a naked send right from another naked send right */
377: extern ipc_port_t ipc_port_copy_send(
378: ipc_port_t port);
379:
380: /* Copyout a naked send right */
381: extern mach_port_t ipc_port_copyout_send(
382: ipc_port_t sright,
383: ipc_space_t space);
384:
385: /* Release a (valid) naked send right */
386: extern void ipc_port_release_send(
387: ipc_port_t port);
388:
389: /* Make a naked send-once right from a receive right */
390: extern ipc_port_t ipc_port_make_sonce(
391: ipc_port_t port);
392:
393: /* Release a naked send-once right */
394: extern void ipc_port_release_sonce(
395: ipc_port_t port);
396:
397: /* Release a naked (in limbo or in transit) receive right */
398: extern void ipc_port_release_receive(
399: ipc_port_t port);
400:
401: /* Allocate a port in a special space */
402: extern ipc_port_t ipc_port_alloc_special(
403: ipc_space_t space);
404:
405: /* Deallocate a port in a special space */
406: extern void ipc_port_dealloc_special(
407: ipc_port_t port,
408: ipc_space_t space);
409:
410: #define ipc_port_alloc_kernel() \
411: ipc_port_alloc_special(ipc_space_kernel)
412: #define ipc_port_dealloc_kernel(port) \
413: ipc_port_dealloc_special((port), ipc_space_kernel)
414:
415: #define ipc_port_alloc_reply() \
416: ipc_port_alloc_special(ipc_space_reply)
417: #define ipc_port_dealloc_reply(port) \
418: ipc_port_dealloc_special((port), ipc_space_reply)
419:
420: #define ipc_port_reference(port) \
421: ipc_object_reference(&(port)->ip_object)
422:
423: #define ipc_port_release(port) \
424: ipc_object_release(&(port)->ip_object)
425:
426: #if MACH_IPC_COMPAT
427:
428: extern kern_return_t
429: ipc_port_alloc_compat(/* ipc_space_t, mach_port_t *, ipc_port_t * */);
430:
431: extern mach_port_t
432: ipc_port_copyout_send_compat(/* ipc_port_t, ipc_space_t */);
433:
434: extern mach_port_t
435: ipc_port_copyout_receiver(/* ipc_port_t, ipc_space_t */);
436:
437: #endif /* MACH_IPC_COMPAT */
438:
439: extern void
440: ipc_port_print(/* ipc_port_t */);
441:
442: #endif /* _IPC_IPC_PORT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.