2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
53 * File: ipc/ipc_notify.c
57 * Notification-sending functions.
62 #include <mach/port.h>
63 #include <mach/message.h>
64 #include <mach/notify.h>
65 #include <kern/assert.h>
66 #include <kern/misc_protos.h>
67 #include <ipc/ipc_kmsg.h>
68 #include <ipc/ipc_mqueue.h>
69 #include <ipc/ipc_notify.h>
70 #include <ipc/ipc_port.h>
73 * Forward declarations
75 void ipc_notify_init_port_deleted(
76 mach_port_deleted_notification_t
*n
);
78 void ipc_notify_init_port_destroyed(
79 mach_port_destroyed_notification_t
*n
);
81 void ipc_notify_init_no_senders(
82 mach_no_senders_notification_t
*n
);
84 void ipc_notify_init_send_once(
85 mach_send_once_notification_t
*n
);
87 void ipc_notify_init_dead_name(
88 mach_dead_name_notification_t
*n
);
90 mach_port_deleted_notification_t ipc_notify_port_deleted_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
;
97 * Routine: ipc_notify_init_port_deleted
99 * Initialize a template for port-deleted notifications.
103 ipc_notify_init_port_deleted(
104 mach_port_deleted_notification_t
*n
)
106 mach_msg_header_t
*m
= &n
->not_header
;
108 m
->msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE
, 0);
109 m
->msgh_local_port
= MACH_PORT_NULL
;
110 m
->msgh_remote_port
= MACH_PORT_NULL
;
111 m
->msgh_id
= MACH_NOTIFY_PORT_DELETED
;
112 m
->msgh_size
= ((int)sizeof *n
) - sizeof(mach_msg_format_0_trailer_t
);
114 n
->not_port
= MACH_PORT_NULL
;
116 n
->trailer
.msgh_seqno
= 0;
117 n
->trailer
.msgh_sender
= KERNEL_SECURITY_TOKEN
;
118 n
->trailer
.msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
119 n
->trailer
.msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
123 * Routine: ipc_notify_init_port_destroyed
125 * Initialize a template for port-destroyed notifications.
129 ipc_notify_init_port_destroyed(
130 mach_port_destroyed_notification_t
*n
)
132 mach_msg_header_t
*m
= &n
->not_header
;
134 m
->msgh_bits
= MACH_MSGH_BITS_COMPLEX
|
135 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE
, 0);
136 m
->msgh_local_port
= MACH_PORT_NULL
;
137 m
->msgh_remote_port
= MACH_PORT_NULL
;
138 m
->msgh_id
= MACH_NOTIFY_PORT_DESTROYED
;
139 m
->msgh_size
= ((int)sizeof *n
) - sizeof(mach_msg_format_0_trailer_t
);
141 n
->not_body
.msgh_descriptor_count
= 1;
142 n
->not_port
.disposition
= MACH_MSG_TYPE_PORT_RECEIVE
;
143 n
->not_port
.name
= MACH_PORT_NULL
;
144 n
->not_port
.type
= MACH_MSG_PORT_DESCRIPTOR
;
145 n
->trailer
.msgh_seqno
= 0;
146 n
->trailer
.msgh_sender
= KERNEL_SECURITY_TOKEN
;
147 n
->trailer
.msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
148 n
->trailer
.msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
152 * Routine: ipc_notify_init_no_senders
154 * Initialize a template for no-senders notifications.
158 ipc_notify_init_no_senders(
159 mach_no_senders_notification_t
*n
)
161 mach_msg_header_t
*m
= &n
->not_header
;
163 m
->msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE
, 0);
164 m
->msgh_local_port
= MACH_PORT_NULL
;
165 m
->msgh_remote_port
= MACH_PORT_NULL
;
166 m
->msgh_id
= MACH_NOTIFY_NO_SENDERS
;
167 m
->msgh_size
= ((int)sizeof *n
) - sizeof(mach_msg_format_0_trailer_t
);
170 n
->trailer
.msgh_seqno
= 0;
171 n
->trailer
.msgh_sender
= KERNEL_SECURITY_TOKEN
;
172 n
->trailer
.msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
173 n
->trailer
.msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
178 * Routine: ipc_notify_init_send_once
180 * Initialize a template for send-once notifications.
184 ipc_notify_init_send_once(
185 mach_send_once_notification_t
*n
)
187 mach_msg_header_t
*m
= &n
->not_header
;
189 m
->msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE
, 0);
190 m
->msgh_local_port
= MACH_PORT_NULL
;
191 m
->msgh_remote_port
= MACH_PORT_NULL
;
192 m
->msgh_id
= MACH_NOTIFY_SEND_ONCE
;
193 m
->msgh_size
= ((int)sizeof *n
) - sizeof(mach_msg_format_0_trailer_t
);
194 n
->trailer
.msgh_seqno
= 0;
195 n
->trailer
.msgh_sender
= KERNEL_SECURITY_TOKEN
;
196 n
->trailer
.msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
197 n
->trailer
.msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
201 * Routine: ipc_notify_init_dead_name
203 * Initialize a template for dead-name notifications.
207 ipc_notify_init_dead_name(
208 mach_dead_name_notification_t
*n
)
210 mach_msg_header_t
*m
= &n
->not_header
;
212 m
->msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE
, 0);
213 m
->msgh_local_port
= MACH_PORT_NULL
;
214 m
->msgh_remote_port
= MACH_PORT_NULL
;
215 m
->msgh_id
= MACH_NOTIFY_DEAD_NAME
;
216 m
->msgh_size
= ((int)sizeof *n
) - sizeof(mach_msg_format_0_trailer_t
);
218 n
->not_port
= MACH_PORT_NULL
;
220 n
->trailer
.msgh_seqno
= 0;
221 n
->trailer
.msgh_sender
= KERNEL_SECURITY_TOKEN
;
222 n
->trailer
.msgh_trailer_type
= MACH_MSG_TRAILER_FORMAT_0
;
223 n
->trailer
.msgh_trailer_size
= MACH_MSG_TRAILER_MINIMUM_SIZE
;
227 * Routine: ipc_notify_init
229 * Initialize the notification subsystem.
233 ipc_notify_init(void)
235 ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template
);
236 ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template
);
237 ipc_notify_init_no_senders(&ipc_notify_no_senders_template
);
238 ipc_notify_init_send_once(&ipc_notify_send_once_template
);
239 ipc_notify_init_dead_name(&ipc_notify_dead_name_template
);
243 * Routine: ipc_notify_port_deleted
245 * Send a port-deleted notification.
248 * Consumes a ref/soright for port.
252 ipc_notify_port_deleted(
254 mach_port_name_t name
)
257 mach_port_deleted_notification_t
*n
;
259 kmsg
= ipc_kmsg_alloc(sizeof *n
);
260 if (kmsg
== IKM_NULL
) {
261 printf("dropped port-deleted (0x%08x, 0x%x)\n", port
, name
);
262 ipc_port_release_sonce(port
);
266 n
= (mach_port_deleted_notification_t
*) &kmsg
->ikm_header
;
267 *n
= ipc_notify_port_deleted_template
;
269 n
->not_header
.msgh_remote_port
= port
;
272 ipc_kmsg_send_always(kmsg
);
276 * Routine: ipc_notify_port_destroyed
278 * Send a port-destroyed notification.
281 * Consumes a ref/soright for port.
282 * Consumes a ref for right, which should be a receive right
283 * prepped for placement into a message. (In-transit,
284 * or in-limbo if a circularity was detected.)
288 ipc_notify_port_destroyed(
293 mach_port_destroyed_notification_t
*n
;
295 kmsg
= ipc_kmsg_alloc(sizeof *n
);
296 if (kmsg
== IKM_NULL
) {
297 printf("dropped port-destroyed (0x%08x, 0x%08x)\n",
299 ipc_port_release_sonce(port
);
300 ipc_port_release_receive(right
);
304 n
= (mach_port_destroyed_notification_t
*) &kmsg
->ikm_header
;
305 *n
= ipc_notify_port_destroyed_template
;
307 n
->not_header
.msgh_remote_port
= port
;
308 n
->not_port
.name
= right
;
310 ipc_kmsg_send_always(kmsg
);
314 * Routine: ipc_notify_no_senders
316 * Send a no-senders notification.
319 * Consumes a ref/soright for port.
323 ipc_notify_no_senders(
325 mach_port_mscount_t mscount
)
328 mach_no_senders_notification_t
*n
;
330 kmsg
= ipc_kmsg_alloc(sizeof *n
);
331 if (kmsg
== IKM_NULL
) {
332 printf("dropped no-senders (0x%08x, %u)\n", port
, mscount
);
333 ipc_port_release_sonce(port
);
337 n
= (mach_no_senders_notification_t
*) &kmsg
->ikm_header
;
338 *n
= ipc_notify_no_senders_template
;
340 n
->not_header
.msgh_remote_port
= port
;
341 n
->not_count
= mscount
;
343 ipc_kmsg_send_always(kmsg
);
347 * Routine: ipc_notify_send_once
349 * Send a send-once notification.
352 * Consumes a ref/soright for port.
356 ipc_notify_send_once(
360 mach_send_once_notification_t
*n
;
362 kmsg
= ipc_kmsg_alloc(sizeof *n
);
363 if (kmsg
== IKM_NULL
) {
364 printf("dropped send-once (0x%08x)\n", port
);
365 ipc_port_release_sonce(port
);
369 n
= (mach_send_once_notification_t
*) &kmsg
->ikm_header
;
370 *n
= ipc_notify_send_once_template
;
372 n
->not_header
.msgh_remote_port
= port
;
374 ipc_kmsg_send_always(kmsg
);
378 * Routine: ipc_notify_dead_name
380 * Send a dead-name notification.
383 * Consumes a ref/soright for port.
387 ipc_notify_dead_name(
389 mach_port_name_t name
)
392 mach_dead_name_notification_t
*n
;
394 kmsg
= ipc_kmsg_alloc(sizeof *n
);
395 if (kmsg
== IKM_NULL
) {
396 printf("dropped dead-name (0x%08x, 0x%x)\n", port
, name
);
397 ipc_port_release_sonce(port
);
401 n
= (mach_dead_name_notification_t
*) &kmsg
->ikm_header
;
402 *n
= ipc_notify_dead_name_template
;
404 n
->not_header
.msgh_remote_port
= port
;
407 ipc_kmsg_send_always(kmsg
);