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