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