|
|
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_port.h
54: * Author: Rich Draves
55: * Date: 1989
56: *
57: * Definitions for ports.
58: */
59:
60: #ifndef _IPC_IPC_PORT_H_
61: #define _IPC_IPC_PORT_H_
62:
63: #include <dipc.h>
64: #include <norma_vm.h>
65: #include <mach_rt.h>
66: #include <mach_assert.h>
67: #include <mach_debug.h>
68:
69: #include <mach/boolean.h>
70: #include <mach/kern_return.h>
71: #include <mach_debug.h>
72: #include <mach/port.h>
73: #include <kern/lock.h>
74: #include <kern/ipc_kobject.h>
75: #include <kern/wait_queue.h>
76: #include <kern/thread_pool.h>
77:
78: #include <ipc/ipc_object.h>
79: #include <ipc/ipc_mqueue.h>
80: #include <ipc/ipc_table.h>
81: #include <ipc/ipc_types.h>
82: #include <ipc/ipc_entry.h>
83:
84: /*
85: * A receive right (port) can be in four states:
86: * 1) dead (not active, ip_timestamp has death time)
87: * 2) in a space (ip_receiver_name != 0, ip_receiver points
88: * to the space but doesn't hold a ref for it)
89: * 3) in transit (ip_receiver_name == 0, ip_destination points
90: * to the destination port and holds a ref for it)
91: * 4) in limbo (ip_receiver_name == 0, ip_destination == IP_NULL)
92: *
93: * If the port is active, and ip_receiver points to some space,
94: * then ip_receiver_name != 0, and that space holds receive rights.
95: * If the port is not active, then ip_timestamp contains a timestamp
96: * taken when the port was destroyed.
97: */
98:
99: typedef unsigned int ipc_port_timestamp_t;
100:
101: typedef unsigned int ipc_port_flags_t;
102:
103: struct ipc_port {
104:
105: /*
106: * Initial sub-structure in common with ipc_pset and rpc_port
107: * First element is an ipc_object
108: */
109: struct ipc_object ip_object;
110:
111: union {
112: struct ipc_space *receiver;
113: struct ipc_port *destination;
114: ipc_port_timestamp_t timestamp;
115: } data;
116:
117: ipc_kobject_t ip_kobject;
118: struct rpc_subsystem * ip_subsystem;
119: mach_port_mscount_t ip_mscount;
120: mach_port_rights_t ip_srights;
121: mach_port_rights_t ip_sorights;
122:
123: struct ipc_port *ip_nsrequest;
124: struct ipc_port *ip_pdrequest;
125: struct ipc_port_request *ip_dnrequests;
126:
127: unsigned int ip_pset_count;
128: struct ipc_mqueue ip_messages;
129: ipc_port_flags_t ip_flags;
130:
131: #if NORMA_VM
132: /*
133: * These fields are needed for the use of XMM.
134: * Few ports need this information; it should
135: * be kept in XMM instead (TBD). XXX
136: */
137: long ip_norma_xmm_object_refs;
138: struct ipc_port *ip_norma_xmm_object;
139: #endif
140:
141: #if MACH_ASSERT
142: #define IP_NSPARES 10
143: #define IP_CALLSTACK_MAX 10
144: queue_chain_t ip_port_links; /* all allocated ports */
145: natural_t ip_thread; /* who made me? thread context */
146: unsigned long ip_timetrack; /* give an idea of "when" created */
147: natural_t ip_callstack[IP_CALLSTACK_MAX]; /* stack trace */
148: unsigned long ip_spares[IP_NSPARES]; /* for debugging */
149: #endif /* MACH_ASSERT */
150: int alias;
151: };
152:
153:
154: #define ip_references ip_object.io_references
155: #define ip_bits ip_object.io_bits
156: #define ip_receiver_name ip_object.io_receiver_name
157:
158: #define ip_thread_pool ip_object.io_thread_pool
159:
160: #define ip_receiver data.receiver
161: #define ip_destination data.destination
162: #define ip_timestamp data.timestamp
163:
164: #define IP_NULL IPC_PORT_NULL
165: #define IP_DEAD IPC_PORT_DEAD
166: #define IP_VALID(port) IPC_PORT_VALID(port)
167:
168: #define ip_active(port) io_active(&(port)->ip_object)
169: #define ip_lock_init(port) io_lock_init(&(port)->ip_object)
170: #define ip_lock(port) io_lock(&(port)->ip_object)
171: #define ip_lock_try(port) io_lock_try(&(port)->ip_object)
172: #define ip_unlock(port) io_unlock(&(port)->ip_object)
173: #define ip_check_unlock(port) io_check_unlock(&(port)->ip_object)
174:
175: #define ip_reference(port) io_reference(&(port)->ip_object)
176: #define ip_release(port) io_release(&(port)->ip_object)
177:
178: #define ip_kotype(port) io_kotype(&(port)->ip_object)
179:
180: #if MACH_RT
181: #define IPC_PORT_FLAGS_RT ((ipc_port_flags_t)(1 << 0))
182: #define IP_RT(port) (((port)->ip_flags & IPC_PORT_FLAGS_RT) != 0)
183: #else /* MACH_RT */
184: #define IP_RT(port) (0)
185: #endif /* MACH_RT */
186:
187: /*
188: * No more senders information.
189: */
190: #define IP_BIT_NMS 0x00008000 /* nms detection enabled? */
191: #define IP_SET_NMS(port) ((port)->ip_bits |= IP_BIT_NMS)
192: #define IP_CLEAR_NMS(port) ((port)->ip_bits &= ~IP_BIT_NMS)
193: #define IP_NMS(port) ((port)->ip_bits & IP_BIT_NMS)
194:
195: typedef ipc_table_index_t ipc_port_request_index_t;
196:
197: typedef struct ipc_port_request {
198: union {
199: struct ipc_port *port;
200: ipc_port_request_index_t index;
201: } notify;
202:
203: union {
204: mach_port_name_t name;
205: struct ipc_table_size *size;
206: } name;
207: } *ipc_port_request_t;
208:
209: #define ipr_next notify.index
210: #define ipr_size name.size
211:
212: #define ipr_soright notify.port
213: #define ipr_name name.name
214:
215: #define IPR_NULL ((ipc_port_request_t) 0)
216:
217: /*
218: * Taking the ipc_port_multiple lock grants the privilege
219: * to lock multiple ports at once. No ports must locked
220: * when it is taken.
221: */
222:
223: decl_mutex_data(extern,ipc_port_multiple_lock_data)
224:
225: #define ipc_port_multiple_lock_init() \
226: mutex_init(&ipc_port_multiple_lock_data, ETAP_IPC_PORT_MULT)
227:
228: #define ipc_port_multiple_lock() \
229: mutex_lock(&ipc_port_multiple_lock_data)
230:
231: #define ipc_port_multiple_unlock() \
232: mutex_unlock(&ipc_port_multiple_lock_data)
233:
234: /*
235: * The port timestamp facility provides timestamps
236: * for port destruction. It is used to serialize
237: * mach_port_names with port death.
238: */
239:
240: decl_mutex_data(extern,ipc_port_timestamp_lock_data)
241: extern ipc_port_timestamp_t ipc_port_timestamp_data;
242:
243: #define ipc_port_timestamp_lock_init() \
244: mutex_init(&ipc_port_timestamp_lock_data, ETAP_IPC_PORT_TIME)
245:
246: #define ipc_port_timestamp_lock() \
247: mutex_lock(&ipc_port_timestamp_lock_data)
248:
249: #define ipc_port_timestamp_unlock() \
250: mutex_unlock(&ipc_port_timestamp_lock_data)
251:
252: /* Retrieve a port timestamp value */
253: extern ipc_port_timestamp_t ipc_port_timestamp(void);
254:
255: /*
256: * Compares two timestamps, and returns TRUE if one
257: * happened before two. Note that this formulation
258: * works when the timestamp wraps around at 2^32,
259: * as long as one and two aren't too far apart.
260: */
261:
262: #define IP_TIMESTAMP_ORDER(one, two) ((int) ((one) - (two)) < 0)
263:
264: #define ipc_port_translate_receive(space, name, portp) \
265: ipc_object_translate((space), (name), \
266: MACH_PORT_RIGHT_RECEIVE, \
267: (ipc_object_t *) (portp))
268:
269: #define ipc_port_translate_send(space, name, portp) \
270: ipc_object_translate((space), (name), \
271: MACH_PORT_RIGHT_SEND, \
272: (ipc_object_t *) (portp))
273:
274: /* Allocate a dead-name request slot */
275: extern kern_return_t
276: ipc_port_dnrequest(
277: ipc_port_t port,
278: mach_port_name_t name,
279: ipc_port_t soright,
280: ipc_port_request_index_t *indexp);
281:
282: /* Grow a port's table of dead-name requests */
283: extern kern_return_t ipc_port_dngrow(
284: ipc_port_t port,
285: int target_size);
286:
287: /* Cancel a dead-name request and return the send-once right */
288: extern ipc_port_t ipc_port_dncancel(
289: ipc_port_t port,
290: mach_port_name_t name,
291: ipc_port_request_index_t index);
292:
293: #define ipc_port_dnrename(port, index, oname, nname) \
294: MACRO_BEGIN \
295: ipc_port_request_t ipr, table; \
296: \
297: assert(ip_active(port)); \
298: \
299: table = port->ip_dnrequests; \
300: assert(table != IPR_NULL); \
301: \
302: ipr = &table[index]; \
303: assert(ipr->ipr_name == oname); \
304: \
305: ipr->ipr_name = nname; \
306: MACRO_END
307:
308: /* Make a port-deleted request */
309: extern void ipc_port_pdrequest(
310: ipc_port_t port,
311: ipc_port_t notify,
312: ipc_port_t *previousp);
313:
314: /* Make a no-senders request */
315: extern void ipc_port_nsrequest(
316: ipc_port_t port,
317: mach_port_mscount_t sync,
318: ipc_port_t notify,
319: ipc_port_t *previousp);
320:
321: #define ipc_port_set_mscount(port, mscount) \
322: MACRO_BEGIN \
323: assert(ip_active(port)); \
324: \
325: (port)->ip_mscount = (mscount); \
326: MACRO_END
327:
328: /* Prepare a receive right for transmission/destruction */
329: extern void ipc_port_clear_receiver(
330: ipc_port_t port);
331:
332: /* Initialize a newly-allocated port */
333: extern void ipc_port_init(
334: ipc_port_t port,
335: ipc_space_t space,
336: mach_port_name_t name);
337:
338: /* Allocate a port */
339: extern kern_return_t ipc_port_alloc(
340: ipc_space_t space,
341: mach_port_name_t *namep,
342: ipc_port_t *portp);
343:
344: /* Allocate a port, with a specific name */
345: extern kern_return_t ipc_port_alloc_name(
346: ipc_space_t space,
347: mach_port_name_t name,
348: ipc_port_t *portp);
349:
350: /* Generate dead name notifications */
351: extern void ipc_port_dnnotify(
352: ipc_port_t port,
353: ipc_port_request_t dnrequests);
354:
355: /* Destroy a port */
356: extern void ipc_port_destroy(
357: ipc_port_t port);
358:
359: /* Check if queueing "port" in a message for "dest" would create a circular
360: group of ports and messages */
361: extern boolean_t
362: ipc_port_check_circularity(
363: ipc_port_t port,
364: ipc_port_t dest);
365:
366: /* Make a send-once notify port from a receive right */
367: extern ipc_port_t ipc_port_lookup_notify(
368: ipc_space_t space,
369: mach_port_name_t name);
370:
371: /* Make a naked send right from a receive right */
372: extern ipc_port_t ipc_port_make_send(
373: ipc_port_t port);
374:
375: /* Make a naked send right from another naked send right */
376: extern ipc_port_t ipc_port_copy_send(
377: ipc_port_t port);
378:
379: /* Copyout a naked send right */
380: extern mach_port_name_t ipc_port_copyout_send(
381: ipc_port_t sright,
382: ipc_space_t space);
383:
384: /* Release a (valid) naked send right */
385: extern void ipc_port_release_send(
386: ipc_port_t port);
387:
388: /* Make a naked send-once right from a receive right */
389: extern ipc_port_t ipc_port_make_sonce(
390: ipc_port_t port);
391:
392: /* Release a naked send-once right */
393: extern void ipc_port_release_sonce(
394: ipc_port_t port);
395:
396: /* Release a naked (in limbo or in transit) receive right */
397: extern void ipc_port_release_receive(
398: ipc_port_t port);
399:
400: /* Allocate a port in a special space */
401: extern ipc_port_t ipc_port_alloc_special(
402: ipc_space_t space);
403:
404: /* Deallocate a port in a special space */
405: extern void ipc_port_dealloc_special(
406: ipc_port_t port,
407: ipc_space_t space);
408:
409: #if MACH_ASSERT
410: /* Track low-level port deallocation */
411: extern void ipc_port_track_dealloc(
412: ipc_port_t port);
413:
414: /* Initialize general port debugging state */
415: extern void ipc_port_debug_init(void);
416: #endif /* MACH_ASSERT */
417:
418: #define ipc_port_alloc_kernel() \
419: ipc_port_alloc_special(ipc_space_kernel)
420: #define ipc_port_dealloc_kernel(port) \
421: ipc_port_dealloc_special((port), ipc_space_kernel)
422:
423: #define ipc_port_alloc_reply() \
424: ipc_port_alloc_special(ipc_space_reply)
425: #define ipc_port_dealloc_reply(port) \
426: ipc_port_dealloc_special((port), ipc_space_reply)
427:
428: #define ipc_port_reference(port) \
429: ipc_object_reference(&(port)->ip_object)
430:
431: #define ipc_port_release(port) \
432: ipc_object_release(&(port)->ip_object)
433:
434: #endif /* _IPC_IPC_PORT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.