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 Software.Distribution@CS.CMU.EDU
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
83void
84ipc_notify_port_deleted(
85 ipc_port_t port,
86 mach_port_name_t name)
87{
88 (void)mach_notify_port_deleted(notify: 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
101void
102ipc_notify_send_possible(
103 ipc_port_t port,
104 mach_port_name_t name)
105{
106 (void)mach_notify_send_possible(notify: 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
122void
123ipc_notify_port_destroyed(
124 ipc_port_t port,
125 ipc_port_t right)
126{
127 mach_notify_port_destroyed(notify: port, rights: 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 */
144ipc_notify_nsenders_t
145ipc_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
183void
184ipc_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(notify: 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
206void
207ipc_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(port: 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
228void
229ipc_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, space: 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(notify: 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
254void
255ipc_notify_dead_name(
256 ipc_port_t port,
257 mach_port_name_t name)
258{
259 (void)mach_notify_dead_name(notify: port, name);
260 /* send-once right consumed */
261}
262