|
|
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: * HISTORY
27: *
28: * Revision 1.1.1.1 1998/09/22 21:05:29 wsanchez
29: * Import of Mac OS X kernel (~semeria)
30: *
31: * Revision 1.1.1.1 1998/03/07 02:26:16 wsanchez
32: * Import of OSF Mach kernel (~mburg)
33: *
34: * Revision 1.2.24.4 1995/02/23 17:31:21 alanl
35: * Promoted MACH_RT to a full-fledged build option. (w/mmp)
36: * [95/02/21 alanl]
37: *
38: * DIPC: Merge from nmk17b2 to nmk18b8.
39: * Removed rt boolean argument from ipc_kmsg_* functions in favor of
40: * a new bit in the msg: MACH_MSGH_BITS_RTALLOC. Determine rt
41: * status of dest port and call either ikm_alloc or ikm_rtalloc, then
42: * mark the new kmsg with the RTALLOC bit if appropriate.
43: * [95/01/05 mmp]
44: *
45: * Revision 1.2.28.3 1994/10/11 18:24:57 rwd
46: * Comment out the tr for each entry into ipc_notify_send_once. This
47: * can dominate the tr log quite easily.
48: * [94/10/07 rwd]
49: *
50: * Revision 1.2.28.2 1994/09/30 21:26:15 alanl
51: * Convert code in ipc_notify_send_once to detect dead
52: * send-once rights from NORMA_IPC to DIPC.
53: * [94/09/30 alanl]
54: *
55: * Revision 1.2.28.1 1994/09/01 12:51:19 alanl
56: * DIPC: Eliminate dead NORMA_IPC code.
57: * [94/09/01 alanl]
58: *
59: * Revision 1.2.24.3 1994/09/23 02:09:05 ezf
60: * change marker to not FREE
61: * [1994/09/22 21:29:36 ezf]
62: *
63: * Revision 1.2.24.2 1994/08/18 23:11:09 widyono
64: * Notify routines, integrate RT: ipc_notify_init_port_deleted(),
65: * ipc_notify_init_port_destroyed(), ipc_notify_init_no_senders(),
66: * ipc_notify_init_send_once(), ipc_notify_init_dead_name()
67: * [1994/07/28 22:24:14 widyono]
68: *
69: * Revision 1.2.24.1 1994/06/13 19:57:31 dlb
70: * Merge MK6 and NMK17
71: * [1994/06/13 16:22:14 dlb]
72: *
73: * Revision 1.2.22.1 1994/02/10 16:25:18 bernadat
74: * Removed call to norma_ipc_notify_no_sender in ipc_notify_no_senders,
75: * since it must be done with ip_lock held in the same critical section
76: * as the "port->ip_srights--" operation.
77: * [93/11/08 paire]
78: * [94/02/10 bernadat]
79: *
80: * Revision 1.2.8.7 1993/09/09 16:06:59 jeffc
81: * CR9745 - delete message accepted notifications
82: * [1993/09/03 22:14:56 jeffc]
83: *
84: * Revision 1.2.8.6 1993/08/05 19:07:33 jeffc
85: * CR9508 -- delete dead Mach3 code. Remove MACH_IPC_TYPED
86: * [1993/08/04 16:51:31 jeffc]
87: *
88: * CR9508 - Delete dead code. Remove MACH_IPC_COMPAT
89: * [1993/08/03 17:07:31 jeffc]
90: *
91: * Revision 1.2.8.5 1993/08/02 17:24:55 rod
92: * ANSI prototypes: include kern/misc_protos.h. CR #9523.
93: * [1993/07/31 15:03:12 rod]
94: *
95: * Revision 1.2.8.4 1993/07/22 16:16:38 rod
96: * Add ANSI prototypes. CR #9523.
97: * [1993/07/22 13:30:46 rod]
98: *
99: * Revision 1.2.8.3 1993/07/19 18:46:51 travos
100: * Changes to the trailer logic, both for correctness (CR8991)
101: * and performances (CR9487): trailers have a default size set
102: * to the minimum.
103: * [1993/07/13 19:13:23 travos]
104: *
105: * Revision 1.2.8.2 1993/06/09 02:32:23 gm
106: * In ipc_notify_init_port_destroyed() initialize disposition in template
107: * to MACH_MSG_TYPE_PORT_RECEIVE. CR#8969.
108: * [1993/04/28 11:17:32 rod]
109: *
110: * Fix untyped notifications. CR#8969.
111: * [1993/04/27 11:28:21 rod]
112: *
113: * Revision 1.2 1993/04/19 16:21:19 devrcs
114: * Set ikm_version in compatability interfaces.
115: * [1993/04/07 21:03:34 rod]
116: *
117: * Added trailer support to untyped ipc. [[email protected]]
118: * [1993/04/06 19:39:03 travos]
119: *
120: * Untyped ipc merge:
121: * Remove the NDR format label from messages with no untyped data
122: * [1993/03/12 22:49:45 travos]
123: * added support for untyped notifications
124: * [1993/02/25 22:03:08 fdr]
125: *
126: * Revision 1.1 1992/09/30 02:07:42 robert
127: * Initial revision
128: *
129: * $EndLog$
130: */
131: /* CMU_HIST */
132: /*
133: * Revision 2.5.2.2 92/03/28 10:09:23 jeffreyh
134: * NORMA_IPC: Don't send send_once notification if port is dead.
135: * [92/03/25 dlb]
136: *
137: * Revision 2.5.2.1 92/01/03 16:35:29 jsb
138: * Did I say ndproxy? I meant to say nsproxy.
139: * [91/12/31 21:40:41 jsb]
140: *
141: * Changes for IP_NORMA_REQUEST macros being renamed to ip_ndproxy{,m,p}.
142: * [91/12/30 07:57:26 jsb]
143: *
144: * Use IP_IS_NORMA_NSREQUEST macro.
145: * [91/12/28 17:05:21 jsb]
146: *
147: * Added norma_ipc_notify_no_senders hook in ipc_notify_no_senders.
148: * [91/12/24 14:37:56 jsb]
149: *
150: * Revision 2.5 91/08/28 11:13:41 jsb
151: * Changed msgh_kind to msgh_seqno.
152: * [91/08/09 rpd]
153: *
154: * Revision 2.4 91/05/14 16:34:24 mrt
155: * Correcting copyright
156: *
157: * Revision 2.3 91/02/05 17:22:33 mrt
158: * Changed to new Mach copyright
159: * [91/02/01 15:46:58 mrt]
160: *
161: * Revision 2.2 90/06/02 14:50:50 rpd
162: * Created for new IPC.
163: * [90/03/26 20:57:58 rpd]
164: *
165: */
166: /* CMU_ENDHIST */
167: /*
168: * Mach Operating System
169: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
170: * All Rights Reserved.
171: *
172: * Permission to use, copy, modify and distribute this software and its
173: * documentation is hereby granted, provided that both the copyright
174: * notice and this permission notice appear in all copies of the
175: * software, derivative works or modified versions, and any portions
176: * thereof, and that both notices appear in supporting documentation.
177: *
178: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
179: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
180: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
181: *
182: * Carnegie Mellon requests users of this software to return to
183: *
184: * Software Distribution Coordinator or [email protected]
185: * School of Computer Science
186: * Carnegie Mellon University
187: * Pittsburgh PA 15213-3890
188: *
189: * any improvements or extensions that they make and grant Carnegie Mellon
190: * the rights to redistribute these changes.
191: */
192: /*
193: */
194: /*
195: * File: ipc/ipc_notify.c
196: * Author: Rich Draves
197: * Date: 1989
198: *
199: * Notification-sending functions.
200: */
201:
202: #include <dipc.h>
203: #include <mach_rt.h>
204:
205: #include <mach/port.h>
206: #include <mach/message.h>
207: #include <mach/notify.h>
208: #include <kern/assert.h>
209: #include <kern/misc_protos.h>
210: #include <ipc/ipc_kmsg.h>
211: #include <ipc/ipc_mqueue.h>
212: #include <ipc/ipc_notify.h>
213: #include <ipc/ipc_port.h>
214: #if DIPC
215: #include <ddb/tr.h>
216: #endif /* DIPC */
217:
218: /*
219: * Forward declarations
220: */
221: void ipc_notify_init_port_deleted(
222: mach_port_deleted_notification_t *n);
223:
224: void ipc_notify_init_port_destroyed(
225: mach_port_destroyed_notification_t *n);
226:
227: void ipc_notify_init_no_senders(
228: mach_no_senders_notification_t *n);
229:
230: void ipc_notify_init_send_once(
231: mach_send_once_notification_t *n);
232:
233: void ipc_notify_init_dead_name(
234: mach_dead_name_notification_t *n);
235:
236: mach_port_deleted_notification_t ipc_notify_port_deleted_template;
237: mach_port_destroyed_notification_t ipc_notify_port_destroyed_template;
238: mach_no_senders_notification_t ipc_notify_no_senders_template;
239: mach_send_once_notification_t ipc_notify_send_once_template;
240: mach_dead_name_notification_t ipc_notify_dead_name_template;
241:
242: /*
243: * Routine: ipc_notify_init_port_deleted
244: * Purpose:
245: * Initialize a template for port-deleted notifications.
246: */
247:
248: void
249: ipc_notify_init_port_deleted(
250: mach_port_deleted_notification_t *n)
251: {
252: mach_msg_header_t *m = &n->not_header;
253:
254: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
255: m->msgh_local_port = MACH_PORT_NULL;
256: m->msgh_remote_port = MACH_PORT_NULL;
257: m->msgh_id = MACH_NOTIFY_PORT_DELETED;
258: m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
259:
260: n->not_port = MACH_PORT_NULL;
261: n->NDR = NDR_record;
262: n->trailer.msgh_seqno = 0;
263: n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
264: n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
265: n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
266: }
267:
268: /*
269: * Routine: ipc_notify_init_port_destroyed
270: * Purpose:
271: * Initialize a template for port-destroyed notifications.
272: */
273:
274: void
275: ipc_notify_init_port_destroyed(
276: mach_port_destroyed_notification_t *n)
277: {
278: mach_msg_header_t *m = &n->not_header;
279:
280: m->msgh_bits = MACH_MSGH_BITS_COMPLEX |
281: MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
282: m->msgh_local_port = MACH_PORT_NULL;
283: m->msgh_remote_port = MACH_PORT_NULL;
284: m->msgh_id = MACH_NOTIFY_PORT_DESTROYED;
285: m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
286:
287: n->not_body.msgh_descriptor_count = 1;
288: n->not_port.disposition = MACH_MSG_TYPE_PORT_RECEIVE;
289: n->not_port.name = MACH_PORT_NULL;
290: n->not_port.type = MACH_MSG_PORT_DESCRIPTOR;
291: n->trailer.msgh_seqno = 0;
292: n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
293: n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
294: n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
295: }
296:
297: /*
298: * Routine: ipc_notify_init_no_senders
299: * Purpose:
300: * Initialize a template for no-senders notifications.
301: */
302:
303: void
304: ipc_notify_init_no_senders(
305: mach_no_senders_notification_t *n)
306: {
307: mach_msg_header_t *m = &n->not_header;
308:
309: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
310: m->msgh_local_port = MACH_PORT_NULL;
311: m->msgh_remote_port = MACH_PORT_NULL;
312: m->msgh_id = MACH_NOTIFY_NO_SENDERS;
313: m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
314:
315: n->NDR = NDR_record;
316: n->trailer.msgh_seqno = 0;
317: n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
318: n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
319: n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
320: n->not_count = 0;
321: }
322:
323: /*
324: * Routine: ipc_notify_init_send_once
325: * Purpose:
326: * Initialize a template for send-once notifications.
327: */
328:
329: void
330: ipc_notify_init_send_once(
331: mach_send_once_notification_t *n)
332: {
333: mach_msg_header_t *m = &n->not_header;
334:
335: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
336: m->msgh_local_port = MACH_PORT_NULL;
337: m->msgh_remote_port = MACH_PORT_NULL;
338: m->msgh_id = MACH_NOTIFY_SEND_ONCE;
339: m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
340: n->trailer.msgh_seqno = 0;
341: n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
342: n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
343: n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
344: }
345:
346: /*
347: * Routine: ipc_notify_init_dead_name
348: * Purpose:
349: * Initialize a template for dead-name notifications.
350: */
351:
352: void
353: ipc_notify_init_dead_name(
354: mach_dead_name_notification_t *n)
355: {
356: mach_msg_header_t *m = &n->not_header;
357:
358: m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
359: m->msgh_local_port = MACH_PORT_NULL;
360: m->msgh_remote_port = MACH_PORT_NULL;
361: m->msgh_id = MACH_NOTIFY_DEAD_NAME;
362: m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
363:
364: n->not_port = MACH_PORT_NULL;
365: n->NDR = NDR_record;
366: n->trailer.msgh_seqno = 0;
367: n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
368: n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
369: n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
370: }
371:
372: /*
373: * Routine: ipc_notify_init
374: * Purpose:
375: * Initialize the notification subsystem.
376: */
377:
378: void
379: ipc_notify_init(void)
380: {
381: ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template);
382: ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template);
383: ipc_notify_init_no_senders(&ipc_notify_no_senders_template);
384: ipc_notify_init_send_once(&ipc_notify_send_once_template);
385: ipc_notify_init_dead_name(&ipc_notify_dead_name_template);
386: }
387:
388: /*
389: * Routine: ipc_notify_port_deleted
390: * Purpose:
391: * Send a port-deleted notification.
392: * Conditions:
393: * Nothing locked.
394: * Consumes a ref/soright for port.
395: */
396:
397: void
398: ipc_notify_port_deleted(
399: ipc_port_t port,
400: mach_port_name_t name)
401: {
402: ipc_kmsg_t kmsg;
403: mach_port_deleted_notification_t *n;
404:
405: #if MACH_RT
406: if (IP_RT(port))
407: kmsg = ikm_rtalloc(sizeof *n);
408: else
409: #endif /* MACH_RT */
410: kmsg = ikm_alloc(sizeof *n);
411: if (kmsg == IKM_NULL) {
412: printf("dropped port-deleted (0x%08x, 0x%x)\n", port, name);
413: ipc_port_release_sonce(port);
414: return;
415: }
416:
417: ikm_init(kmsg, sizeof *n);
418: n = (mach_port_deleted_notification_t *) &kmsg->ikm_header;
419: *n = ipc_notify_port_deleted_template;
420: #if MACH_RT
421: if (IP_RT(port))
422: KMSG_MARK_RT(kmsg);
423: #endif /* MACH_RT */
424:
425: n->not_header.msgh_remote_port = port;
426: n->not_port = name;
427:
428: ipc_kmsg_send_always(kmsg);
429: }
430:
431: /*
432: * Routine: ipc_notify_port_destroyed
433: * Purpose:
434: * Send a port-destroyed notification.
435: * Conditions:
436: * Nothing locked.
437: * Consumes a ref/soright for port.
438: * Consumes a ref for right, which should be a receive right
439: * prepped for placement into a message. (In-transit,
440: * or in-limbo if a circularity was detected.)
441: */
442:
443: void
444: ipc_notify_port_destroyed(
445: ipc_port_t port,
446: ipc_port_t right)
447: {
448: ipc_kmsg_t kmsg;
449: mach_port_destroyed_notification_t *n;
450:
451: #if MACH_RT
452: if (IP_RT(port))
453: kmsg = ikm_rtalloc(sizeof *n);
454: else
455: #endif /* MACH_RT */
456: kmsg = ikm_alloc(sizeof *n);
457: if (kmsg == IKM_NULL) {
458: printf("dropped port-destroyed (0x%08x, 0x%08x)\n",
459: port, right);
460: ipc_port_release_sonce(port);
461: ipc_port_release_receive(right);
462: return;
463: }
464:
465: ikm_init(kmsg, sizeof *n);
466: n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header;
467: *n = ipc_notify_port_destroyed_template;
468: #if MACH_RT
469: if (IP_RT(port))
470: KMSG_MARK_RT(kmsg);
471: #endif /* MACH_RT */
472:
473: n->not_header.msgh_remote_port = port;
474: n->not_port.name = right;
475:
476: ipc_kmsg_send_always(kmsg);
477: }
478:
479: /*
480: * Routine: ipc_notify_no_senders
481: * Purpose:
482: * Send a no-senders notification.
483: * Conditions:
484: * Nothing locked.
485: * Consumes a ref/soright for port.
486: */
487:
488: void
489: ipc_notify_no_senders(
490: ipc_port_t port,
491: mach_port_mscount_t mscount)
492: {
493: ipc_kmsg_t kmsg;
494: mach_no_senders_notification_t *n;
495:
496: #if MACH_RT
497: if (IP_RT(port))
498: kmsg = ikm_rtalloc(sizeof *n);
499: else
500: #endif /* MACH_RT */
501: kmsg = ikm_alloc(sizeof *n);
502: if (kmsg == IKM_NULL) {
503: printf("dropped no-senders (0x%08x, %u)\n", port, mscount);
504: ipc_port_release_sonce(port);
505: return;
506: }
507:
508: ikm_init(kmsg, sizeof *n);
509: n = (mach_no_senders_notification_t *) &kmsg->ikm_header;
510: *n = ipc_notify_no_senders_template;
511: #if MACH_RT
512: if (IP_RT(port))
513: KMSG_MARK_RT(kmsg);
514: #endif /* MACH_RT */
515:
516: n->not_header.msgh_remote_port = port;
517: n->not_count = mscount;
518:
519: ipc_kmsg_send_always(kmsg);
520: }
521:
522: /*
523: * Routine: ipc_notify_send_once
524: * Purpose:
525: * Send a send-once notification.
526: * Conditions:
527: * Nothing locked.
528: * Consumes a ref/soright for port.
529: */
530:
531: void
532: ipc_notify_send_once(
533: ipc_port_t port)
534: {
535: ipc_kmsg_t kmsg;
536: mach_send_once_notification_t *n;
537: #if DIPC
538: boolean_t active;
539: TR_DECL("ipc_notify_send_once");
540: #endif /* DIPC */
541:
542: #if DIPC
543: /* tr2("enter: port 0x%x", port);*/
544: /*
545: * If the port is not active, sending this
546: * notification causes an infinite loop.
547: * DIPC gets here because the send
548: * once right could be on another node.
549: */
550: ip_lock(port);
551: active = ip_active(port);
552: ip_unlock(port);
553:
554: if (!active) {
555: tr2("...port 0x%x is dead", port);
556: ipc_port_release_sonce(port);
557: return;
558: }
559: #endif /* DIPC */
560:
561: #if MACH_RT
562: if (IP_RT(port))
563: kmsg = ikm_rtalloc(sizeof *n);
564: else
565: #endif /* MACH_RT */
566: kmsg = ikm_alloc(sizeof *n);
567: if (kmsg == IKM_NULL) {
568: printf("dropped send-once (0x%08x)\n", port);
569: ipc_port_release_sonce(port);
570: return;
571: }
572:
573: ikm_init(kmsg, sizeof *n);
574: n = (mach_send_once_notification_t *) &kmsg->ikm_header;
575: *n = ipc_notify_send_once_template;
576: #if MACH_RT
577: if (IP_RT(port))
578: KMSG_MARK_RT(kmsg);
579: #endif /* MACH_RT */
580:
581: n->not_header.msgh_remote_port = port;
582:
583: ipc_kmsg_send_always(kmsg);
584: }
585:
586: /*
587: * Routine: ipc_notify_dead_name
588: * Purpose:
589: * Send a dead-name notification.
590: * Conditions:
591: * Nothing locked.
592: * Consumes a ref/soright for port.
593: */
594:
595: void
596: ipc_notify_dead_name(
597: ipc_port_t port,
598: mach_port_name_t name)
599: {
600: ipc_kmsg_t kmsg;
601: mach_dead_name_notification_t *n;
602:
603: #if MACH_RT
604: if (IP_RT(port))
605: kmsg = ikm_rtalloc(sizeof *n);
606: else
607: #endif /* MACH_RT */
608: kmsg = ikm_alloc(sizeof *n);
609: if (kmsg == IKM_NULL) {
610: printf("dropped dead-name (0x%08x, 0x%x)\n", port, name);
611: ipc_port_release_sonce(port);
612: return;
613: }
614:
615: ikm_init(kmsg, sizeof *n);
616: n = (mach_dead_name_notification_t *) &kmsg->ikm_header;
617: *n = ipc_notify_dead_name_template;
618: #if MACH_RT
619: if (IP_RT(port))
620: KMSG_MARK_RT(kmsg);
621: #endif /* MACH_RT */
622:
623: n->not_header.msgh_remote_port = port;
624: n->not_port = name;
625:
626: ipc_kmsg_send_always(kmsg);
627: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.