|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: */
31: /*
32: * File: ipc/ipc_port.h
33: * Author: Rich Draves
34: * Date: 1989
35: *
36: * Definitions for ports.
37: */
38:
39: #ifndef _IPC_IPC_PORT_H_
40: #define _IPC_IPC_PORT_H_
41:
42: #include <mach_ipc_compat.h>
43: #include <norma_ipc.h>
44:
45: #include <mach/boolean.h>
46: #include <mach/kern_return.h>
47: #include <mach/port.h>
48: #include <kern/lock.h>
49: #include <kern/macro_help.h>
50: #include <kern/ipc_kobject.h>
51: #include <ipc/ipc_mqueue.h>
52: #include <ipc/ipc_table.h>
53: #include <ipc/ipc_thread.h>
54: #include "ipc_target.h"
55: #include <mach/rpc.h>
56:
57: /*
58: * A receive right (port) can be in four states:
59: * 1) dead (not active, ip_timestamp has death time)
60: * 2) in a space (ip_receiver_name != 0, ip_receiver points
61: * to the space but doesn't hold a ref for it)
62: * 3) in transit (ip_receiver_name == 0, ip_destination points
63: * to the destination port and holds a ref for it)
64: * 4) in limbo (ip_receiver_name == 0, ip_destination == IP_NULL)
65: *
66: * If the port is active, and ip_receiver points to some space,
67: * then ip_receiver_name != 0, and that space holds receive rights.
68: * If the port is not active, then ip_timestamp contains a timestamp
69: * taken when the port was destroyed.
70: */
71:
72: typedef unsigned int ipc_port_timestamp_t;
73:
74: struct ipc_port {
75: struct ipc_target ip_target;
76:
77: /* This points to the ip_target above if this port isn't on a port set;
78: otherwise it points to the port set's ips_target. */
79: struct ipc_target *ip_cur_target;
80:
81: union {
82: struct ipc_space *receiver;
83: struct ipc_port *destination;
84: ipc_port_timestamp_t timestamp;
85: } data;
86:
87: ipc_kobject_t ip_kobject;
88:
89: mach_port_mscount_t ip_mscount;
90: mach_port_rights_t ip_srights;
91: mach_port_rights_t ip_sorights;
92:
93: struct ipc_port *ip_nsrequest;
94: struct ipc_port *ip_pdrequest;
95: struct ipc_port_request *ip_dnrequests;
96:
97: struct ipc_pset *ip_pset;
98: mach_port_seqno_t ip_seqno; /* locked by message queue */
99: mach_port_msgcount_t ip_msgcount;
100: mach_port_msgcount_t ip_qlimit;
101: struct ipc_thread_queue ip_blocked;
102:
103: #if NORMA_IPC
104: unsigned long ip_norma_uid;
105: unsigned long ip_norma_dest_node;
106: long ip_norma_stransit;
107: long ip_norma_sotransit;
108: long ip_norma_xmm_object_refs;
109: boolean_t ip_norma_is_proxy;
110: boolean_t ip_norma_is_special;
111: struct ipc_port *ip_norma_atrium;
112: struct ipc_port *ip_norma_queue_next;
113: struct ipc_port *ip_norma_xmm_object;
114: struct ipc_port *ip_norma_next;
115: long ip_norma_spare1;
116: long ip_norma_spare2;
117: long ip_norma_spare3;
118: long ip_norma_spare4;
1.1.1.2 ! root 119: #endif /* NORMA_IPC */
1.1 root 120: };
121:
122: #define ip_object ip_target.ipt_object
123: #define ip_receiver_name ip_target.ipt_name
124: #define ip_messages ip_target.ipt_messages
125: #define ip_references ip_object.io_references
126: #define ip_bits ip_object.io_bits
127: #define ip_receiver data.receiver
128: #define ip_destination data.destination
129: #define ip_timestamp data.timestamp
130:
131: #define IP_NULL ((ipc_port_t) IO_NULL)
132: #define IP_DEAD ((ipc_port_t) IO_DEAD)
133:
134: #define IP_VALID(port) IO_VALID(&(port)->ip_object)
135:
136: #define ip_active(port) io_active(&(port)->ip_object)
137: #define ip_lock_init(port) io_lock_init(&(port)->ip_object)
138: #define ip_lock(port) io_lock(&(port)->ip_object)
139: #define ip_lock_try(port) io_lock_try(&(port)->ip_object)
140: #define ip_unlock(port) io_unlock(&(port)->ip_object)
141: #define ip_check_unlock(port) io_check_unlock(&(port)->ip_object)
142: #define ip_reference(port) io_reference(&(port)->ip_object)
143: #define ip_release(port) io_release(&(port)->ip_object)
144:
145: #define ip_alloc() ((ipc_port_t) io_alloc(IOT_PORT))
146: #define ip_free(port) io_free(IOT_PORT, &(port)->ip_object)
147:
148: #define ip_kotype(port) io_kotype(&(port)->ip_object)
149:
150: typedef ipc_table_index_t ipc_port_request_index_t;
151:
152: typedef struct ipc_port_request {
153: union {
154: struct ipc_port *port;
155: ipc_port_request_index_t index;
156: } notify;
157:
158: union {
159: mach_port_t name;
160: struct ipc_table_size *size;
161: } name;
162: } *ipc_port_request_t;
163:
164: #define ipr_next notify.index
165: #define ipr_size name.size
166:
167: #define ipr_soright notify.port
168: #define ipr_name name.name
169:
170: #define IPR_NULL ((ipc_port_request_t) 0)
171:
172: #if MACH_IPC_COMPAT
173: /*
174: * For backwards compatibility, the ip_pdrequest field can hold a
175: * send right instead of a send-once right. This is indicated by
176: * the low bit of the pointer. This works because the zone package
177: * guarantees that the two low bits of port pointers are zero.
178: */
179:
180: #define ip_pdsendp(soright) ((unsigned int)(soright) & 1)
181: #define ip_pdsend(soright) ((ipc_port_t)((unsigned int)(soright) &~ 1))
182: #define ip_pdsendm(sright) ((ipc_port_t)((unsigned int)(sright) | 1))
183:
184: /*
185: * For backwards compatibility, the ipr_soright field can hold
186: * a space pointer. This is indicated by the low bit of the pointer.
187: * This works because the zone package guarantees that the two low
188: * bits of port and space pointers are zero.
189: */
190:
191: #define ipr_spacep(soright) ((unsigned int)(soright) & 1)
192: #define ipr_space(soright) ((ipc_space_t)((unsigned int)(soright) &~ 1))
193: #define ipr_spacem(space) ((ipc_port_t)((unsigned int)(space) | 1))
1.1.1.2 ! root 194: #endif /* MACH_IPC_COMPAT */
1.1 root 195:
196: /*
197: * Taking the ipc_port_multiple lock grants the privilege
198: * to lock multiple ports at once. No ports must locked
199: * when it is taken.
200: */
201:
202: decl_simple_lock_data(extern, ipc_port_multiple_lock_data)
203:
204: #define ipc_port_multiple_lock_init() \
205: simple_lock_init(&ipc_port_multiple_lock_data)
206:
207: #define ipc_port_multiple_lock() \
208: simple_lock(&ipc_port_multiple_lock_data)
209:
210: #define ipc_port_multiple_unlock() \
211: simple_unlock(&ipc_port_multiple_lock_data)
212:
213: /*
214: * The port timestamp facility provides timestamps
215: * for port destruction. It is used to serialize
216: * mach_port_names with port death.
217: */
218:
219: decl_simple_lock_data(extern, ipc_port_timestamp_lock_data)
220: extern ipc_port_timestamp_t ipc_port_timestamp_data;
221:
222: #define ipc_port_timestamp_lock_init() \
223: simple_lock_init(&ipc_port_timestamp_lock_data)
224:
225: #define ipc_port_timestamp_lock() \
226: simple_lock(&ipc_port_timestamp_lock_data)
227:
228: #define ipc_port_timestamp_unlock() \
229: simple_unlock(&ipc_port_timestamp_lock_data)
230:
231: extern ipc_port_timestamp_t
232: ipc_port_timestamp();
233:
234: /*
235: * Compares two timestamps, and returns TRUE if one
236: * happened before two. Note that this formulation
237: * works when the timestamp wraps around at 2^32,
238: * as long as one and two aren't too far apart.
239: */
240:
241: #define IP_TIMESTAMP_ORDER(one, two) ((int) ((one) - (two)) < 0)
242:
243: #define ipc_port_translate_receive(space, name, portp) \
244: ipc_object_translate((space), (name), \
245: MACH_PORT_RIGHT_RECEIVE, \
246: (ipc_object_t *) (portp))
247:
248: #define ipc_port_translate_send(space, name, portp) \
249: ipc_object_translate((space), (name), \
250: MACH_PORT_RIGHT_SEND, \
251: (ipc_object_t *) (portp))
252:
253: extern kern_return_t
254: ipc_port_dnrequest(/* ipc_port_t, mach_port_t, ipc_port_t,
255: ipc_port_request_index_t * */);
256:
257: extern kern_return_t
258: ipc_port_dngrow(/* ipc_port_t */);
259:
260: extern ipc_port_t
261: ipc_port_dncancel(/* ipc_port_t, mach_port_t, ipc_port_request_index_t */);
262:
263: #define ipc_port_dnrename(port, index, oname, nname) \
264: MACRO_BEGIN \
265: ipc_port_request_t ipr, table; \
266: \
267: assert(ip_active(port)); \
268: \
269: table = port->ip_dnrequests; \
270: assert(table != IPR_NULL); \
271: \
272: ipr = &table[index]; \
273: assert(ipr->ipr_name == oname); \
274: \
275: ipr->ipr_name = nname; \
276: MACRO_END
277:
278: /* Make a port-deleted request */
279: extern void ipc_port_pdrequest(
280: ipc_port_t port,
281: ipc_port_t notify,
282: ipc_port_t *previousp);
283:
284: /* Make a no-senders request */
285: extern void ipc_port_nsrequest(
286: ipc_port_t port,
287: mach_port_mscount_t sync,
288: ipc_port_t notify,
289: ipc_port_t *previousp);
290:
291: /* Change a port's queue limit */
292: extern void ipc_port_set_qlimit(
293: ipc_port_t port,
294: mach_port_msgcount_t qlimit);
295:
296: #define ipc_port_set_mscount(port, mscount) \
297: MACRO_BEGIN \
298: assert(ip_active(port)); \
299: \
300: (port)->ip_mscount = (mscount); \
301: MACRO_END
302:
303: extern struct ipc_mqueue *
304: ipc_port_lock_mqueue(/* ipc_port_t */);
305:
306: extern void
307: ipc_port_set_seqno(/* ipc_port_t, mach_port_seqno_t */);
308:
309: extern void
310: ipc_port_clear_receiver(/* ipc_port_t */);
311:
312: extern void
313: ipc_port_init(/* ipc_port_t, ipc_space_t, mach_port_t */);
314:
315: extern kern_return_t
316: ipc_port_alloc(/* ipc_space_t, mach_port_t *, ipc_port_t * */);
317:
318: extern kern_return_t
319: ipc_port_alloc_name(/* ipc_space_t, mach_port_t, ipc_port_t * */);
320:
321: extern void
322: ipc_port_destroy(/* ipc_port_t */);
323:
324: extern boolean_t
325: ipc_port_check_circularity(/* ipc_port_t, ipc_port_t */);
326:
327: extern ipc_port_t
328: ipc_port_lookup_notify(/* ipc_space_t, mach_port_t */);
329:
330: extern ipc_port_t
331: ipc_port_make_send(/* ipc_port_t */);
332:
333: extern ipc_port_t
334: ipc_port_copy_send(/* ipc_port_t */);
335:
336: extern mach_port_t
337: ipc_port_copyout_send(/* ipc_port_t, ipc_space_t */);
338:
339: extern void
340: ipc_port_release_send(/* ipc_port_t */);
341:
342: extern ipc_port_t
343: ipc_port_make_sonce(/* ipc_port_t */);
344:
345: extern void
346: ipc_port_release_sonce(/* ipc_port_t */);
347:
348: extern void
349: ipc_port_release_receive(/* ipc_port_t */);
350:
351: extern ipc_port_t
352: ipc_port_alloc_special(/* ipc_space_t */);
353:
354: extern void
355: ipc_port_dealloc_special(/* ipc_port_t */);
356:
357: #define ipc_port_alloc_kernel() \
358: ipc_port_alloc_special(ipc_space_kernel)
359: #define ipc_port_dealloc_kernel(port) \
360: ipc_port_dealloc_special((port), ipc_space_kernel)
361:
362: #define ipc_port_alloc_reply() \
363: ipc_port_alloc_special(ipc_space_reply)
364: #define ipc_port_dealloc_reply(port) \
365: ipc_port_dealloc_special((port), ipc_space_reply)
366:
367: #define ipc_port_reference(port) \
368: ipc_object_reference(&(port)->ip_object)
369:
370: #define ipc_port_release(port) \
371: ipc_object_release(&(port)->ip_object)
372:
373: #if MACH_IPC_COMPAT
374:
375: extern kern_return_t
376: ipc_port_alloc_compat(/* ipc_space_t, mach_port_t *, ipc_port_t * */);
377:
378: extern mach_port_t
379: ipc_port_copyout_send_compat(/* ipc_port_t, ipc_space_t */);
380:
381: extern mach_port_t
382: ipc_port_copyout_receiver(/* ipc_port_t, ipc_space_t */);
383:
1.1.1.2 ! root 384: #endif /* MACH_IPC_COMPAT */
1.1 root 385:
386: extern void
387: ipc_port_print(/* ipc_port_t */);
388:
389: #if NORMA_IPC
390:
391: #define IP_NORMA_IS_PROXY(port) ((port)->ip_norma_is_proxy)
392:
393: /*
394: * A proxy never has a real nsrequest, but is always has a fake
395: * nsrequest so that the norma ipc system is notified when there
396: * are no send rights for a proxy. A fake nsrequest is indicated by
397: * the low bit of the pointer. This works because the zone package
398: * guarantees that the two low bits of port pointers are zero.
399: */
400:
401: #define ip_nsproxyp(nsrequest) ((unsigned int)(nsrequest) & 1)
402: #define ip_nsproxy(nsrequest) ((ipc_port_t)((unsigned int)(nsrequest) &~ 1))
403: #define ip_nsproxym(proxy) ((ipc_port_t)((unsigned int)(proxy) | 1))
404:
1.1.1.2 ! root 405: #endif /* NORMA_IPC */
1.1 root 406:
1.1.1.2 ! root 407: #endif /* _IPC_IPC_PORT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.