xref: /NextBSD/sys/sys/mach/ipc/ipc_port.h (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
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.12.2.4  92/05/28  18:14:17  jeffreyh
27  * 	Change value of IP_NORMA_FAKE_DNREQUEST to
28  * 	not get confused with MACH_IPC_COMPAT
29  *
30  * Revision 2.12.2.3  92/05/26  18:54:02  jeffreyh
31  * 	Add dead name proxy definitions
32  * 	[92/05/25            dlb]
33  *
34  * 	Added ip_norma_sync to allow thread synchronization on ports.
35  * 	[92/05/19            sjs]
36  *
37  * 	Added norma_ip_forward to indicate a proxy cannot be thrown away
38  * 	until the root node has been updated to point at the new node.
39  * 	[92/05/18            sjs]
40  *
41  * Revision 2.12.2.2.1.1  92/05/06  17:47:13  jeffreyh
42  * 	Add ip_norma_atrium_waiter for atrium message syncronization.
43  * 	[92/05/05            dlb]
44  *
45  * Revision 2.12.2.2  92/02/21  11:23:37  jsb
46  * 	Removed ip_norma_queued. Added ip_norma_spare[1234].
47  * 	[92/02/18  07:44:11  jsb]
48  *
49  * 	Added ip_norma_xmm_object_refs.
50  * 	[92/02/16  16:12:50  jsb]
51  *
52  * 	Added ip_norma_xmm_object.
53  * 	[92/02/09  14:42:47  jsb]
54  *
55  * Revision 2.12.2.1  92/01/03  16:35:50  jsb
56  * 	Renamed IP_NORMA_REQUEST macros to ip_nsproxy{,m,p}.
57  * 	They now look like Rich's ip_pdrequest macros.
58  * 	[91/12/30  07:53:29  jsb]
59  *
60  * 	Added IP_NORMA_NSREQUEST macros for no-senders notification support.
61  * 	[91/12/28  17:03:42  jsb]
62  *
63  * 	Added ip_norma_{queued,queue_next} for new norma_ipc_send
64  * 	implementation that maintains a list of ports with unsent
65  * 	remote messages. (The old implementation kept a single
66  * 	list of unsent messages for all ports.)
67  * 	[91/12/28  08:44:40  jsb]
68  *
69  * 	Added ip_norma_atrium.
70  * 	[91/12/26  20:03:40  jsb]
71  *
72  * 	Added ip_norma_sotransit. Removed ip_norma_{wanted,migrating}.
73  * 	Made ip_norma_dest_node unsigned.
74  * 	[91/12/25  16:44:29  jsb]
75  *
76  * 	NORMA_IPC: removed unused fields from struct ipc_port. Corrected log.
77  * 	[91/12/24  14:16:33  jsb]
78  *
79  * Revision 2.12  91/12/14  14:28:26  jsb
80  * 	NORMA_IPC: replaced dummy port struct fields with real names.
81  *
82  * Revision 2.11  91/11/14  16:56:20  rpd
83  * 	Added ipc_fields.h hack, with fields in struct ipc_port to match.
84  *	Added IP_NORMA_IS_PROXY macro.
85  * 	[91/11/00            jsb]
86  *
87  * Revision 2.10  91/10/09  16:10:01  af
88  * 	Added (unconditional) ipc_port_print declaration.
89  * 	[91/09/02            rpd]
90  *
91  * Revision 2.9  91/08/28  11:13:50  jsb
92  * 	Added ip_seqno and ipc_port_set_seqno.
93  * 	[91/08/09            rpd]
94  * 	Renamed clport (now ip_norma) fields in struct ipc_port.
95  * 	[91/08/14  19:31:55  jsb]
96  *
97  * Revision 2.8  91/08/03  18:18:37  jsb
98  * 	Fixed include. Added clport fields directly to struct ipc_port.
99  * 	[91/07/17  14:06:25  jsb]
100  *
101  * Revision 2.7  91/06/17  15:46:26  jsb
102  * 	Renamed NORMA conditionals.
103  * 	[91/06/17  10:44:06  jsb]
104  *
105  * Revision 2.6  91/05/14  16:35:34  mrt
106  * 	Correcting copyright
107  *
108  * Revision 2.5  91/02/05  17:23:10  mrt
109  * 	Changed to new Mach copyright
110  * 	[91/02/01  15:50:04  mrt]
111  *
112  * Revision 2.4  90/11/05  14:29:39  rpd
113  * 	Added ipc_port_reference, ipc_port_release.
114  * 	[90/10/29            rpd]
115  *
116  * Revision 2.3  90/09/28  16:55:18  jsb
117  * 	Added NORMA_IPC support.
118  * 	[90/09/28  14:03:58  jsb]
119  *
120  * Revision 2.2  90/06/02  14:51:13  rpd
121  * 	Created for new IPC.
122  * 	[90/03/26  21:01:25  rpd]
123  *
124  */
125 /* CMU_ENDHIST */
126 /*
127  * Mach Operating System
128  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
129  * All Rights Reserved.
130  *
131  * Permission to use, copy, modify and distribute this software and its
132  * documentation is hereby granted, provided that both the copyright
133  * notice and this permission notice appear in all copies of the
134  * software, derivative works or modified versions, and any portions
135  * thereof, and that both notices appear in supporting documentation.
136  *
137  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
138  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
139  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
140  *
141  * Carnegie Mellon requests users of this software to return to
142  *
143  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
144  *  School of Computer Science
145  *  Carnegie Mellon University
146  *  Pittsburgh PA 15213-3890
147  *
148  * any improvements or extensions that they make and grant Carnegie Mellon
149  * the rights to redistribute these changes.
150  */
151 /*
152  */
153 /*
154  *	File:	ipc/ipc_port.h
155  *	Author:	Rich Draves
156  *	Date:	1989
157  *
158  *	Definitions for ports.
159  */
160 
161 #ifndef	_IPC_IPC_PORT_H_
162 #define _IPC_IPC_PORT_H_
163 
164 #include <sys/lock.h>
165 #include <sys/mutex.h>
166 #include <sys/mach/mach_types.h>
167 #include <sys/mach/kern_return.h>
168 #include <sys/mach/port.h>
169 #include <sys/mach/thread_pool.h>
170 
171 
172 #include <sys/mach/ipc/ipc_object.h>
173 #include <sys/mach/ipc/ipc_mqueue.h>
174 #include <sys/mach/ipc/ipc_table.h>
175 #include <sys/mach/ipc/ipc_thread.h>
176 #include <sys/mach/ipc/ipc_types.h>
177 #include <sys/mach/ipc/ipc_entry.h>
178 
179 /*
180  * This structure defines the elements in common between
181  * ports and port sets.  The ipc_common_data MUST BE FIRST here,
182  * just as the ipc_object must be first within that.
183  *
184  * This structure must be used anywhere an ipc_object needs
185  * to be locked.
186  */
187 typedef struct rpc_common_data {
188 	struct ipc_common_data  rcd_comm;
189 	struct thread_pool      rcd_thread_pool;
190 	struct mtx rcd_io_lock_data;
191 } *rpc_common_t;
192 
193 
194 /*
195  *  A receive right (port) can be in four states:
196  *	1) dead (not active, ip_timestamp has death time)
197  *	2) in a space (ip_receiver_name != 0, ip_receiver points
198  *	to the space but doesn't hold a ref for it)
199  *	3) in transit (ip_receiver_name == 0, ip_destination points
200  *	to the destination port and holds a ref for it)
201  *	4) in limbo (ip_receiver_name == 0, ip_destination == IP_NULL)
202  *
203  *  If the port is active, and ip_receiver points to some space,
204  *  then ip_receiver_name != 0, and that space holds receive rights.
205  *  If the port is not active, then ip_timestamp contains a timestamp
206  *  taken when the port was destroyed.
207  */
208 
209 typedef unsigned int ipc_port_timestamp_t;
210 
211 typedef unsigned int ipc_port_flags_t;
212 
213 #define	IP_CONTEXT_FILE	0x1
214 
215 struct ipc_port {
216 
217 	/*
218 	 * Initial sub-structure in common with ipc_pset and rpc_port
219 	 * First element is an ipc_object
220 	 */
221 	struct rpc_common_data port_comm;
222 
223 	union {
224 		struct ipc_space *receiver;
225 		struct ipc_port *destination;
226 		ipc_port_timestamp_t timestamp;
227 	} data;
228 
229 	mach_port_mscount_t ip_mscount;
230 	mach_port_rights_t ip_srights;
231 	mach_port_rights_t ip_sorights;
232 
233 	struct ipc_port *ip_nsrequest;
234 	struct ipc_port *ip_pdrequest;
235 	struct ipc_port_request *ip_dnrequests;
236 
237 	struct ipc_pset *ip_pset;
238 	mach_port_seqno_t ip_seqno;		/* locked by message queue */
239 	mach_port_msgcount_t ip_msgcount;
240 	mach_port_msgcount_t ip_qlimit;
241 	struct ipc_mqueue ip_messages;
242 	struct ipc_thread_queue ip_blocked;
243 	ipc_port_flags_t ip_flags;
244 	TAILQ_ENTRY(ipc_port) ip_next;
245 	natural_t ip_sprequests: 1,
246 		ip_spimportant:1,
247 		ip_impdonation:1,
248 		ip_tempowner:1,
249 		ip_guarded:1,
250 		ip_strict_guard:1,
251 		ip_pad:26;
252 	mach_vm_address_t ip_context;
253 };
254 
255 
256 #define ip_object		port_comm.rcd_comm.icd_object
257 #define ip_references		ip_object.io_references
258 #define ip_bits			ip_object.io_bits
259 #define ip_kobject		port_comm.rcd_comm.icd_kobject
260 #define ip_subsystem		port_comm.rcd_comm.icd_subsystem
261 #define ip_receiver_name	port_comm.rcd_comm.icd_receiver_name
262 
263 #define ip_thread_pool		port_comm.rcd_thread_pool
264 
265 #define	ip_receiver		data.receiver
266 #define	ip_destination		data.destination
267 #define	ip_timestamp		data.timestamp
268 
269 #define	IP_NULL			((ipc_port_t) IO_NULL)
270 #define	IP_DEAD			((ipc_port_t) IO_DEAD)
271 
272 #define	IP_VALID(port)		IO_VALID(&(port)->ip_object)
273 
274 #define	ip_active(port)		io_active(&(port)->ip_object)
275 #define	ip_lock_init(port)	io_lock_init(&(port)->ip_object)
276 #define	ip_lock(port)		io_lock(&(port)->ip_object)
277 #define	ip_lock_try(port)	io_lock_try(&(port)->ip_object)
278 #define	ip_unlock(port)		io_unlock(&(port)->ip_object)
279 #define	ip_reference(port)	io_reference(&(port)->ip_object)
280 #define	ip_release(port)	io_release(&(port)->ip_object)
281 #define ip_lock_assert(port) io_lock_assert(&(port)->ip_object)
282 #define ip_unlock_assert(port) io_unlock_assert(&(port)->ip_object)
283 
284 #define	ip_kotype(port)		io_kotype(&(port)->ip_object)
285 
286 /*
287  *	No more senders information.
288  */
289 #define	IP_BIT_NMS		0x00008000	/* nms detection enabled? */
290 #define	IP_SET_NMS(port)	((port)->ip_bits |= IP_BIT_NMS)
291 #define IP_CLEAR_NMS(port)	((port)->ip_bits &= ~IP_BIT_NMS)
292 #define	IP_NMS(port)		((port)->ip_bits & IP_BIT_NMS)
293 
294 typedef ipc_table_index_t ipc_port_request_index_t;
295 
296 typedef struct ipc_port_request {
297 	union {
298 		struct ipc_port *port;
299 		ipc_port_request_index_t index;
300 	} notify;
301 
302 	union {
303 		mach_port_name_t name;
304 		struct ipc_table_size *size;
305 	} name;
306 } *ipc_port_request_t;
307 
308 #define	ipr_next		notify.index
309 #define	ipr_size		name.size
310 
311 #define	ipr_soright		notify.port
312 #define	ipr_name		name.name
313 
314 #define	IPR_NULL		((ipc_port_request_t) 0)
315 
316 /*
317  *	Taking the ipc_port_multiple lock grants the privilege
318  *	to lock multiple ports at once.  No ports must locked
319  *	when it is taken.
320  */
321 
322 extern struct mtx ipc_port_multiple_lock_data;
323 
324 #define	ipc_port_multiple_lock_init()					\
325 		mach_mutex_init(&ipc_port_multiple_lock_data, "ETAP_IPC_PORT_MULT")
326 
327 #define	ipc_port_multiple_lock()					\
328 		mtx_lock(&ipc_port_multiple_lock_data)
329 
330 #define	ipc_port_multiple_unlock()					\
331 		mtx_unlock(&ipc_port_multiple_lock_data)
332 
333 /*
334  *	The port timestamp facility provides timestamps
335  *	for port destruction.  It is used to serialize
336  *	mach_port_names with port death.
337  */
338 
339 decl_mutex_data(extern,ipc_port_timestamp_lock_data)
340 extern ipc_port_timestamp_t ipc_port_timestamp_data;
341 
342 #define	ipc_port_timestamp_lock_init()					\
343 		mach_mutex_init(&ipc_port_timestamp_lock_data, "ETAP_IPC_PORT_TIME")
344 
345 #define	ipc_port_timestamp_lock()					\
346 		mtx_lock(&ipc_port_timestamp_lock_data)
347 
348 #define	ipc_port_timestamp_unlock()					\
349 		mtx_unlock(&ipc_port_timestamp_lock_data)
350 
351 /* Retrieve a port timestamp value */
352 extern ipc_port_timestamp_t ipc_port_timestamp(void);
353 
354 /*
355  *	Compares two timestamps, and returns TRUE if one
356  *	happened before two.  Note that this formulation
357  *	works when the timestamp wraps around at 2^32,
358  *	as long as one and two aren't too far apart.
359  */
360 
361 #define	IP_TIMESTAMP_ORDER(one, two)	((int) ((one) - (two)) < 0)
362 
363 #define	ipc_port_translate_receive(space, name, portp)			\
364 		ipc_object_translate((space), (name),			\
365 				     MACH_PORT_RIGHT_RECEIVE,		\
366 				     (ipc_object_t *) (portp))
367 
368 #define	ipc_port_translate_send(space, name, portp)			\
369 		ipc_object_translate((space), (name),			\
370 				     MACH_PORT_RIGHT_SEND,		\
371 				     (ipc_object_t *) (portp))
372 
373 /* Allocate a dead-name request slot */
374 extern kern_return_t
375 ipc_port_dnrequest(
376 	ipc_port_t			port,
377 	mach_port_name_t			name,
378 	ipc_port_t			soright,
379 	ipc_port_request_index_t	*indexp);
380 
381 /* Grow a port's table of dead-name requests */
382 extern kern_return_t ipc_port_dngrow(
383 	ipc_port_t	port,
384 	int		target_size);
385 
386 /* Cancel a dead-name request and return the send-once right */
387 extern ipc_port_t ipc_port_dncancel(
388 	ipc_port_t			port,
389 	mach_port_name_t			name,
390 	ipc_port_request_index_t	index);
391 
392 #define	ipc_port_dnrename(port, index, oname, nname)			\
393 MACRO_BEGIN								\
394 	ipc_port_request_t ipr, table;					\
395 									\
396 	assert(ip_active(port));					\
397 									\
398 	table = port->ip_dnrequests;					\
399 	assert(table != IPR_NULL);					\
400 									\
401 	ipr = &table[index];						\
402 	assert(ipr->ipr_name == oname);					\
403 									\
404 	ipr->ipr_name = nname;						\
405 MACRO_END
406 
407 /* Make a port-deleted request */
408 extern void ipc_port_pdrequest(
409 	ipc_port_t	port,
410 	ipc_port_t	notify,
411 	ipc_port_t	*previousp);
412 
413 /* Make a no-senders request */
414 extern void ipc_port_nsrequest(
415 	ipc_port_t		port,
416 	mach_port_mscount_t	sync,
417 	ipc_port_t		notify,
418 	ipc_port_t		*previousp);
419 
420 /* Change a port's queue limit */
421 extern void ipc_port_set_qlimit(
422 	ipc_port_t		port,
423 	mach_port_msgcount_t	qlimit);
424 
425 #define	ipc_port_set_mscount(port, mscount)				\
426 MACRO_BEGIN								\
427 	assert(ip_active(port));					\
428 									\
429 	(port)->ip_mscount = (mscount);					\
430 MACRO_END
431 
432 /* Change a port's sequence number */
433 extern void ipc_port_set_seqno(
434 	ipc_port_t		port,
435 	mach_port_seqno_t 	seqno);
436 
437 /* Prepare a receive right for transmission/destruction */
438 extern void ipc_port_clear_receiver(
439 	ipc_port_t	port);
440 
441 /* Initialize a newly-allocated port */
442 extern void ipc_port_init(
443 	ipc_port_t	port,
444 	ipc_space_t	space,
445 	mach_port_name_t	name);
446 
447 /* Allocate a port */
448 extern kern_return_t ipc_port_alloc(
449 	ipc_space_t	space,
450 	mach_port_name_t	*namep,
451 	ipc_port_t	*portp);
452 
453 /* Allocate a port, with a specific name */
454 extern kern_return_t ipc_port_alloc_name(
455 	ipc_space_t	space,
456 	mach_port_name_t	name,
457 	ipc_port_t	*portp);
458 
459 /* Generate dead name notifications */
460 extern void ipc_port_dnnotify(
461 	ipc_port_t		port,
462 	ipc_port_request_t	dnrequests);
463 
464 /* Destroy a port */
465 extern void ipc_port_destroy(
466 	ipc_port_t	port);
467 
468 /* Check if queueing "port" in a message for "dest" would create a circular
469    group of ports and messages */
470 extern boolean_t
471 ipc_port_check_circularity(
472 	ipc_port_t	port,
473 	ipc_port_t	dest);
474 
475 /* Make a send-once notify port from a receive right */
476 extern ipc_port_t ipc_port_lookup_notify(
477 	ipc_space_t	space,
478 	mach_port_name_t 	name);
479 
480 /* Make a naked send right from a receive right */
481 extern ipc_port_t ipc_port_make_send(
482 	ipc_port_t	port);
483 
484 /* Make a naked send right from another naked send right */
485 extern ipc_port_t ipc_port_copy_send(
486 	ipc_port_t	port);
487 
488 /* Copyout a naked send right */
489 extern mach_port_name_t ipc_port_copyout_send(
490 	ipc_port_t	sright,
491 	ipc_space_t	space);
492 
493 /* Release a (valid) naked send right */
494 extern void ipc_port_release_send(
495 	ipc_port_t	port);
496 
497 /* Make a naked send-once right from a receive right */
498 extern ipc_port_t ipc_port_make_sonce(
499 	ipc_port_t	port);
500 
501 /* Release a naked send-once right */
502 extern void ipc_port_release_sonce(
503 	ipc_port_t	port);
504 
505 /* Release a naked (in limbo or in transit) receive right */
506 extern void ipc_port_release_receive(
507 	ipc_port_t	port);
508 
509 /* Allocate a port in a special space */
510 extern ipc_port_t ipc_port_alloc_special(
511 	ipc_space_t	space);
512 
513 /* Deallocate a port in a special space */
514 extern void ipc_port_dealloc_special(
515 	ipc_port_t	port,
516 	ipc_space_t	space);
517 
518 #if	MACH_ASSERT
519 /* Track low-level port deallocation */
520 extern void ipc_port_track_dealloc(
521 	ipc_port_t	port);
522 
523 /* Initialize general port debugging state */
524 extern void ipc_port_debug_init(void);
525 #endif	/* MACH_ASSERT */
526 
527 #define	ipc_port_alloc_kernel()		\
528 		ipc_port_alloc_special(ipc_space_kernel)
529 #define	ipc_port_dealloc_kernel(port)	\
530 		ipc_port_dealloc_special((port), ipc_space_kernel)
531 
532 #define	ipc_port_alloc_reply()		\
533 		ipc_port_alloc_special(ipc_space_reply)
534 #define	ipc_port_dealloc_reply(port)	\
535 		ipc_port_dealloc_special((port), ipc_space_reply)
536 
537 #define	ipc_port_reference(port)	\
538 		ipc_object_reference(&(port)->ip_object)
539 
540 #define	ipc_port_release(port)		\
541 		ipc_object_release(&(port)->ip_object)
542 
543 /*
544  *	IP_IS_REMOTE:  Determine whether a port's receiver
545  *	is local or remote.  By local, we mean that the
546  *	receiver is located on the same node as the caller;
547  *	by remote, we mean that the receiver is on a different
548  *	node.
549  *
550  *	The caller must hold a reference on the port.  This call
551  *	may be made with the port unlocked; however, no guarantees
552  *	are made that the port will remain local (or remote) after
553  *	the call completes.  The caller must have additional
554  *	knowledge to be certain that the port doesn't migrate.
555  *
556  *	IP_PORT_NODE:  return the destination node of a port.
557  *	This call is provided as a compatibility hack!  In this
558  *	case, XMM knows about node names.
559  *
560  *	Strictly speaking, this call should only be made on a
561  *	proxy port; however, we mandate that, for a principal,
562  *	the returned value should be the name of the local node.
563  *	XXX Probably shouldn't use node_self in the non-DIPC case. XXX
564  *
565  *	The caller must hold a reference on the port.  No guarantee
566  *	can be made by the distributed IPC subsystem that the port
567  *	will not migrate after this call completes.
568  *
569  */
570 
571 #define	IP_IS_REMOTE(port)		FALSE
572 #define	IP_PORT_NODE(port)		node_self()
573 #define IP_WAS_REMOTE(port)		FALSE
574 
575 #endif	/* _IPC_IPC_PORT_H_ */
576