xref: /NextBSD/lib/libdispatch/private/mach_private.h (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20 
21 /*
22  * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23  * which are subject to change in future releases of Mac OS X. Any applications
24  * relying on these interfaces WILL break.
25  */
26 
27 #ifndef __DISPATCH_MACH_PRIVATE__
28 #define __DISPATCH_MACH_PRIVATE__
29 
30 #ifndef __DISPATCH_INDIRECT__
31 #error "Please #include <dispatch/dispatch.h> instead of this file directly."
32 #include <dispatch/base.h> // for HeaderDoc
33 #endif
34 
35 __BEGIN_DECLS
36 
37 #if DISPATCH_MACH_SPI
38 
39 #include <mach/mach.h>
40 
41 /*!
42  * @functiongroup Dispatch Mach Channel SPI
43  *
44  * IMPORTANT: This is Libsystem-internal SPI not intended for general use and
45  * is subject to change at any time without warning.
46  */
47 
48 /*!
49  * @typedef dispatch_mach_t
50  * A dispatch mach channel asynchronously recevives and sends mach messages.
51  */
52 DISPATCH_DECL(dispatch_mach);
53 
54 /*!
55  * @typedef dispatch_mach_reason_t
56  * Reasons for a mach channel handler to be invoked.
57  *
58  * @const DISPATCH_MACH_CONNECTED
59  * The channel has been connected. The first handler invocation on a channel
60  * after calling dispatch_mach_connect() will have this reason.
61  *
62  * @const DISPATCH_MACH_MESSAGE_RECEIVED
63  * A message was received, it is passed in the message parameter.
64  *
65  * @const DISPATCH_MACH_MESSAGE_SENT
66  * A message was sent, it is passed in the message parameter (so that associated
67  * resources can be disposed of).
68  *
69  * @const DISPATCH_MACH_MESSAGE_SEND_FAILED
70  * A message failed to be sent, it is passed in the message parameter (so that
71  * associated resources can be disposed of), along with the error code from
72  * mach_msg().
73  *
74  * @const DISPATCH_MACH_MESSAGE_NOT_SENT
75  * A message was not sent due to the channel being canceled or reconnected, it
76  * is passed in the message parameter (so that associated resources can be
77  * disposed of).
78  *
79  * @const DISPATCH_MACH_BARRIER_COMPLETED
80  * A barrier block has finished executing.
81  *
82  * @const DISPATCH_MACH_DISCONNECTED
83  * The channel has been disconnected by a call to dispatch_mach_reconnect() or
84  * dispatch_mach_cancel(), an empty message is passed in the message parameter
85  * (so that associated port rights can be disposed of).
86  * The message header will contain either a remote port with a previously
87  * connected send right, or a local port with a previously connected receive
88  * right (if the channel was canceled), or a local port with a receive right
89  * that was being monitored for a direct reply to a message previously sent to
90  * the channel (if no reply was received).
91  *
92  * @const DISPATCH_MACH_CANCELED
93  * The channel has been canceled.
94  */
95 DISPATCH_ENUM(dispatch_mach_reason, unsigned long,
96 	DISPATCH_MACH_CONNECTED = 1,
97 	DISPATCH_MACH_MESSAGE_RECEIVED,
98 	DISPATCH_MACH_MESSAGE_SENT,
99 	DISPATCH_MACH_MESSAGE_SEND_FAILED,
100 	DISPATCH_MACH_MESSAGE_NOT_SENT,
101 	DISPATCH_MACH_BARRIER_COMPLETED,
102 	DISPATCH_MACH_DISCONNECTED,
103 	DISPATCH_MACH_CANCELED,
104 	DISPATCH_MACH_REASON_LAST, /* unused */
105 );
106 
107 /*!
108  * @typedef dispatch_mach_trailer_t
109  * Trailer type of mach message received by dispatch mach channels
110  */
111 
112 typedef mach_msg_context_trailer_t dispatch_mach_trailer_t;
113 
114 /*!
115  * @constant DISPATCH_MACH_RECEIVE_MAX_INLINE_MESSAGE_SIZE
116  * Maximum size of a message that can be received inline by a dispatch mach
117  * channel, reception of larger messages requires an extra roundtrip through
118  * the kernel.
119  */
120 
121 #define DISPATCH_MACH_RECEIVE_MAX_INLINE_MESSAGE_SIZE \
122 		(0x4000 - sizeof(dispatch_mach_trailer_t))
123 
124 /*!
125  * @typedef dispatch_mach_msg_t
126  * A dispatch mach message encapsulates messages received or sent with dispatch
127  * mach channels.
128  */
129 DISPATCH_DECL(dispatch_mach_msg);
130 
131 /*!
132  * @typedef dispatch_mach_msg_destructor_t
133  * Dispatch mach message object destructors.
134  *
135  * @const DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT
136  * Message buffer storage is internal to the object, if a buffer is supplied
137  * during object creation, its contents are copied.
138  *
139  * @const DISPATCH_MACH_MSG_DESTRUCTOR_FREE
140  * Message buffer will be deallocated with free(3).
141  *
142  * @const DISPATCH_MACH_MSG_DESTRUCTOR_FREE
143  * Message buffer will be deallocated with vm_deallocate.
144  */
145 DISPATCH_ENUM(dispatch_mach_msg_destructor, unsigned int,
146 	DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT = 0,
147 	DISPATCH_MACH_MSG_DESTRUCTOR_FREE,
148 	DISPATCH_MACH_MSG_DESTRUCTOR_VM_DEALLOCATE,
149 );
150 
151 /*!
152  * @function dispatch_mach_msg_create
153  * Creates a dispatch mach message object, either with a newly allocated message
154  * buffer of given size, or from an existing message buffer that will be
155  * deallocated with the specified destructor when the object is released.
156  *
157  * If a non-NULL reference to a pointer is provided in 'msg_ptr', it is filled
158  * with the location of the (possibly newly allocated) message buffer.
159  *
160  * It is the responsibility of the application to ensure that it does not modify
161  * the underlying message buffer once the dispatch mach message object is passed
162  * to other dispatch mach API.
163  *
164  * @param msg			The message buffer to create the message object from.
165  *						If 'destructor' is DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT,
166  *						this argument may be NULL to leave the newly allocated
167  *						message buffer zero-initialized.
168  * @param size			The size of the message buffer.
169  *						Must be >= sizeof(mach_msg_header_t)
170  * @param destructor	The destructor to use to deallocate the message buffer
171  *						when the object is released.
172  * @param msg_ptr		A pointer to a pointer variable to be filled with the
173  *						location of the (possibly newly allocated) message
174  *						buffer, or NULL.
175  * @result				A newly created dispatch mach message object.
176  */
177 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0)
178 DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
179 DISPATCH_NOTHROW
180 dispatch_mach_msg_t
181 dispatch_mach_msg_create(mach_msg_header_t *msg, size_t size,
182 		dispatch_mach_msg_destructor_t destructor, mach_msg_header_t **msg_ptr);
183 
184 /*!
185  * @function dispatch_mach_msg_get_msg
186  * Returns the message buffer underlying a dispatch mach message object.
187  *
188  * @param message	The dispatch mach message object to query.
189  * @param size_ptr	A pointer to a size_t variable to be filled with the
190  *					size of the message buffer, or NULL.
191  * @result			Pointer to message buffer underlying the object.
192  */
193 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0)
194 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
195 mach_msg_header_t*
196 dispatch_mach_msg_get_msg(dispatch_mach_msg_t message, size_t *size_ptr);
197 
198 #ifdef __BLOCKS__
199 /*!
200  * @typedef dispatch_mach_handler_t
201  * Prototype of dispatch mach channel handler blocks.
202  *
203  * @param reason	Reason the handler was invoked.
204  * @param message	Message object that was sent or received.
205  * @param error		Mach error code for the send operation.
206  */
207 typedef void (^dispatch_mach_handler_t)(dispatch_mach_reason_t reason,
208 		dispatch_mach_msg_t message, mach_error_t error);
209 
210 /*!
211  * @function dispatch_mach_create
212  * Create a dispatch mach channel to asynchronously receive and send mach
213  * messages.
214  *
215  * The specified handler will be called with the corresponding reason parameter
216  * for each message received and for each message that was successfully sent,
217  * that failed to be sent, or was not sent; as well as when a barrier block
218  * has completed, or when channel connection, reconnection or cancellation has
219  * taken effect.
220  *
221  * Dispatch mach channels are created in a disconnected state, they must be
222  * connected via dispatch_mach_connect() to begin receiving and sending
223  * messages.
224  *
225  * @param label
226  * An optional string label to attach to the channel. The string is not copied,
227  * if it is non-NULL it must point to storage that remains valid for the
228  * lifetime of the channel object. May be NULL.
229  *
230  * @param queue
231  * The target queue of the channel, where the handler and barrier blocks will
232  * be submitted.
233  *
234  * @param handler
235  * The handler block to submit when a message has been sent or received.
236  *
237  * @result
238  * The newly created dispatch mach channel.
239  */
240 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
241 DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
242 DISPATCH_NONNULL3 DISPATCH_NOTHROW
243 dispatch_mach_t
244 dispatch_mach_create(const char *label, dispatch_queue_t queue,
245 		dispatch_mach_handler_t handler);
246 #endif
247 
248 /*!
249  * @typedef dispatch_mach_handler_function_t
250  * Prototype of dispatch mach channel handler functions.
251  *
252  * @param context	Application-defined context parameter.
253  * @param reason	Reason the handler was invoked.
254  * @param message	Message object that was sent or received.
255  * @param error		Mach error code for the send operation.
256  */
257 typedef void (*dispatch_mach_handler_function_t)(void *context,
258 		dispatch_mach_reason_t reason, dispatch_mach_msg_t message,
259 		mach_error_t error);
260 
261 /*!
262  * @function dispatch_mach_create_f
263  * Create a dispatch mach channel to asynchronously receive and send mach
264  * messages.
265  *
266  * The specified handler will be called with the corresponding reason parameter
267  * for each message received and for each message that was successfully sent,
268  * that failed to be sent, or was not sent; as well as when a barrier block
269  * has completed, or when channel connection, reconnection or cancellation has
270  * taken effect.
271  *
272  * Dispatch mach channels are created in a disconnected state, they must be
273  * connected via dispatch_mach_connect() to begin receiving and sending
274  * messages.
275  *
276  * @param label
277  * An optional string label to attach to the channel. The string is not copied,
278  * if it is non-NULL it must point to storage that remains valid for the
279  * lifetime of the channel object. May be NULL.
280  *
281  * @param queue
282  * The target queue of the channel, where the handler and barrier blocks will
283  * be submitted.
284  *
285  * @param context
286  * The application-defined context to pass to the handler.
287  *
288  * @param handler
289  * The handler function to submit when a message has been sent or received.
290  *
291  * @result
292  * The newly created dispatch mach channel.
293  */
294 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
295 DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
296 DISPATCH_NONNULL4 DISPATCH_NOTHROW
297 dispatch_mach_t
298 dispatch_mach_create_f(const char *label, dispatch_queue_t queue, void *context,
299 		dispatch_mach_handler_function_t handler);
300 
301 /*!
302  * @function dispatch_mach_connect
303  * Connect a mach channel to the specified receive and send rights.
304  *
305  * This function must only be called once during the lifetime of a channel, it
306  * will initiate message reception and perform any already submitted message
307  * sends or barrier operations.
308  *
309  * @param channel
310  * The mach channel to connect.
311  *
312  * @param receive
313  * The receive right to associate with the channel. May be MACH_PORT_NULL.
314  *
315  * @param send
316  * The send right to associate with the channel. May be MACH_PORT_NULL.
317  *
318  * @param checkin
319  * An optional message object encapsulating the initial check-in message to send
320  * upon channel connection. The check-in message is sent immediately before the
321  * first message submitted via dispatch_mach_send(). The message object will be
322  * retained until the initial send operation is complete (or not peformed due
323  * to channel cancellation or reconnection) and the channel handler has
324  * returned. May be NULL.
325  */
326 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
327 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
328 void
329 dispatch_mach_connect(dispatch_mach_t channel, mach_port_t receive,
330 		mach_port_t send, dispatch_mach_msg_t checkin);
331 
332 /*!
333  * @function dispatch_mach_reconnect
334  * Reconnect a mach channel to the specified send right.
335  *
336  * Disconnects the channel from the current send right, interrupts any pending
337  * message sends (and returns the messages as unsent), and reconnects the
338  * channel to a new send right.
339  *
340  * The application must wait for the channel handler to be invoked with
341  * DISPATCH_MACH_DISCONNECTED before releasing the previous send right.
342  *
343  * @param channel
344  * The mach channel to reconnect.
345  *
346  * @param send
347  * The new send right to associate with the channel. May be MACH_PORT_NULL.
348  *
349  * @param checkin
350  * An optional message object encapsulating the initial check-in message to send
351  * upon channel reconnection. The check-in message is sent immediately before
352  * the first message submitted via dispatch_mach_send() after this function
353  * returns. The message object will be retained until the initial send operation
354  * is complete (or not peformed due to channel cancellation or reconnection)
355  * and the channel handler has returned. May be NULL.
356  */
357 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
358 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
359 void
360 dispatch_mach_reconnect(dispatch_mach_t channel, mach_port_t send,
361 		dispatch_mach_msg_t checkin);
362 
363 /*!
364  * @function dispatch_mach_cancel
365  * Cancel a mach channel, preventing any further messages from being sent or
366  * received.
367  *
368  * The application must wait for the channel handler to be invoked with
369  * DISPATCH_MACH_DISCONNECTED before releasing the underlying send and receive
370  * rights.
371  *
372  * Note: explicit cancellation of mach channels is required, no implicit
373  *       cancellation takes place on release of the last application reference
374  *       to the channel object. Failure to cancel will cause the channel and
375  *       its associated resources to be leaked.
376  *
377  * @param channel
378  * The mach channel to cancel.
379  */
380 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
381 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
382 void
383 dispatch_mach_cancel(dispatch_mach_t channel);
384 
385 /*!
386  * @function dispatch_mach_send
387  * Asynchronously send a message encapsulated in a dispatch mach message object
388  * to the specified mach channel.
389  *
390  * Unless the message is being sent to a send-once right (as determined by the
391  * presence of MACH_MSG_TYPE_MOVE_SEND_ONCE in the message header remote bits),
392  * the message header remote port is set to the channel send right before the
393  * send operation is performed.
394  *
395  * If the message expects a direct reply (as determined by the presence of
396  * MACH_MSG_TYPE_MAKE_SEND_ONCE in the message header local bits) the receive
397  * right specified in the message header local port will be monitored until a
398  * reply message (or a send-once notification) is received, or the channel is
399  * canceled. Hence the application must wait for the channel handler to be
400  * invoked with a DISPATCH_MACH_DISCONNECTED message before releasing that
401  * receive right.
402  *
403  * If the message send operation is attempted but the channel is canceled
404  * before the send operation succesfully completes, the message returned to the
405  * channel handler with DISPATCH_MACH_MESSAGE_NOT_SENT may be the result of a
406  * pseudo-receive operation. If the message expected a direct reply, the
407  * receive right originally specified in the message header local port will
408  * returned in a DISPATCH_MACH_DISCONNECTED message.
409  *
410  * @param channel
411  * The mach channel to which to send the message.
412  *
413  * @param message
414  * The message object encapsulating the message to send. The object will be
415  * retained until the send operation is complete and the channel handler has
416  * returned. The storage underlying the message object may be modified by the
417  * send operation.
418  *
419  * @param options
420  * Additional send options to pass to mach_msg() when performing the send
421  * operation.
422  */
423 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
424 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NOTHROW
425 void
426 dispatch_mach_send(dispatch_mach_t channel, dispatch_mach_msg_t message,
427 		mach_msg_option_t options);
428 
429 #ifdef __BLOCKS__
430 /*!
431  * @function dispatch_mach_send_barrier
432  * Submit a send barrier to the specified mach channel. Messages submitted to
433  * the channel before the barrier will be sent before the barrier block is
434  * executed, and messages submitted to the channel after the barrier will only
435  * be sent once the barrier block has completed and the channel handler
436  * invocation for the barrier has returned.
437  *
438  * @param channel
439  * The mach channel to which to submit the barrier.
440  *
441  * @param barrier
442  * The barrier block to submit to the channel target queue.
443  */
444 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
445 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
446 void
447 dispatch_mach_send_barrier(dispatch_mach_t channel, dispatch_block_t barrier);
448 #endif
449 
450 /*!
451  * @function dispatch_mach_send_barrier_f
452  * Submit a send barrier to the specified mach channel. Messages submitted to
453  * the channel before the barrier will be sent before the barrier block is
454  * executed, and messages submitted to the channel after the barrier will only
455  * be sent once the barrier block has completed and the channel handler
456  * invocation for the barrier has returned.
457  *
458  * @param channel
459  * The mach channel to which to submit the barrier.
460  *
461  * @param context
462  * The application-defined context parameter to pass to the function.
463  *
464  * @param barrier
465  * The barrier function to submit to the channel target queue.
466  */
467 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
468 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
469 void
470 dispatch_mach_send_barrier_f(dispatch_mach_t channel, void *context,
471 		dispatch_function_t barrier);
472 
473 #ifdef __BLOCKS__
474 /*!
475  * @function dispatch_mach_receive_barrier
476  * Submit a receive barrier to the specified mach channel. Channel handlers for
477  * messages received by the channel after the receive barrier has been
478  * submitted will only be invoked once the barrier block has completed and the
479  * channel handler invocation for the barrier has returned.
480  *
481  * @param channel
482  * The mach channel to which to submit the receive barrier.
483  *
484  * @param barrier
485  * The barrier block to submit to the channel target queue.
486  */
487 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
488 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
489 void
490 dispatch_mach_receive_barrier(dispatch_mach_t channel,
491 		dispatch_block_t barrier);
492 #endif
493 
494 /*!
495  * @function dispatch_mach_receive_barrier_f
496  * Submit a receive barrier to the specified mach channel. Channel handlers for
497  * messages received by the channel after the receive barrier has been
498  * submitted will only be invoked once the barrier block has completed and the
499  * channel handler invocation for the barrier has returned.
500  *
501  * @param channel
502  * The mach channel to which to submit the receive barrier.
503  *
504  * @param context
505  * The application-defined context parameter to pass to the function.
506  *
507  * @param barrier
508  * The barrier function to submit to the channel target queue.
509  */
510 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
511 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
512 void
513 dispatch_mach_receive_barrier_f(dispatch_mach_t channel, void *context,
514 		dispatch_function_t barrier);
515 
516 /*!
517  * @function dispatch_mach_get_checkin_port
518  * Returns the port specified in the message header remote port of the check-in
519  * message passed to the most recent invocation of dispatch_mach_connect() or
520  * dispatch_mach_reconnect() for the provided mach channel (irrespective of the
521  * completion of the (re)connect or check-in operations in question).
522  *
523  * Returns MACH_PORT_NULL if dispatch_mach_connect() has not yet been called or
524  * if the most recently specified check-in message was NULL, and MACH_PORT_DEAD
525  * if the channel has been canceled.
526  *
527  * It is the responsibility of the application to ensure that the port
528  * specified in a check-in message remains valid at the time this function is
529  * called.
530  *
531  * @param channel
532  * The mach channel to query.
533  *
534  * @result
535  * The most recently specified check-in port for the channel.
536  */
537 __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
538 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
539 mach_port_t
540 dispatch_mach_get_checkin_port(dispatch_mach_t channel);
541 
542 #endif // DISPATCH_MACH_SPI
543 
544 __END_DECLS
545 
546 #endif
547