]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_notify.c
xnu-344.34.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_notify.c
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 * Mach Operating System
27 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28 * All Rights Reserved.
29 *
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.
35 *
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.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50 /*
51 */
52 /*
53 * File: ipc/ipc_notify.c
54 * Author: Rich Draves
55 * Date: 1989
56 *
57 * Notification-sending functions.
58 */
59
60 #include <mach_rt.h>
61
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>
71
72 /*
73 * Forward declarations
74 */
75 void ipc_notify_init_port_deleted(
76 mach_port_deleted_notification_t *n);
77
78 void ipc_notify_init_port_destroyed(
79 mach_port_destroyed_notification_t *n);
80
81 void ipc_notify_init_no_senders(
82 mach_no_senders_notification_t *n);
83
84 void ipc_notify_init_send_once(
85 mach_send_once_notification_t *n);
86
87 void ipc_notify_init_dead_name(
88 mach_dead_name_notification_t *n);
89
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;
95
96 /*
97 * Routine: ipc_notify_init_port_deleted
98 * Purpose:
99 * Initialize a template for port-deleted notifications.
100 */
101
102 void
103 ipc_notify_init_port_deleted(
104 mach_port_deleted_notification_t *n)
105 {
106 mach_msg_header_t *m = &n->not_header;
107
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);
113
114 n->not_port = MACH_PORT_NULL;
115 n->NDR = NDR_record;
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;
120 }
121
122 /*
123 * Routine: ipc_notify_init_port_destroyed
124 * Purpose:
125 * Initialize a template for port-destroyed notifications.
126 */
127
128 void
129 ipc_notify_init_port_destroyed(
130 mach_port_destroyed_notification_t *n)
131 {
132 mach_msg_header_t *m = &n->not_header;
133
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);
140
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;
149 }
150
151 /*
152 * Routine: ipc_notify_init_no_senders
153 * Purpose:
154 * Initialize a template for no-senders notifications.
155 */
156
157 void
158 ipc_notify_init_no_senders(
159 mach_no_senders_notification_t *n)
160 {
161 mach_msg_header_t *m = &n->not_header;
162
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);
168
169 n->NDR = NDR_record;
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;
174 n->not_count = 0;
175 }
176
177 /*
178 * Routine: ipc_notify_init_send_once
179 * Purpose:
180 * Initialize a template for send-once notifications.
181 */
182
183 void
184 ipc_notify_init_send_once(
185 mach_send_once_notification_t *n)
186 {
187 mach_msg_header_t *m = &n->not_header;
188
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;
198 }
199
200 /*
201 * Routine: ipc_notify_init_dead_name
202 * Purpose:
203 * Initialize a template for dead-name notifications.
204 */
205
206 void
207 ipc_notify_init_dead_name(
208 mach_dead_name_notification_t *n)
209 {
210 mach_msg_header_t *m = &n->not_header;
211
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);
217
218 n->not_port = MACH_PORT_NULL;
219 n->NDR = NDR_record;
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;
224 }
225
226 /*
227 * Routine: ipc_notify_init
228 * Purpose:
229 * Initialize the notification subsystem.
230 */
231
232 void
233 ipc_notify_init(void)
234 {
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);
240 }
241
242 /*
243 * Routine: ipc_notify_port_deleted
244 * Purpose:
245 * Send a port-deleted notification.
246 * Conditions:
247 * Nothing locked.
248 * Consumes a ref/soright for port.
249 */
250
251 void
252 ipc_notify_port_deleted(
253 ipc_port_t port,
254 mach_port_name_t name)
255 {
256 ipc_kmsg_t kmsg;
257 mach_port_deleted_notification_t *n;
258
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);
263 return;
264 }
265
266 n = (mach_port_deleted_notification_t *) &kmsg->ikm_header;
267 *n = ipc_notify_port_deleted_template;
268
269 n->not_header.msgh_remote_port = port;
270 n->not_port = name;
271
272 ipc_kmsg_send_always(kmsg);
273 }
274
275 /*
276 * Routine: ipc_notify_port_destroyed
277 * Purpose:
278 * Send a port-destroyed notification.
279 * Conditions:
280 * Nothing locked.
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.)
285 */
286
287 void
288 ipc_notify_port_destroyed(
289 ipc_port_t port,
290 ipc_port_t right)
291 {
292 ipc_kmsg_t kmsg;
293 mach_port_destroyed_notification_t *n;
294
295 kmsg = ipc_kmsg_alloc(sizeof *n);
296 if (kmsg == IKM_NULL) {
297 printf("dropped port-destroyed (0x%08x, 0x%08x)\n",
298 port, right);
299 ipc_port_release_sonce(port);
300 ipc_port_release_receive(right);
301 return;
302 }
303
304 n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header;
305 *n = ipc_notify_port_destroyed_template;
306
307 n->not_header.msgh_remote_port = port;
308 n->not_port.name = right;
309
310 ipc_kmsg_send_always(kmsg);
311 }
312
313 /*
314 * Routine: ipc_notify_no_senders
315 * Purpose:
316 * Send a no-senders notification.
317 * Conditions:
318 * Nothing locked.
319 * Consumes a ref/soright for port.
320 */
321
322 void
323 ipc_notify_no_senders(
324 ipc_port_t port,
325 mach_port_mscount_t mscount)
326 {
327 ipc_kmsg_t kmsg;
328 mach_no_senders_notification_t *n;
329
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);
334 return;
335 }
336
337 n = (mach_no_senders_notification_t *) &kmsg->ikm_header;
338 *n = ipc_notify_no_senders_template;
339
340 n->not_header.msgh_remote_port = port;
341 n->not_count = mscount;
342
343 ipc_kmsg_send_always(kmsg);
344 }
345
346 /*
347 * Routine: ipc_notify_send_once
348 * Purpose:
349 * Send a send-once notification.
350 * Conditions:
351 * Nothing locked.
352 * Consumes a ref/soright for port.
353 */
354
355 void
356 ipc_notify_send_once(
357 ipc_port_t port)
358 {
359 ipc_kmsg_t kmsg;
360 mach_send_once_notification_t *n;
361
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);
366 return;
367 }
368
369 n = (mach_send_once_notification_t *) &kmsg->ikm_header;
370 *n = ipc_notify_send_once_template;
371
372 n->not_header.msgh_remote_port = port;
373
374 ipc_kmsg_send_always(kmsg);
375 }
376
377 /*
378 * Routine: ipc_notify_dead_name
379 * Purpose:
380 * Send a dead-name notification.
381 * Conditions:
382 * Nothing locked.
383 * Consumes a ref/soright for port.
384 */
385
386 void
387 ipc_notify_dead_name(
388 ipc_port_t port,
389 mach_port_name_t name)
390 {
391 ipc_kmsg_t kmsg;
392 mach_dead_name_notification_t *n;
393
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);
398 return;
399 }
400
401 n = (mach_dead_name_notification_t *) &kmsg->ikm_header;
402 *n = ipc_notify_dead_name_template;
403
404 n->not_header.msgh_remote_port = port;
405 n->not_port = name;
406
407 ipc_kmsg_send_always(kmsg);
408 }