1 /*
2 * Copyright (c) 2018 Apple 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 #ifndef __MACH_RIGHT_PRIVATE_H
29 #define __MACH_RIGHT_PRIVATE_H
30
31 #include <os/base.h>
32 #include <mach/mach.h>
33 #include <mach/port.h>
34 #include <mach/mach_port.h>
35 #include <sys/cdefs.h>
36 #include <stdbool.h>
37
38 __BEGIN_DECLS;
39
40 /*!
41 * @typedef mach_right_recv_t
42 * A type representing the receive right to a Mach port.
43 */
44 typedef struct _mach_right_recv {
45 mach_port_t mrr_name;
46 } mach_right_recv_t;
47
48 /*!
49 * @const MACH_RIGHT_RECV_NULL
50 * A convenience initializer for a receive right object.
51 */
52 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
53 #define MACH_RIGHT_RECV_NULL ((mach_right_recv_t){MACH_PORT_NULL})
54 #elif defined(__cplusplus) && __cplusplus >= 201103L
55 #define MACH_RIGHT_RECV_NULL (mach_right_recv_t{MACH_PORT_NULL})
56 #elif defined(__cplusplus)
57 #define MACH_RIGHT_RECV_NULL \
58 (mach_right_recv_t((mach_right_recv_t){MACH_PORT_NULL}))
59 #else
60 #define MACH_RIGHT_RECV_NULL {MACH_PORT_NULL}
61 #endif
62
63 /*!
64 * @typedef mach_right_send_t
65 * A type representing a send right to a Mach port.
66 */
67 typedef struct _mach_right_send {
68 mach_port_t mrs_name;
69 } mach_right_send_t;
70
71 /*!
72 * @const MACH_RIGHT_SEND_NULL
73 * A convenience initializer for a send right object.
74 */
75 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
76 #define MACH_RIGHT_SEND_NULL ((mach_right_send_t){MACH_PORT_NULL})
77 #elif defined(__cplusplus) && __cplusplus >= 201103L
78 #define MACH_RIGHT_SEND_NULL (mach_right_send_t{MACH_PORT_NULL})
79 #elif defined(__cplusplus)
80 #define MACH_RIGHT_SEND_NULL \
81 (mach_right_send_t((mach_right_send_t){MACH_PORT_NULL}))
82 #else
83 #define MACH_RIGHT_SEND_NULL {MACH_PORT_NULL}
84 #endif
85
86 /*!
87 * @typedef mach_right_send_once_t
88 * A type representing a send-once right to a Mach port.
89 */
90 typedef struct _mach_right_send_once {
91 mach_port_t mrso_name;
92 } mach_right_send_once_t;
93
94 /*!
95 * @const MACH_RIGHT_SEND_ONCE_NULL
96 * A convenience initializer for a send-once right object.
97 */
98 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
99 #define MACH_RIGHT_SEND_ONCE_NULL ((mach_right_send_once_t){MACH_PORT_NULL})
100 #elif defined(__cplusplus) && __cplusplus >= 201103L
101 #define MACH_RIGHT_SEND_ONCE_NULL (mach_right_send_once_t{MACH_PORT_NULL})
102 #elif defined(__cplusplus)
103 #define MACH_RIGHT_SEND_ONCE_NULL \
104 (mach_right_send_once_t((mach_right_send_once_t){MACH_PORT_NULL}))
105 #else
106 #define MACH_RIGHT_SEND_ONCE_NULL {MACH_PORT_NULL}
107 #endif
108
109 /*!
110 * @function mach_right_recv
111 * Wraps a port name as a receive right object.
112 *
113 * @param pn
114 * The port name. If this name is valid but does not represent a receive right,
115 * the behavior of mach_right_recv_* implementations is undefined.
116 *
117 * @result
118 * A new receive right object.
119 */
120 OS_ALWAYS_INLINE OS_WARN_RESULT
121 static inline mach_right_recv_t
mach_right_recv(mach_port_name_t pn)122 mach_right_recv(mach_port_name_t pn)
123 {
124 mach_right_recv_t mrr = {pn};
125 return mrr;
126 }
127
128 /*!
129 * @function mach_right_send
130 * Wraps a port name as a send right object.
131 *
132 * @param pn
133 * The port name. If this name is valid but does not represent a send right, the
134 * behavior of mach_right_send_* implementations is undefined.
135 *
136 * @result
137 * A new send right object.
138 */
139 OS_ALWAYS_INLINE OS_WARN_RESULT
140 static inline mach_right_send_t
mach_right_send(mach_port_name_t pn)141 mach_right_send(mach_port_name_t pn)
142 {
143 mach_right_send_t mrs = {pn};
144 return mrs;
145 }
146
147 /*!
148 * @function mach_right_send_valid
149 * Checks if the given send right object is valid.
150 *
151 * @param mrs
152 * The send right object to check.
153 *
154 * @result
155 * A Boolean indicating whether the right is valid.
156 */
157 OS_ALWAYS_INLINE OS_WARN_RESULT
158 static inline bool
mach_right_send_valid(mach_right_send_t mrs)159 mach_right_send_valid(mach_right_send_t mrs)
160 {
161 return MACH_PORT_VALID(mrs.mrs_name);
162 }
163
164 /*!
165 * @function mach_right_send_once
166 * Wraps a port name as a send-once right object.
167 *
168 * @param pn
169 * The port name. If this name is valid but does not represent a send-once
170 * right, the behavior of mach_right_send_once_* implementations is undefined.
171 *
172 * @result
173 * A new send-once right object.
174 */
175 OS_ALWAYS_INLINE OS_WARN_RESULT
176 static inline mach_right_send_once_t
mach_right_send_once(mach_port_name_t pn)177 mach_right_send_once(mach_port_name_t pn)
178 {
179 mach_right_send_once_t mrso = {pn};
180 return mrso;
181 }
182
183 /*!
184 * @function mach_right_send_once_valid
185 * Checks if the given send-once right object is valid.
186 *
187 * @param mrso
188 * The send-once right object to check.
189 *
190 * @result
191 * A Boolean indicating whether the right is valid.
192 */
193 OS_ALWAYS_INLINE OS_WARN_RESULT
194 static inline bool
mach_right_send_once_valid(mach_right_send_once_t mrso)195 mach_right_send_once_valid(mach_right_send_once_t mrso)
196 {
197 return MACH_PORT_VALID(mrso.mrso_name);
198 }
199
200 /*!
201 * @typedef mach_right_flags_t
202 * Flags influencing the behavior of a constructed Mach port.
203 *
204 * @const MACH_RIGHT_RECV_INIT
205 * No flags set. This value is suitable for initialization purposes.
206 *
207 * @const MACH_RIGHT_RECV_UNGUARDED
208 * The given context should not serve as a guard for the underlying port's
209 * destruction.
210 */
211 OS_ENUM(mach_right_flags, uint64_t,
212 MACH_RIGHT_RECV_FLAG_INIT = 0,
213 MACH_RIGHT_RECV_FLAG_UNGUARDED = (1 << 0),
214 );
215
216 /*!
217 * @function mach_right_recv_construct
218 * Allocates a new Mach port and returns the receive right to the caller.
219 *
220 * @param flags
221 * Flags to influence the behavior of the new port.
222 *
223 * @param sr
224 * If non-NULL, will be filled in with the name of a send right which
225 * corresponds to the new port. The caller is responsible for disposing of this
226 * send right with {@link mach_right_send_release}.
227 *
228 * @param ctx
229 * Context to be associated with the new port. By default, this context must be
230 * passed to {@link mach_right_recv_destruct} in order to destroy the underlying
231 * port. This requirement may be elided with the
232 * {@link MACH_RIGHT_RECV_UNGUARDED} flag.
233 *
234 * @result
235 * A new port handle which refers to the receive right for the newly-created
236 * port. The caller is responsible for disposing of this handle with
237 * {@link mach_right_recv_destruct}.
238 *
239 * @discussion
240 * The implementation will abort on any failure to allocate a new port object in
241 * the kernel. Thus the caller may assert that a new, valid receive right is
242 * always returned.
243 */
244 OS_EXPORT OS_WARN_RESULT
245 mach_right_recv_t
246 mach_right_recv_construct(mach_right_flags_t flags,
247 mach_right_send_t *_Nullable sr, uintptr_t ctx);
248
249 /*!
250 * @function mach_right_recv_destruct
251 * Closes the port referred to by the given receive right.
252 *
253 * @param r
254 * The receive right for the port to manipulate.
255 *
256 * @param s
257 * A pointer to the send right to dispose of. If NULL is given, no attempt will
258 * be made to clean up any send right associated with the port. If the name of
259 * the given send right does not match the name of the given receive right, the
260 * implementation's behavior is undefined.
261 *
262 * @param ctx
263 * The context which guards the underlying port destruction. If the receive
264 * right was created with {@link MACH_RIGHT_RECV_UNGUARDED}, this parameter is
265 * ignored.
266 *
267 * @discussion
268 * If a send right is passed, the implementation performs the moral equivalent
269 * of
270 *
271 * mach_right_recv_destruct(r, MACH_PORT_NULL, ctx);
272 * mach_right_send_release(s);
273 *
274 * except in a more efficient manner, requiring only one system call.
275 *
276 * The implementation will abort on any failure to dispose of the port. As such,
277 * this routine should only be used on ports that are known to be under the
278 * caller's complete control.
279 */
280 OS_EXPORT
281 void
282 mach_right_recv_destruct(mach_right_recv_t r, mach_right_send_t *_Nullable s,
283 uintptr_t ctx);
284
285 /*!
286 * @function mach_right_send_create
287 * Creates a send right to the port referenced by the given receive right.
288 *
289 * @param r
290 * The receive right for the port for which to create the send right.
291 *
292 * @result
293 * The name of the new send right. The caller is responsible for disposing of
294 * this send right with {@link mach_right_send_release}.
295 *
296 * This operation will increment the make-send count of the port referenced by
297 * the given receive right.
298 *
299 * @discussion
300 * The implementation will abort on any failure to create the send right. As
301 * such, this routine should only be used on ports that are known to be under
302 * the caller's complete control.
303 */
304 OS_EXPORT OS_WARN_RESULT
305 mach_right_send_t
306 mach_right_send_create(mach_right_recv_t r);
307
308 /*!
309 * @function mach_right_send_retain
310 * Increments the user reference count for the given send right.
311 *
312 * @param s
313 * The send right to manipulate.
314 *
315 * @result
316 * If the reference count was successfully incremented, the given port name is
317 * returned. If either MACH_PORT_NULL or MACH_PORT_DEAD are given, the given
318 * value is returned. If the given send right became a dead name before or
319 * during the attempt to retain the send right, MACH_PORT_DEAD is returned.
320 *
321 * If the implementation encounters any other failure condition, it will abort.
322 */
323 OS_EXPORT OS_WARN_RESULT
324 mach_right_send_t
325 mach_right_send_retain(mach_right_send_t s);
326
327 /*!
328 * @function mach_right_send_release
329 * Decrements the user reference count for the given send right.
330 *
331 * @param s
332 * The send right to manipulate.
333 *
334 * @discussion
335 * If the given send right became a dead name before or during the attempt to
336 * release it, the implementation will dispose of that dead name.
337 *
338 * If the implementation encounters any other failure condition, it will abort.
339 */
340 OS_EXPORT
341 void
342 mach_right_send_release(mach_right_send_t s);
343
344 /*!
345 * @function mach_right_send_once_create
346 * Creates a send-once right from the given receive right.
347 *
348 * @param r
349 * The receive right for the port for which to create the send-once right.
350 *
351 * @result
352 * The newly-created send-once right.
353 *
354 * @discussion
355 * The implementation will abort on any failure to allocate a new send-once
356 * right, and therefore the caller should only provide a receive right which is
357 * under its complete control. The caller may assert that a new, valid send-once
358 * right is always returned.
359 *
360 * The returned send-once right will never share a name with the given receive
361 * right. A send-once right must be consumed either by using it to send a
362 * message or by consuming it with {@link mach_right_send_once_consume}.
363 *
364 * The returned right does not support retain/release semantics despite the
365 * presence of "create" in the name.
366 */
367 OS_EXPORT OS_WARN_RESULT
368 mach_right_send_once_t
369 mach_right_send_once_create(mach_right_recv_t r);
370
371 /*!
372 * @function mach_right_send_once_consume
373 * Consumes the given send-once right.
374 *
375 * @param so
376 * The send-once right to manipulate.
377 *
378 * @discussion
379 * If the given send-once right became a dead name before or during the attempt
380 * to release it, the implementation will dispose of that dead name.
381 *
382 * If the implementation encounters any other failure condition, it will abort.
383 *
384 * This operation will cause a send-once notification to be delivered to the
385 * port to which the send-once right refers unless the right is a dead name, in
386 * which case there are no side effects.
387 */
388 OS_EXPORT
389 void
390 mach_right_send_once_consume(mach_right_send_once_t so);
391
392 __END_DECLS;
393
394 #endif // __MACH_RIGHT_PRIVATE_H
395