1 /*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or [email protected]
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56 /*
57 */
58 /*
59 * File: ipc/ipc_notify.c
60 * Author: Rich Draves
61 * Date: 1989
62 *
63 * Notification-sending functions.
64 */
65
66 #include <mach/port.h>
67 #include <mach/message.h>
68 #include <mach/mach_notify.h>
69 #include <kern/misc_protos.h>
70 #include <kern/ipc_kobject.h>
71 #include <ipc/ipc_notify.h>
72 #include <ipc/ipc_port.h>
73
74 /*
75 * Routine: ipc_notify_port_deleted
76 * Purpose:
77 * Send a port-deleted notification.
78 * Conditions:
79 * Nothing locked.
80 * Consumes a ref/soright for port.
81 */
82
83 void
ipc_notify_port_deleted(ipc_port_t port,mach_port_name_t name)84 ipc_notify_port_deleted(
85 ipc_port_t port,
86 mach_port_name_t name)
87 {
88 (void)mach_notify_port_deleted(port, name);
89 /* send-once right consumed */
90 }
91
92 /*
93 * Routine: ipc_notify_send_possible
94 * Purpose:
95 * Send a send-possible notification.
96 * Conditions:
97 * Nothing locked.
98 * Consumes a ref/soright for port.
99 */
100
101 void
ipc_notify_send_possible(ipc_port_t port,mach_port_name_t name)102 ipc_notify_send_possible(
103 ipc_port_t port,
104 mach_port_name_t name)
105 {
106 (void)mach_notify_send_possible(port, name);
107 /* send-once right consumed */
108 }
109
110 /*
111 * Routine: ipc_notify_port_destroyed
112 * Purpose:
113 * Send a port-destroyed notification.
114 * Conditions:
115 * Nothing locked.
116 * Consumes a ref/soright for port.
117 * Consumes a ref for right, which should be a receive right
118 * prepped for placement into a message. (In-transit,
119 * or in-limbo if a circularity was detected.)
120 */
121
122 void
ipc_notify_port_destroyed(ipc_port_t port,ipc_port_t right)123 ipc_notify_port_destroyed(
124 ipc_port_t port,
125 ipc_port_t right)
126 {
127 mach_notify_port_destroyed(port, right);
128 /* send-once and receive rights consumed */
129 }
130
131 /*
132 * Routine: ipc_notify_no_senders_prepare
133 * Purpose:
134 * Prepare for consuming a no senders notification
135 * when the port send right count just hit 0.
136 * Conditions:
137 * The port is locked.
138 *
139 * For kobjects (ns_is_kobject), the `ns_notify` port has a reference.
140 * For regular ports, the `ns_notify` has an outstanding send once right.
141 * Returns:
142 * A token that must be passed to ipc_notify_no_senders_emit.
143 */
144 ipc_notify_nsenders_t
ipc_notify_no_senders_prepare(ipc_port_t port)145 ipc_notify_no_senders_prepare(
146 ipc_port_t port)
147 {
148 ipc_notify_nsenders_t req = { };
149
150 ip_mq_lock_held(port);
151
152 if (port->ip_nsrequest == IP_KOBJECT_NSREQUEST_ARMED) {
153 port->ip_nsrequest = IP_NULL;
154
155 if (ip_active(port)) {
156 req.ns_notify = port;
157 req.ns_mscount = port->ip_mscount;
158 req.ns_is_kobject = true;
159 } else {
160 /* silently consume the port-ref */
161 ip_release_live(port);
162 }
163 } else if (port->ip_nsrequest) {
164 req.ns_notify = port->ip_nsrequest;
165 req.ns_mscount = port->ip_mscount;
166 req.ns_is_kobject = false;
167
168 port->ip_nsrequest = IP_NULL;
169 }
170
171 return req;
172 }
173
174 /*
175 * Routine: ipc_notify_no_senders
176 * Purpose:
177 * Send a no-senders notification.
178 * Conditions:
179 * Nothing locked.
180 * Consumes a ref/soright for port.
181 */
182
183 void
ipc_notify_no_senders(ipc_port_t port,mach_port_mscount_t mscount,boolean_t kobject)184 ipc_notify_no_senders(
185 ipc_port_t port,
186 mach_port_mscount_t mscount,
187 boolean_t kobject)
188 {
189 if (kobject) {
190 ipc_kobject_notify_no_senders(port, mscount);
191 } else {
192 (void)mach_notify_no_senders(port, mscount);
193 /* send-once right consumed */
194 }
195 }
196
197 /*
198 * Routine: ipc_notify_no_senders_consume
199 * Purpose:
200 * Consume a no-senders notification.
201 * Conditions:
202 * Nothing locked.
203 * Consumes a ref/soright for port.
204 */
205
206 void
ipc_notify_no_senders_consume(ipc_notify_nsenders_t nsrequest)207 ipc_notify_no_senders_consume(
208 ipc_notify_nsenders_t nsrequest)
209 {
210 if (nsrequest.ns_notify) {
211 if (nsrequest.ns_is_kobject) {
212 ip_release(nsrequest.ns_notify);
213 } else {
214 ipc_port_release_sonce(nsrequest.ns_notify);
215 }
216 }
217 }
218
219 /*
220 * Routine: ipc_notify_send_once_and_unlock
221 * Purpose:
222 * Send a send-once notification.
223 * Conditions:
224 * Port is locked.
225 * Consumes a ref/soright for port.
226 */
227
228 void
ipc_notify_send_once_and_unlock(ipc_port_t port)229 ipc_notify_send_once_and_unlock(
230 ipc_port_t port)
231 {
232 if (!ip_active(port)) {
233 ipc_port_release_sonce_and_unlock(port);
234 } else if (ip_in_space(port, ipc_space_kernel)) {
235 ipc_kobject_notify_send_once_and_unlock(port);
236 } else if (ip_full_kernel(port)) {
237 ipc_port_release_sonce_and_unlock(port);
238 } else {
239 ip_mq_unlock(port);
240 (void)mach_notify_send_once(port);
241 }
242 /* send-once right consumed */
243 }
244
245 /*
246 * Routine: ipc_notify_dead_name
247 * Purpose:
248 * Send a dead-name notification.
249 * Conditions:
250 * Nothing locked.
251 * Consumes a ref/soright for port.
252 */
253
254 void
ipc_notify_dead_name(ipc_port_t port,mach_port_name_t name)255 ipc_notify_dead_name(
256 ipc_port_t port,
257 mach_port_name_t name)
258 {
259 (void)mach_notify_dead_name(port, name);
260 /* send-once right consumed */
261 }
262