|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: ipc/ipc_notify.c ! 28: * Author: Rich Draves ! 29: * Date: 1989 ! 30: * ! 31: * Notification-sending functions. ! 32: */ ! 33: ! 34: #include <mach_ipc_compat.h> ! 35: ! 36: #include <mach/port.h> ! 37: #include <mach/message.h> ! 38: #include <mach/notify.h> ! 39: #include <kern/assert.h> ! 40: #include <ipc/ipc_kmsg.h> ! 41: #include <ipc/ipc_mqueue.h> ! 42: #include <ipc/ipc_notify.h> ! 43: #include <ipc/ipc_port.h> ! 44: ! 45: #include <ipc/ipc_machdep.h> ! 46: ! 47: mach_port_deleted_notification_t ipc_notify_port_deleted_template; ! 48: mach_msg_accepted_notification_t ipc_notify_msg_accepted_template; ! 49: mach_port_destroyed_notification_t ipc_notify_port_destroyed_template; ! 50: mach_no_senders_notification_t ipc_notify_no_senders_template; ! 51: mach_send_once_notification_t ipc_notify_send_once_template; ! 52: mach_dead_name_notification_t ipc_notify_dead_name_template; ! 53: ! 54: #if MACH_IPC_COMPAT ! 55: /* ! 56: * When notification messages are received via the old ! 57: * msg_receive trap, the msg_type field should contain ! 58: * MSG_TYPE_EMERGENCY. We arrange for this by putting ! 59: * MSG_TYPE_EMERGENCY into msgh_seqno, which ! 60: * ipc_kmsg_copyout_compat copies to msg_type. ! 61: */ ! 62: ! 63: #define NOTIFY_MSGH_SEQNO MSG_TYPE_EMERGENCY ! 64: #else /* MACH_IPC_COMPAT */ ! 65: #define NOTIFY_MSGH_SEQNO 0 ! 66: #endif /* MACH_IPC_COMPAT */ ! 67: ! 68: /* ! 69: * Routine: ipc_notify_init_port_deleted ! 70: * Purpose: ! 71: * Initialize a template for port-deleted notifications. ! 72: */ ! 73: ! 74: void ! 75: ipc_notify_init_port_deleted(n) ! 76: mach_port_deleted_notification_t *n; ! 77: { ! 78: mach_msg_header_t *m = &n->not_header; ! 79: mach_msg_type_t *t = &n->not_type; ! 80: ! 81: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0); ! 82: m->msgh_size = sizeof *n; ! 83: m->msgh_seqno = NOTIFY_MSGH_SEQNO; ! 84: m->msgh_local_port = MACH_PORT_NULL; ! 85: m->msgh_remote_port = MACH_PORT_NULL; ! 86: m->msgh_id = MACH_NOTIFY_PORT_DELETED; ! 87: ! 88: t->msgt_name = MACH_MSG_TYPE_PORT_NAME; ! 89: t->msgt_size = PORT_T_SIZE_IN_BITS; ! 90: t->msgt_number = 1; ! 91: t->msgt_inline = TRUE; ! 92: t->msgt_longform = FALSE; ! 93: t->msgt_deallocate = FALSE; ! 94: t->msgt_unused = 0; ! 95: ! 96: n->not_port = MACH_PORT_NULL; ! 97: } ! 98: ! 99: /* ! 100: * Routine: ipc_notify_init_msg_accepted ! 101: * Purpose: ! 102: * Initialize a template for msg-accepted notifications. ! 103: */ ! 104: ! 105: void ! 106: ipc_notify_init_msg_accepted(n) ! 107: mach_msg_accepted_notification_t *n; ! 108: { ! 109: mach_msg_header_t *m = &n->not_header; ! 110: mach_msg_type_t *t = &n->not_type; ! 111: ! 112: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0); ! 113: m->msgh_size = sizeof *n; ! 114: m->msgh_seqno = NOTIFY_MSGH_SEQNO; ! 115: m->msgh_local_port = MACH_PORT_NULL; ! 116: m->msgh_remote_port = MACH_PORT_NULL; ! 117: m->msgh_id = MACH_NOTIFY_MSG_ACCEPTED; ! 118: ! 119: t->msgt_name = MACH_MSG_TYPE_PORT_NAME; ! 120: t->msgt_size = PORT_T_SIZE_IN_BITS; ! 121: t->msgt_number = 1; ! 122: t->msgt_inline = TRUE; ! 123: t->msgt_longform = FALSE; ! 124: t->msgt_deallocate = FALSE; ! 125: t->msgt_unused = 0; ! 126: ! 127: n->not_port = MACH_PORT_NULL; ! 128: } ! 129: ! 130: /* ! 131: * Routine: ipc_notify_init_port_destroyed ! 132: * Purpose: ! 133: * Initialize a template for port-destroyed notifications. ! 134: */ ! 135: ! 136: void ! 137: ipc_notify_init_port_destroyed( ! 138: mach_port_destroyed_notification_t *n) ! 139: { ! 140: mach_msg_header_t *m = &n->not_header; ! 141: mach_msg_type_t *t = &n->not_type; ! 142: ! 143: m->msgh_bits = MACH_MSGH_BITS_COMPLEX | ! 144: MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0); ! 145: m->msgh_size = sizeof *n; ! 146: m->msgh_seqno = NOTIFY_MSGH_SEQNO; ! 147: m->msgh_local_port = MACH_PORT_NULL; ! 148: m->msgh_remote_port = MACH_PORT_NULL; ! 149: m->msgh_id = MACH_NOTIFY_PORT_DESTROYED; ! 150: ! 151: t->msgt_name = MACH_MSG_TYPE_PORT_RECEIVE; ! 152: t->msgt_size = PORT_T_SIZE_IN_BITS; ! 153: t->msgt_number = 1; ! 154: t->msgt_inline = TRUE; ! 155: t->msgt_longform = FALSE; ! 156: t->msgt_deallocate = FALSE; ! 157: t->msgt_unused = 0; ! 158: ! 159: n->not_port = MACH_PORT_NULL; ! 160: } ! 161: ! 162: /* ! 163: * Routine: ipc_notify_init_no_senders ! 164: * Purpose: ! 165: * Initialize a template for no-senders notifications. ! 166: */ ! 167: ! 168: void ! 169: ipc_notify_init_no_senders( ! 170: mach_no_senders_notification_t *n) ! 171: { ! 172: mach_msg_header_t *m = &n->not_header; ! 173: mach_msg_type_t *t = &n->not_type; ! 174: ! 175: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0); ! 176: m->msgh_size = sizeof *n; ! 177: m->msgh_seqno = NOTIFY_MSGH_SEQNO; ! 178: m->msgh_local_port = MACH_PORT_NULL; ! 179: m->msgh_remote_port = MACH_PORT_NULL; ! 180: m->msgh_id = MACH_NOTIFY_NO_SENDERS; ! 181: ! 182: t->msgt_name = MACH_MSG_TYPE_INTEGER_32; ! 183: t->msgt_size = PORT_T_SIZE_IN_BITS; ! 184: t->msgt_number = 1; ! 185: t->msgt_inline = TRUE; ! 186: t->msgt_longform = FALSE; ! 187: t->msgt_deallocate = FALSE; ! 188: t->msgt_unused = 0; ! 189: ! 190: n->not_count = 0; ! 191: } ! 192: ! 193: /* ! 194: * Routine: ipc_notify_init_send_once ! 195: * Purpose: ! 196: * Initialize a template for send-once notifications. ! 197: */ ! 198: ! 199: void ! 200: ipc_notify_init_send_once( ! 201: mach_send_once_notification_t *n) ! 202: { ! 203: mach_msg_header_t *m = &n->not_header; ! 204: ! 205: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0); ! 206: m->msgh_size = sizeof *n; ! 207: m->msgh_seqno = NOTIFY_MSGH_SEQNO; ! 208: m->msgh_local_port = MACH_PORT_NULL; ! 209: m->msgh_remote_port = MACH_PORT_NULL; ! 210: m->msgh_id = MACH_NOTIFY_SEND_ONCE; ! 211: } ! 212: ! 213: /* ! 214: * Routine: ipc_notify_init_dead_name ! 215: * Purpose: ! 216: * Initialize a template for dead-name notifications. ! 217: */ ! 218: ! 219: void ! 220: ipc_notify_init_dead_name( ! 221: mach_dead_name_notification_t *n) ! 222: { ! 223: mach_msg_header_t *m = &n->not_header; ! 224: mach_msg_type_t *t = &n->not_type; ! 225: ! 226: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0); ! 227: m->msgh_size = sizeof *n; ! 228: m->msgh_seqno = NOTIFY_MSGH_SEQNO; ! 229: m->msgh_local_port = MACH_PORT_NULL; ! 230: m->msgh_remote_port = MACH_PORT_NULL; ! 231: m->msgh_id = MACH_NOTIFY_DEAD_NAME; ! 232: ! 233: t->msgt_name = MACH_MSG_TYPE_PORT_NAME; ! 234: t->msgt_size = PORT_T_SIZE_IN_BITS; ! 235: t->msgt_number = 1; ! 236: t->msgt_inline = TRUE; ! 237: t->msgt_longform = FALSE; ! 238: t->msgt_deallocate = FALSE; ! 239: t->msgt_unused = 0; ! 240: ! 241: n->not_port = MACH_PORT_NULL; ! 242: } ! 243: ! 244: /* ! 245: * Routine: ipc_notify_init ! 246: * Purpose: ! 247: * Initialize the notification subsystem. ! 248: */ ! 249: ! 250: void ! 251: ipc_notify_init(void) ! 252: { ! 253: ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template); ! 254: ipc_notify_init_msg_accepted(&ipc_notify_msg_accepted_template); ! 255: ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template); ! 256: ipc_notify_init_no_senders(&ipc_notify_no_senders_template); ! 257: ipc_notify_init_send_once(&ipc_notify_send_once_template); ! 258: ipc_notify_init_dead_name(&ipc_notify_dead_name_template); ! 259: } ! 260: ! 261: /* ! 262: * Routine: ipc_notify_port_deleted ! 263: * Purpose: ! 264: * Send a port-deleted notification. ! 265: * Conditions: ! 266: * Nothing locked. ! 267: * Consumes a ref/soright for port. ! 268: */ ! 269: ! 270: void ! 271: ipc_notify_port_deleted(port, name) ! 272: ipc_port_t port; ! 273: mach_port_t name; ! 274: { ! 275: ipc_kmsg_t kmsg; ! 276: mach_port_deleted_notification_t *n; ! 277: ! 278: kmsg = ikm_alloc(sizeof *n); ! 279: if (kmsg == IKM_NULL) { ! 280: printf("dropped port-deleted (0x%08x, 0x%x)\n", port, name); ! 281: ipc_port_release_sonce(port); ! 282: return; ! 283: } ! 284: ! 285: ikm_init(kmsg, sizeof *n); ! 286: n = (mach_port_deleted_notification_t *) &kmsg->ikm_header; ! 287: *n = ipc_notify_port_deleted_template; ! 288: ! 289: n->not_header.msgh_remote_port = (mach_port_t) port; ! 290: n->not_port = name; ! 291: ! 292: ipc_mqueue_send_always(kmsg); ! 293: } ! 294: ! 295: /* ! 296: * Routine: ipc_notify_msg_accepted ! 297: * Purpose: ! 298: * Send a msg-accepted notification. ! 299: * Conditions: ! 300: * Nothing locked. ! 301: * Consumes a ref/soright for port. ! 302: */ ! 303: ! 304: void ! 305: ipc_notify_msg_accepted(port, name) ! 306: ipc_port_t port; ! 307: mach_port_t name; ! 308: { ! 309: ipc_kmsg_t kmsg; ! 310: mach_msg_accepted_notification_t *n; ! 311: ! 312: kmsg = ikm_alloc(sizeof *n); ! 313: if (kmsg == IKM_NULL) { ! 314: printf("dropped msg-accepted (0x%08x, 0x%x)\n", port, name); ! 315: ipc_port_release_sonce(port); ! 316: return; ! 317: } ! 318: ! 319: ikm_init(kmsg, sizeof *n); ! 320: n = (mach_msg_accepted_notification_t *) &kmsg->ikm_header; ! 321: *n = ipc_notify_msg_accepted_template; ! 322: ! 323: n->not_header.msgh_remote_port = (mach_port_t) port; ! 324: n->not_port = name; ! 325: ! 326: ipc_mqueue_send_always(kmsg); ! 327: } ! 328: ! 329: /* ! 330: * Routine: ipc_notify_port_destroyed ! 331: * Purpose: ! 332: * Send a port-destroyed notification. ! 333: * Conditions: ! 334: * Nothing locked. ! 335: * Consumes a ref/soright for port. ! 336: * Consumes a ref for right, which should be a receive right ! 337: * prepped for placement into a message. (In-transit, ! 338: * or in-limbo if a circularity was detected.) ! 339: */ ! 340: ! 341: void ! 342: ipc_notify_port_destroyed(port, right) ! 343: ipc_port_t port; ! 344: ipc_port_t right; ! 345: { ! 346: ipc_kmsg_t kmsg; ! 347: mach_port_destroyed_notification_t *n; ! 348: ! 349: kmsg = ikm_alloc(sizeof *n); ! 350: if (kmsg == IKM_NULL) { ! 351: printf("dropped port-destroyed (0x%08x, 0x%08x)\n", ! 352: port, right); ! 353: ipc_port_release_sonce(port); ! 354: ipc_port_release_receive(right); ! 355: return; ! 356: } ! 357: ! 358: ikm_init(kmsg, sizeof *n); ! 359: n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header; ! 360: *n = ipc_notify_port_destroyed_template; ! 361: ! 362: n->not_header.msgh_remote_port = (mach_port_t) port; ! 363: n->not_port = (mach_port_t) right; ! 364: ! 365: ipc_mqueue_send_always(kmsg); ! 366: } ! 367: ! 368: /* ! 369: * Routine: ipc_notify_no_senders ! 370: * Purpose: ! 371: * Send a no-senders notification. ! 372: * Conditions: ! 373: * Nothing locked. ! 374: * Consumes a ref/soright for port. ! 375: */ ! 376: ! 377: void ! 378: ipc_notify_no_senders(port, mscount) ! 379: ipc_port_t port; ! 380: mach_port_mscount_t mscount; ! 381: { ! 382: ipc_kmsg_t kmsg; ! 383: mach_no_senders_notification_t *n; ! 384: ! 385: #if NORMA_IPC ! 386: if (ip_nsproxyp(port)) { ! 387: assert(mscount == 0); ! 388: norma_ipc_notify_no_senders(ip_nsproxy(port)); ! 389: return; ! 390: } ! 391: #endif /* NORMA_IPC */ ! 392: kmsg = ikm_alloc(sizeof *n); ! 393: if (kmsg == IKM_NULL) { ! 394: printf("dropped no-senders (0x%08x, %u)\n", port, mscount); ! 395: ipc_port_release_sonce(port); ! 396: return; ! 397: } ! 398: ! 399: ikm_init(kmsg, sizeof *n); ! 400: n = (mach_no_senders_notification_t *) &kmsg->ikm_header; ! 401: *n = ipc_notify_no_senders_template; ! 402: ! 403: n->not_header.msgh_remote_port = (mach_port_t) port; ! 404: n->not_count = mscount; ! 405: ! 406: ipc_mqueue_send_always(kmsg); ! 407: } ! 408: ! 409: /* ! 410: * Routine: ipc_notify_send_once ! 411: * Purpose: ! 412: * Send a send-once notification. ! 413: * Conditions: ! 414: * Nothing locked. ! 415: * Consumes a ref/soright for port. ! 416: */ ! 417: ! 418: void ! 419: ipc_notify_send_once(port) ! 420: ipc_port_t port; ! 421: { ! 422: ipc_kmsg_t kmsg; ! 423: mach_send_once_notification_t *n; ! 424: ! 425: kmsg = ikm_alloc(sizeof *n); ! 426: if (kmsg == IKM_NULL) { ! 427: printf("dropped send-once (0x%08x)\n", port); ! 428: ipc_port_release_sonce(port); ! 429: return; ! 430: } ! 431: ! 432: ikm_init(kmsg, sizeof *n); ! 433: n = (mach_send_once_notification_t *) &kmsg->ikm_header; ! 434: *n = ipc_notify_send_once_template; ! 435: ! 436: n->not_header.msgh_remote_port = (mach_port_t) port; ! 437: ! 438: ipc_mqueue_send_always(kmsg); ! 439: } ! 440: ! 441: /* ! 442: * Routine: ipc_notify_dead_name ! 443: * Purpose: ! 444: * Send a dead-name notification. ! 445: * Conditions: ! 446: * Nothing locked. ! 447: * Consumes a ref/soright for port. ! 448: */ ! 449: ! 450: void ! 451: ipc_notify_dead_name(port, name) ! 452: ipc_port_t port; ! 453: mach_port_t name; ! 454: { ! 455: ipc_kmsg_t kmsg; ! 456: mach_dead_name_notification_t *n; ! 457: ! 458: kmsg = ikm_alloc(sizeof *n); ! 459: if (kmsg == IKM_NULL) { ! 460: printf("dropped dead-name (0x%08x, 0x%x)\n", port, name); ! 461: ipc_port_release_sonce(port); ! 462: return; ! 463: } ! 464: ! 465: ikm_init(kmsg, sizeof *n); ! 466: n = (mach_dead_name_notification_t *) &kmsg->ikm_header; ! 467: *n = ipc_notify_dead_name_template; ! 468: ! 469: n->not_header.msgh_remote_port = (mach_port_t) port; ! 470: n->not_port = name; ! 471: ! 472: ipc_mqueue_send_always(kmsg); ! 473: } ! 474: ! 475: #if MACH_IPC_COMPAT ! 476: ! 477: /* ! 478: * Routine: ipc_notify_port_deleted_compat ! 479: * Purpose: ! 480: * Send a port-deleted notification. ! 481: * Sends it to a send right instead of a send-once right. ! 482: * Conditions: ! 483: * Nothing locked. ! 484: * Consumes a ref/sright for port. ! 485: */ ! 486: ! 487: void ! 488: ipc_notify_port_deleted_compat(port, name) ! 489: ipc_port_t port; ! 490: mach_port_t name; ! 491: { ! 492: ipc_kmsg_t kmsg; ! 493: mach_port_deleted_notification_t *n; ! 494: ! 495: kmsg = ikm_alloc(sizeof *n); ! 496: if (kmsg == IKM_NULL) { ! 497: printf("dropped port-deleted-compat (0x%08x, 0x%x)\n", ! 498: port, name); ! 499: ipc_port_release_send(port); ! 500: return; ! 501: } ! 502: ! 503: ikm_init(kmsg, sizeof *n); ! 504: n = (mach_port_deleted_notification_t *) &kmsg->ikm_header; ! 505: *n = ipc_notify_port_deleted_template; ! 506: ! 507: n->not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); ! 508: n->not_header.msgh_remote_port = (mach_port_t) port; ! 509: n->not_port = name; ! 510: ! 511: ipc_mqueue_send_always(kmsg); ! 512: } ! 513: ! 514: /* ! 515: * Routine: ipc_notify_msg_accepted_compat ! 516: * Purpose: ! 517: * Send a msg-accepted notification. ! 518: * Sends it to a send right instead of a send-once right. ! 519: * Conditions: ! 520: * Nothing locked. ! 521: * Consumes a ref/sright for port. ! 522: */ ! 523: ! 524: void ! 525: ipc_notify_msg_accepted_compat(port, name) ! 526: ipc_port_t port; ! 527: mach_port_t name; ! 528: { ! 529: ipc_kmsg_t kmsg; ! 530: mach_msg_accepted_notification_t *n; ! 531: ! 532: kmsg = ikm_alloc(sizeof *n); ! 533: if (kmsg == IKM_NULL) { ! 534: printf("dropped msg-accepted-compat (0x%08x, 0x%x)\n", ! 535: port, name); ! 536: ipc_port_release_send(port); ! 537: return; ! 538: } ! 539: ! 540: ikm_init(kmsg, sizeof *n); ! 541: n = (mach_msg_accepted_notification_t *) &kmsg->ikm_header; ! 542: *n = ipc_notify_msg_accepted_template; ! 543: ! 544: n->not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); ! 545: n->not_header.msgh_remote_port = (mach_port_t) port; ! 546: n->not_port = name; ! 547: ! 548: ipc_mqueue_send_always(kmsg); ! 549: } ! 550: ! 551: /* ! 552: * Routine: ipc_notify_port_destroyed_compat ! 553: * Purpose: ! 554: * Send a port-destroyed notification. ! 555: * Sends it to a send right instead of a send-once right. ! 556: * Conditions: ! 557: * Nothing locked. ! 558: * Consumes a ref/sright for port. ! 559: * Consumes a ref for right, which should be a receive right ! 560: * prepped for placement into a message. (In-transit, ! 561: * or in-limbo if a circularity was detected.) ! 562: */ ! 563: ! 564: void ! 565: ipc_notify_port_destroyed_compat(port, right) ! 566: ipc_port_t port; ! 567: ipc_port_t right; ! 568: { ! 569: ipc_kmsg_t kmsg; ! 570: mach_port_destroyed_notification_t *n; ! 571: ! 572: kmsg = ikm_alloc(sizeof *n); ! 573: if (kmsg == IKM_NULL) { ! 574: printf("dropped port-destroyed-compat (0x%08x, 0x%08x)\n", ! 575: port, right); ! 576: ipc_port_release_send(port); ! 577: ipc_port_release_receive(right); ! 578: return; ! 579: } ! 580: ! 581: ikm_init(kmsg, sizeof *n); ! 582: n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header; ! 583: *n = ipc_notify_port_destroyed_template; ! 584: ! 585: n->not_header.msgh_bits = MACH_MSGH_BITS_COMPLEX | ! 586: MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); ! 587: n->not_header.msgh_remote_port = (mach_port_t) port; ! 588: n->not_port = (mach_port_t) right; ! 589: ! 590: ipc_mqueue_send_always(kmsg); ! 591: } ! 592: ! 593: #endif /* MACH_IPC_COMPAT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.