FreeBSD/Linux Kernel Cross Reference
sys/ipc/ipc_notify.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: ipc_notify.c,v $
29 * Revision 2.10 93/11/17 16:59:17 dbg
30 * Added ANSI function prototypes.
31 * [93/09/23 dbg]
32 *
33 * Revision 2.9 93/01/14 17:33:03 danner
34 * 64bit cleanup.
35 * [92/11/30 af]
36 *
37 * Revision 2.8 92/08/03 17:34:53 jfriedl
38 * removed silly prototypes
39 * [92/08/02 jfriedl]
40 *
41 * Revision 2.7 92/05/21 17:10:54 jfriedl
42 * tried prototypes.
43 * [92/05/20 jfriedl]
44 *
45 * Revision 2.6 92/03/10 16:26:04 jsb
46 * Merged in norma branch changes as of NORMA_MK7:
47 * Added norma_ipc_notify_no_senders hook in ipc_notify_no_senders,
48 * using ip_nsproxy* macros.
49 * [92/03/09 13:24:06 jsb]
50 *
51 * Revision 2.5 91/08/28 11:13:41 jsb
52 * Changed msgh_kind to msgh_seqno.
53 * [91/08/09 rpd]
54 *
55 * Revision 2.4 91/05/14 16:34:24 mrt
56 * Correcting copyright
57 *
58 * Revision 2.3 91/02/05 17:22:33 mrt
59 * Changed to new Mach copyright
60 * [91/02/01 15:46:58 mrt]
61 *
62 * Revision 2.2 90/06/02 14:50:50 rpd
63 * Created for new IPC.
64 * [90/03/26 20:57:58 rpd]
65 *
66 */
67 /*
68 * File: ipc/ipc_notify.c
69 * Author: Rich Draves
70 * Date: 1989
71 *
72 * Notification-sending functions.
73 */
74
75 #include <mach_ipc_compat.h>
76
77 #include <mach/port.h>
78 #include <mach/message.h>
79 #include <mach/notify.h>
80 #include <kern/assert.h>
81 #include <kern/kern_io.h>
82 #include <ipc/ipc_kmsg.h>
83 #include <ipc/ipc_mqueue.h>
84 #include <ipc/ipc_notify.h>
85 #include <ipc/ipc_port.h>
86
87 #include <ipc/ipc_machdep.h>
88
89 mach_port_deleted_notification_t ipc_notify_port_deleted_template;
90 mach_msg_accepted_notification_t ipc_notify_msg_accepted_template;
91 mach_port_destroyed_notification_t ipc_notify_port_destroyed_template;
92 mach_no_senders_notification_t ipc_notify_no_senders_template;
93 mach_send_once_notification_t ipc_notify_send_once_template;
94 mach_dead_name_notification_t ipc_notify_dead_name_template;
95
96 #if MACH_IPC_COMPAT
97 /*
98 * When notification messages are received via the old
99 * msg_receive trap, the msg_type field should contain
100 * MSG_TYPE_EMERGENCY. We arrange for this by putting
101 * MSG_TYPE_EMERGENCY into msgh_seqno, which
102 * ipc_kmsg_copyout_compat copies to msg_type.
103 */
104
105 #define NOTIFY_MSGH_SEQNO MSG_TYPE_EMERGENCY
106 #else /* MACH_IPC_COMPAT */
107 #define NOTIFY_MSGH_SEQNO 0
108 #endif /* MACH_IPC_COMPAT */
109
110 /*
111 * Routine: ipc_notify_init_port_deleted
112 * Purpose:
113 * Initialize a template for port-deleted notifications.
114 */
115
116 void
117 ipc_notify_init_port_deleted(
118 mach_port_deleted_notification_t *n)
119 {
120 mach_msg_header_t *m = &n->not_header;
121 mach_msg_type_t *t = &n->not_type;
122
123 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
124 m->msgh_size = sizeof *n;
125 m->msgh_seqno = NOTIFY_MSGH_SEQNO;
126 m->msgh_local_port = MACH_PORT_NULL;
127 m->msgh_remote_port = MACH_PORT_NULL;
128 m->msgh_id = MACH_NOTIFY_PORT_DELETED;
129
130 t->msgt_name = MACH_MSG_TYPE_PORT_NAME;
131 t->msgt_size = PORT_T_SIZE_IN_BITS;
132 t->msgt_number = 1;
133 t->msgt_inline = TRUE;
134 t->msgt_longform = FALSE;
135 t->msgt_deallocate = FALSE;
136 t->msgt_unused = 0;
137
138 n->not_port = MACH_PORT_NULL;
139 }
140
141 /*
142 * Routine: ipc_notify_init_msg_accepted
143 * Purpose:
144 * Initialize a template for msg-accepted notifications.
145 */
146
147 void
148 ipc_notify_init_msg_accepted(
149 mach_msg_accepted_notification_t *n)
150 {
151 mach_msg_header_t *m = &n->not_header;
152 mach_msg_type_t *t = &n->not_type;
153
154 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
155 m->msgh_size = sizeof *n;
156 m->msgh_seqno = NOTIFY_MSGH_SEQNO;
157 m->msgh_local_port = MACH_PORT_NULL;
158 m->msgh_remote_port = MACH_PORT_NULL;
159 m->msgh_id = MACH_NOTIFY_MSG_ACCEPTED;
160
161 t->msgt_name = MACH_MSG_TYPE_PORT_NAME;
162 t->msgt_size = PORT_T_SIZE_IN_BITS;
163 t->msgt_number = 1;
164 t->msgt_inline = TRUE;
165 t->msgt_longform = FALSE;
166 t->msgt_deallocate = FALSE;
167 t->msgt_unused = 0;
168
169 n->not_port = MACH_PORT_NULL;
170 }
171
172 /*
173 * Routine: ipc_notify_init_port_destroyed
174 * Purpose:
175 * Initialize a template for port-destroyed notifications.
176 */
177
178 void
179 ipc_notify_init_port_destroyed(
180 mach_port_destroyed_notification_t *n)
181 {
182 mach_msg_header_t *m = &n->not_header;
183 mach_msg_type_t *t = &n->not_type;
184
185 m->msgh_bits = MACH_MSGH_BITS_COMPLEX |
186 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
187 m->msgh_size = sizeof *n;
188 m->msgh_seqno = NOTIFY_MSGH_SEQNO;
189 m->msgh_local_port = MACH_PORT_NULL;
190 m->msgh_remote_port = MACH_PORT_NULL;
191 m->msgh_id = MACH_NOTIFY_PORT_DESTROYED;
192
193 t->msgt_name = MACH_MSG_TYPE_PORT_RECEIVE;
194 t->msgt_size = PORT_T_SIZE_IN_BITS;
195 t->msgt_number = 1;
196 t->msgt_inline = TRUE;
197 t->msgt_longform = FALSE;
198 t->msgt_deallocate = FALSE;
199 t->msgt_unused = 0;
200
201 n->not_port = MACH_PORT_NULL;
202 }
203
204 /*
205 * Routine: ipc_notify_init_no_senders
206 * Purpose:
207 * Initialize a template for no-senders notifications.
208 */
209
210 void
211 ipc_notify_init_no_senders(
212 mach_no_senders_notification_t *n)
213 {
214 mach_msg_header_t *m = &n->not_header;
215 mach_msg_type_t *t = &n->not_type;
216
217 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
218 m->msgh_size = sizeof *n;
219 m->msgh_seqno = NOTIFY_MSGH_SEQNO;
220 m->msgh_local_port = MACH_PORT_NULL;
221 m->msgh_remote_port = MACH_PORT_NULL;
222 m->msgh_id = MACH_NOTIFY_NO_SENDERS;
223
224 t->msgt_name = MACH_MSG_TYPE_INTEGER_T;
225 t->msgt_size = PORT_T_SIZE_IN_BITS;
226 t->msgt_number = 1;
227 t->msgt_inline = TRUE;
228 t->msgt_longform = FALSE;
229 t->msgt_deallocate = FALSE;
230 t->msgt_unused = 0;
231
232 n->not_count = 0;
233 }
234
235 /*
236 * Routine: ipc_notify_init_send_once
237 * Purpose:
238 * Initialize a template for send-once notifications.
239 */
240
241 void
242 ipc_notify_init_send_once(
243 mach_send_once_notification_t *n)
244 {
245 mach_msg_header_t *m = &n->not_header;
246
247 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
248 m->msgh_size = sizeof *n;
249 m->msgh_seqno = NOTIFY_MSGH_SEQNO;
250 m->msgh_local_port = MACH_PORT_NULL;
251 m->msgh_remote_port = MACH_PORT_NULL;
252 m->msgh_id = MACH_NOTIFY_SEND_ONCE;
253 }
254
255 /*
256 * Routine: ipc_notify_init_dead_name
257 * Purpose:
258 * Initialize a template for dead-name notifications.
259 */
260
261 void
262 ipc_notify_init_dead_name(
263 mach_dead_name_notification_t *n)
264 {
265 mach_msg_header_t *m = &n->not_header;
266 mach_msg_type_t *t = &n->not_type;
267
268 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
269 m->msgh_size = sizeof *n;
270 m->msgh_seqno = NOTIFY_MSGH_SEQNO;
271 m->msgh_local_port = MACH_PORT_NULL;
272 m->msgh_remote_port = MACH_PORT_NULL;
273 m->msgh_id = MACH_NOTIFY_DEAD_NAME;
274
275 t->msgt_name = MACH_MSG_TYPE_PORT_NAME;
276 t->msgt_size = PORT_T_SIZE_IN_BITS;
277 t->msgt_number = 1;
278 t->msgt_inline = TRUE;
279 t->msgt_longform = FALSE;
280 t->msgt_deallocate = FALSE;
281 t->msgt_unused = 0;
282
283 n->not_port = MACH_PORT_NULL;
284 }
285
286 /*
287 * Routine: ipc_notify_init
288 * Purpose:
289 * Initialize the notification subsystem.
290 */
291
292 void
293 ipc_notify_init(void)
294 {
295 ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template);
296 ipc_notify_init_msg_accepted(&ipc_notify_msg_accepted_template);
297 ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template);
298 ipc_notify_init_no_senders(&ipc_notify_no_senders_template);
299 ipc_notify_init_send_once(&ipc_notify_send_once_template);
300 ipc_notify_init_dead_name(&ipc_notify_dead_name_template);
301 }
302
303 /*
304 * Routine: ipc_notify_port_deleted
305 * Purpose:
306 * Send a port-deleted notification.
307 * Conditions:
308 * Nothing locked.
309 * Consumes a ref/soright for port.
310 */
311
312 void
313 ipc_notify_port_deleted(
314 ipc_port_t port,
315 mach_port_t name)
316 {
317 ipc_kmsg_t kmsg;
318 mach_port_deleted_notification_t *n;
319
320 kmsg = ikm_alloc(sizeof *n);
321 if (kmsg == IKM_NULL) {
322 printf("dropped port-deleted (%#08x, %#x)\n",
323 (vm_offset_t) port, name);
324 ipc_port_release_sonce(port);
325 return;
326 }
327
328 ikm_init(kmsg, sizeof *n);
329 n = (mach_port_deleted_notification_t *) &kmsg->ikm_header;
330 *n = ipc_notify_port_deleted_template;
331
332 n->not_header.msgh_remote_port = (mach_port_t) port;
333 n->not_port = name;
334
335 ipc_mqueue_send_always(kmsg);
336 }
337
338 /*
339 * Routine: ipc_notify_msg_accepted
340 * Purpose:
341 * Send a msg-accepted notification.
342 * Conditions:
343 * Nothing locked.
344 * Consumes a ref/soright for port.
345 */
346
347 void
348 ipc_notify_msg_accepted(
349 ipc_port_t port,
350 mach_port_t name)
351 {
352 ipc_kmsg_t kmsg;
353 mach_msg_accepted_notification_t *n;
354
355 kmsg = ikm_alloc(sizeof *n);
356 if (kmsg == IKM_NULL) {
357 printf("dropped msg-accepted (%#08x, %#x)\n",
358 (vm_offset_t) port, name);
359 ipc_port_release_sonce(port);
360 return;
361 }
362
363 ikm_init(kmsg, sizeof *n);
364 n = (mach_msg_accepted_notification_t *) &kmsg->ikm_header;
365 *n = ipc_notify_msg_accepted_template;
366
367 n->not_header.msgh_remote_port = (mach_port_t) port;
368 n->not_port = name;
369
370 ipc_mqueue_send_always(kmsg);
371 }
372
373 /*
374 * Routine: ipc_notify_port_destroyed
375 * Purpose:
376 * Send a port-destroyed notification.
377 * Conditions:
378 * Nothing locked.
379 * Consumes a ref/soright for port.
380 * Consumes a ref for right, which should be a receive right
381 * prepped for placement into a message. (In-transit,
382 * or in-limbo if a circularity was detected.)
383 */
384
385 void
386 ipc_notify_port_destroyed(
387 ipc_port_t port,
388 ipc_port_t right)
389 {
390 ipc_kmsg_t kmsg;
391 mach_port_destroyed_notification_t *n;
392
393 kmsg = ikm_alloc(sizeof *n);
394 if (kmsg == IKM_NULL) {
395 printf("dropped port-destroyed (%#08x, %#08x)\n",
396 (vm_offset_t)port, (vm_offset_t) right);
397 ipc_port_release_sonce(port);
398 ipc_port_release_receive(right);
399 return;
400 }
401
402 ikm_init(kmsg, sizeof *n);
403 n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header;
404 *n = ipc_notify_port_destroyed_template;
405
406 n->not_header.msgh_remote_port = (mach_port_t) port;
407 n->not_port = (mach_port_t) right;
408
409 ipc_mqueue_send_always(kmsg);
410 }
411
412 /*
413 * Routine: ipc_notify_no_senders
414 * Purpose:
415 * Send a no-senders notification.
416 * Conditions:
417 * Nothing locked.
418 * Consumes a ref/soright for port.
419 */
420
421 void
422 ipc_notify_no_senders(
423 ipc_port_t port,
424 mach_port_mscount_t mscount)
425 {
426 ipc_kmsg_t kmsg;
427 mach_no_senders_notification_t *n;
428
429 #if NORMA_IPC
430 if (ip_nsproxyp(port)) {
431 assert(mscount == 0);
432 norma_ipc_notify_no_senders(ip_nsproxy(port));
433 return;
434 }
435 #endif /* NORMA_IPC */
436 kmsg = ikm_alloc(sizeof *n);
437 if (kmsg == IKM_NULL) {
438 printf("dropped no-senders (%#08x, %u)\n",
439 (vm_offset_t) port, mscount);
440 ipc_port_release_sonce(port);
441 return;
442 }
443
444 ikm_init(kmsg, sizeof *n);
445 n = (mach_no_senders_notification_t *) &kmsg->ikm_header;
446 *n = ipc_notify_no_senders_template;
447
448 n->not_header.msgh_remote_port = (mach_port_t) port;
449 n->not_count = mscount;
450
451 ipc_mqueue_send_always(kmsg);
452 }
453
454 /*
455 * Routine: ipc_notify_send_once
456 * Purpose:
457 * Send a send-once notification.
458 * Conditions:
459 * Nothing locked.
460 * Consumes a ref/soright for port.
461 */
462
463 void
464 ipc_notify_send_once(
465 ipc_port_t port)
466 {
467 ipc_kmsg_t kmsg;
468 mach_send_once_notification_t *n;
469
470 kmsg = ikm_alloc(sizeof *n);
471 if (kmsg == IKM_NULL) {
472 printf("dropped send-once (%#08x)\n", (vm_offset_t) port);
473 ipc_port_release_sonce(port);
474 return;
475 }
476
477 ikm_init(kmsg, sizeof *n);
478 n = (mach_send_once_notification_t *) &kmsg->ikm_header;
479 *n = ipc_notify_send_once_template;
480
481 n->not_header.msgh_remote_port = (mach_port_t) port;
482
483 ipc_mqueue_send_always(kmsg);
484 }
485
486 /*
487 * Routine: ipc_notify_dead_name
488 * Purpose:
489 * Send a dead-name notification.
490 * Conditions:
491 * Nothing locked.
492 * Consumes a ref/soright for port.
493 */
494
495 void
496 ipc_notify_dead_name(
497 ipc_port_t port,
498 mach_port_t name)
499 {
500 ipc_kmsg_t kmsg;
501 mach_dead_name_notification_t *n;
502
503 kmsg = ikm_alloc(sizeof *n);
504 if (kmsg == IKM_NULL) {
505 printf("dropped dead-name (%#08x, %#x)\n",
506 (vm_offset_t) port, name);
507 ipc_port_release_sonce(port);
508 return;
509 }
510
511 ikm_init(kmsg, sizeof *n);
512 n = (mach_dead_name_notification_t *) &kmsg->ikm_header;
513 *n = ipc_notify_dead_name_template;
514
515 n->not_header.msgh_remote_port = (mach_port_t) port;
516 n->not_port = name;
517
518 ipc_mqueue_send_always(kmsg);
519 }
520
521 #if MACH_IPC_COMPAT
522
523 /*
524 * Routine: ipc_notify_port_deleted_compat
525 * Purpose:
526 * Send a port-deleted notification.
527 * Sends it to a send right instead of a send-once right.
528 * Conditions:
529 * Nothing locked.
530 * Consumes a ref/sright for port.
531 */
532
533 void
534 ipc_notify_port_deleted_compat(
535 ipc_port_t port,
536 mach_port_t name)
537 {
538 ipc_kmsg_t kmsg;
539 mach_port_deleted_notification_t *n;
540
541 kmsg = ikm_alloc(sizeof *n);
542 if (kmsg == IKM_NULL) {
543 printf("dropped port-deleted-compat (%#08x, %#x)\n",
544 (vm_offset_t) port, name);
545 ipc_port_release_send(port);
546 return;
547 }
548
549 ikm_init(kmsg, sizeof *n);
550 n = (mach_port_deleted_notification_t *) &kmsg->ikm_header;
551 *n = ipc_notify_port_deleted_template;
552
553 n->not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0);
554 n->not_header.msgh_remote_port = (mach_port_t) port;
555 n->not_port = name;
556
557 ipc_mqueue_send_always(kmsg);
558 }
559
560 /*
561 * Routine: ipc_notify_msg_accepted_compat
562 * Purpose:
563 * Send a msg-accepted notification.
564 * Sends it to a send right instead of a send-once right.
565 * Conditions:
566 * Nothing locked.
567 * Consumes a ref/sright for port.
568 */
569
570 void
571 ipc_notify_msg_accepted_compat(
572 ipc_port_t port,
573 mach_port_t name)
574 {
575 ipc_kmsg_t kmsg;
576 mach_msg_accepted_notification_t *n;
577
578 kmsg = ikm_alloc(sizeof *n);
579 if (kmsg == IKM_NULL) {
580 printf("dropped msg-accepted-compat (%#08x, %#x)\n",
581 (vm_offset_t) port, name);
582 ipc_port_release_send(port);
583 return;
584 }
585
586 ikm_init(kmsg, sizeof *n);
587 n = (mach_msg_accepted_notification_t *) &kmsg->ikm_header;
588 *n = ipc_notify_msg_accepted_template;
589
590 n->not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0);
591 n->not_header.msgh_remote_port = (mach_port_t) port;
592 n->not_port = name;
593
594 ipc_mqueue_send_always(kmsg);
595 }
596
597 /*
598 * Routine: ipc_notify_port_destroyed_compat
599 * Purpose:
600 * Send a port-destroyed notification.
601 * Sends it to a send right instead of a send-once right.
602 * Conditions:
603 * Nothing locked.
604 * Consumes a ref/sright for port.
605 * Consumes a ref for right, which should be a receive right
606 * prepped for placement into a message. (In-transit,
607 * or in-limbo if a circularity was detected.)
608 */
609
610 void
611 ipc_notify_port_destroyed_compat(
612 ipc_port_t port,
613 ipc_port_t right)
614 {
615 ipc_kmsg_t kmsg;
616 mach_port_destroyed_notification_t *n;
617
618 kmsg = ikm_alloc(sizeof *n);
619 if (kmsg == IKM_NULL) {
620 printf("dropped port-destroyed-compat (%#08x, %#08x)\n",
621 (vm_offset_t) port, (vm_offset_t) right);
622 ipc_port_release_send(port);
623 ipc_port_release_receive(right);
624 return;
625 }
626
627 ikm_init(kmsg, sizeof *n);
628 n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header;
629 *n = ipc_notify_port_destroyed_template;
630
631 n->not_header.msgh_bits = MACH_MSGH_BITS_COMPLEX |
632 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0);
633 n->not_header.msgh_remote_port = (mach_port_t) port;
634 n->not_port = (mach_port_t) right;
635
636 ipc_mqueue_send_always(kmsg);
637 }
638
639 #endif /* MACH_IPC_COMPAT */
Cache object: b1f4d1fa51c25e05827abf3734ca9b23
|