|
|
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.