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 */
52DISPATCH_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 */
95DISPATCH_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
112typedef 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		((PAGE_SIZE > 0x1000 ? 1 : 3) * PAGE_SIZE - \
123		sizeof(dispatch_mach_trailer_t))
124
125/*!
126 * @typedef dispatch_mach_msg_t
127 * A dispatch mach message encapsulates messages received or sent with dispatch
128 * mach channels.
129 */
130DISPATCH_DECL(dispatch_mach_msg);
131
132/*!
133 * @typedef dispatch_mach_msg_destructor_t
134 * Dispatch mach message object destructors.
135 *
136 * @const DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT
137 * Message buffer storage is internal to the object, if a buffer is supplied
138 * during object creation, its contents are copied.
139 *
140 * @const DISPATCH_MACH_MSG_DESTRUCTOR_FREE
141 * Message buffer will be deallocated with free(3).
142 *
143 * @const DISPATCH_MACH_MSG_DESTRUCTOR_FREE
144 * Message buffer will be deallocated with vm_deallocate.
145 */
146DISPATCH_ENUM(dispatch_mach_msg_destructor, unsigned int,
147	DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT = 0,
148	DISPATCH_MACH_MSG_DESTRUCTOR_FREE,
149	DISPATCH_MACH_MSG_DESTRUCTOR_VM_DEALLOCATE,
150);
151
152/*!
153 * @function dispatch_mach_msg_create
154 * Creates a dispatch mach message object, either with a newly allocated message
155 * buffer of given size, or from an existing message buffer that will be
156 * deallocated with the specified destructor when the object is released.
157 *
158 * If a non-NULL reference to a pointer is provided in 'msg_ptr', it is filled
159 * with the location of the (possibly newly allocated) message buffer.
160 *
161 * It is the responsibility of the application to ensure that it does not modify
162 * the underlying message buffer once the dispatch mach message object is passed
163 * to other dispatch mach API.
164 *
165 * @param msg			The message buffer to create the message object from.
166 *						If 'destructor' is DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT,
167 *						this argument may be NULL to leave the newly allocated
168 *						message buffer zero-initialized.
169 * @param size			The size of the message buffer.
170 *						Must be >= sizeof(mach_msg_header_t)
171 * @param destructor	The destructor to use to deallocate the message buffer
172 *						when the object is released.
173 * @param msg_ptr		A pointer to a pointer variable to be filled with the
174 *						location of the (possibly newly allocated) message
175 *						buffer, or NULL.
176 * @result				A newly created dispatch mach message object.
177 */
178__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0)
179DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
180DISPATCH_NOTHROW
181dispatch_mach_msg_t
182dispatch_mach_msg_create(mach_msg_header_t *msg, size_t size,
183		dispatch_mach_msg_destructor_t destructor, mach_msg_header_t **msg_ptr);
184
185/*!
186 * @function dispatch_mach_msg_get_msg
187 * Returns the message buffer underlying a dispatch mach message object.
188 *
189 * @param message	The dispatch mach message object to query.
190 * @param size_ptr	A pointer to a size_t variable to be filled with the
191 *					size of the message buffer, or NULL.
192 * @result			Pointer to message buffer underlying the object.
193 */
194__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0)
195DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
196mach_msg_header_t*
197dispatch_mach_msg_get_msg(dispatch_mach_msg_t message, size_t *size_ptr);
198
199#ifdef __BLOCKS__
200/*!
201 * @typedef dispatch_mach_handler_t
202 * Prototype of dispatch mach channel handler blocks.
203 *
204 * @param reason	Reason the handler was invoked.
205 * @param message	Message object that was sent or received.
206 * @param error		Mach error code for the send operation.
207 */
208typedef void (^dispatch_mach_handler_t)(dispatch_mach_reason_t reason,
209		dispatch_mach_msg_t message, mach_error_t error);
210
211/*!
212 * @function dispatch_mach_create
213 * Create a dispatch mach channel to asynchronously receive and send mach
214 * messages.
215 *
216 * The specified handler will be called with the corresponding reason parameter
217 * for each message received and for each message that was successfully sent,
218 * that failed to be sent, or was not sent; as well as when a barrier block
219 * has completed, or when channel connection, reconnection or cancellation has
220 * taken effect.
221 *
222 * Dispatch mach channels are created in a disconnected state, they must be
223 * connected via dispatch_mach_connect() to begin receiving and sending
224 * messages.
225 *
226 * @param label
227 * An optional string label to attach to the channel. The string is not copied,
228 * if it is non-NULL it must point to storage that remains valid for the
229 * lifetime of the channel object. May be NULL.
230 *
231 * @param queue
232 * The target queue of the channel, where the handler and barrier blocks will
233 * be submitted.
234 *
235 * @param handler
236 * The handler block to submit when a message has been sent or received.
237 *
238 * @result
239 * The newly created dispatch mach channel.
240 */
241__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
242DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
243DISPATCH_NONNULL3 DISPATCH_NOTHROW
244dispatch_mach_t
245dispatch_mach_create(const char *label, dispatch_queue_t queue,
246		dispatch_mach_handler_t handler);
247#endif
248
249/*!
250 * @typedef dispatch_mach_handler_function_t
251 * Prototype of dispatch mach channel handler functions.
252 *
253 * @param context	Application-defined context parameter.
254 * @param reason	Reason the handler was invoked.
255 * @param message	Message object that was sent or received.
256 * @param error		Mach error code for the send operation.
257 */
258typedef void (*dispatch_mach_handler_function_t)(void *context,
259		dispatch_mach_reason_t reason, dispatch_mach_msg_t message,
260		mach_error_t error);
261
262/*!
263 * @function dispatch_mach_create_f
264 * Create a dispatch mach channel to asynchronously receive and send mach
265 * messages.
266 *
267 * The specified handler will be called with the corresponding reason parameter
268 * for each message received and for each message that was successfully sent,
269 * that failed to be sent, or was not sent; as well as when a barrier block
270 * has completed, or when channel connection, reconnection or cancellation has
271 * taken effect.
272 *
273 * Dispatch mach channels are created in a disconnected state, they must be
274 * connected via dispatch_mach_connect() to begin receiving and sending
275 * messages.
276 *
277 * @param label
278 * An optional string label to attach to the channel. The string is not copied,
279 * if it is non-NULL it must point to storage that remains valid for the
280 * lifetime of the channel object. May be NULL.
281 *
282 * @param queue
283 * The target queue of the channel, where the handler and barrier blocks will
284 * be submitted.
285 *
286 * @param context
287 * The application-defined context to pass to the handler.
288 *
289 * @param handler
290 * The handler function to submit when a message has been sent or received.
291 *
292 * @result
293 * The newly created dispatch mach channel.
294 */
295__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
296DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
297DISPATCH_NONNULL4 DISPATCH_NOTHROW
298dispatch_mach_t
299dispatch_mach_create_f(const char *label, dispatch_queue_t queue, void *context,
300		dispatch_mach_handler_function_t handler);
301
302/*!
303 * @function dispatch_mach_connect
304 * Connect a mach channel to the specified receive and send rights.
305 *
306 * This function must only be called once during the lifetime of a channel, it
307 * will initiate message reception and perform any already submitted message
308 * sends or barrier operations.
309 *
310 * @param channel
311 * The mach channel to connect.
312 *
313 * @param receive
314 * The receive right to associate with the channel. May be MACH_PORT_NULL.
315 *
316 * @param send
317 * The send right to associate with the channel. May be MACH_PORT_NULL.
318 *
319 * @param checkin
320 * An optional message object encapsulating the initial check-in message to send
321 * upon channel connection. The check-in message is sent immediately before the
322 * first message submitted via dispatch_mach_send(). The message object will be
323 * retained until the initial send operation is complete (or not peformed due
324 * to channel cancellation or reconnection) and the channel handler has
325 * returned. May be NULL.
326 */
327__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
328DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
329void
330dispatch_mach_connect(dispatch_mach_t channel, mach_port_t receive,
331		mach_port_t send, dispatch_mach_msg_t checkin);
332
333/*!
334 * @function dispatch_mach_reconnect
335 * Reconnect a mach channel to the specified send right.
336 *
337 * Disconnects the channel from the current send right, interrupts any pending
338 * message sends (and returns the messages as unsent), and reconnects the
339 * channel to a new send right.
340 *
341 * The application must wait for the channel handler to be invoked with
342 * DISPATCH_MACH_DISCONNECTED before releasing the previous send right.
343 *
344 * @param channel
345 * The mach channel to reconnect.
346 *
347 * @param send
348 * The new send right to associate with the channel. May be MACH_PORT_NULL.
349 *
350 * @param checkin
351 * An optional message object encapsulating the initial check-in message to send
352 * upon channel reconnection. The check-in message is sent immediately before
353 * the first message submitted via dispatch_mach_send() after this function
354 * returns. The message object will be retained until the initial send operation
355 * is complete (or not peformed due to channel cancellation or reconnection)
356 * and the channel handler has returned. May be NULL.
357 */
358__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
359DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
360void
361dispatch_mach_reconnect(dispatch_mach_t channel, mach_port_t send,
362		dispatch_mach_msg_t checkin);
363
364/*!
365 * @function dispatch_mach_cancel
366 * Cancel a mach channel, preventing any further messages from being sent or
367 * received.
368 *
369 * The application must wait for the channel handler to be invoked with
370 * DISPATCH_MACH_DISCONNECTED before releasing the underlying send and receive
371 * rights.
372 *
373 * Note: explicit cancellation of mach channels is required, no implicit
374 *       cancellation takes place on release of the last application reference
375 *       to the channel object. Failure to cancel will cause the channel and
376 *       its associated resources to be leaked.
377 *
378 * @param channel
379 * The mach channel to cancel.
380 */
381__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
382DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
383void
384dispatch_mach_cancel(dispatch_mach_t channel);
385
386/*!
387 * @function dispatch_mach_send
388 * Asynchronously send a message encapsulated in a dispatch mach message object
389 * to the specified mach channel.
390 *
391 * Unless the message is being sent to a send-once right (as determined by the
392 * presence of MACH_MSG_TYPE_MOVE_SEND_ONCE in the message header remote bits),
393 * the message header remote port is set to the channel send right before the
394 * send operation is performed.
395 *
396 * If the message expects a direct reply (as determined by the presence of
397 * MACH_MSG_TYPE_MAKE_SEND_ONCE in the message header local bits) the receive
398 * right specified in the message header local port will be monitored until a
399 * reply message (or a send-once notification) is received, or the channel is
400 * canceled. Hence the application must wait for the channel handler to be
401 * invoked with a DISPATCH_MACH_DISCONNECTED message before releasing that
402 * receive right.
403 *
404 * If the message send operation is attempted but the channel is canceled
405 * before the send operation succesfully completes, the message returned to the
406 * channel handler with DISPATCH_MACH_MESSAGE_NOT_SENT may be the result of a
407 * pseudo-receive operation. If the message expected a direct reply, the
408 * receive right originally specified in the message header local port will
409 * returned in a DISPATCH_MACH_DISCONNECTED message.
410 *
411 * @param channel
412 * The mach channel to which to send the message.
413 *
414 * @param message
415 * The message object encapsulating the message to send. The object will be
416 * retained until the send operation is complete and the channel handler has
417 * returned. The storage underlying the message object may be modified by the
418 * send operation.
419 *
420 * @param options
421 * Additional send options to pass to mach_msg() when performing the send
422 * operation.
423 */
424__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
425DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NOTHROW
426void
427dispatch_mach_send(dispatch_mach_t channel, dispatch_mach_msg_t message,
428		mach_msg_option_t options);
429
430#ifdef __BLOCKS__
431/*!
432 * @function dispatch_mach_send_barrier
433 * Submit a send barrier to the specified mach channel. Messages submitted to
434 * the channel before the barrier will be sent before the barrier block is
435 * executed, and messages submitted to the channel after the barrier will only
436 * be sent once the barrier block has completed and the channel handler
437 * invocation for the barrier has returned.
438 *
439 * @param channel
440 * The mach channel to which to submit the barrier.
441 *
442 * @param barrier
443 * The barrier block to submit to the channel target queue.
444 */
445__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
446DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
447void
448dispatch_mach_send_barrier(dispatch_mach_t channel, dispatch_block_t barrier);
449#endif
450
451/*!
452 * @function dispatch_mach_send_barrier_f
453 * Submit a send barrier to the specified mach channel. Messages submitted to
454 * the channel before the barrier will be sent before the barrier block is
455 * executed, and messages submitted to the channel after the barrier will only
456 * be sent once the barrier block has completed and the channel handler
457 * invocation for the barrier has returned.
458 *
459 * @param channel
460 * The mach channel to which to submit the barrier.
461 *
462 * @param context
463 * The application-defined context parameter to pass to the function.
464 *
465 * @param barrier
466 * The barrier function to submit to the channel target queue.
467 */
468__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
469DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
470void
471dispatch_mach_send_barrier_f(dispatch_mach_t channel, void *context,
472		dispatch_function_t barrier);
473
474#ifdef __BLOCKS__
475/*!
476 * @function dispatch_mach_receive_barrier
477 * Submit a receive barrier to the specified mach channel. Channel handlers for
478 * messages received by the channel after the receive barrier has been
479 * submitted will only be invoked once the barrier block has completed and the
480 * channel handler invocation for the barrier has returned.
481 *
482 * @param channel
483 * The mach channel to which to submit the receive barrier.
484 *
485 * @param barrier
486 * The barrier block to submit to the channel target queue.
487 */
488__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
489DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
490void
491dispatch_mach_receive_barrier(dispatch_mach_t channel,
492		dispatch_block_t barrier);
493#endif
494
495/*!
496 * @function dispatch_mach_receive_barrier_f
497 * Submit a receive barrier to the specified mach channel. Channel handlers for
498 * messages received by the channel after the receive barrier has been
499 * submitted will only be invoked once the barrier block has completed and the
500 * channel handler invocation for the barrier has returned.
501 *
502 * @param channel
503 * The mach channel to which to submit the receive barrier.
504 *
505 * @param context
506 * The application-defined context parameter to pass to the function.
507 *
508 * @param barrier
509 * The barrier function to submit to the channel target queue.
510 */
511__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
512DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
513void
514dispatch_mach_receive_barrier_f(dispatch_mach_t channel, void *context,
515		dispatch_function_t barrier);
516
517/*!
518 * @function dispatch_mach_get_checkin_port
519 * Returns the port specified in the message header remote port of the check-in
520 * message passed to the most recent invocation of dispatch_mach_connect() or
521 * dispatch_mach_reconnect() for the provided mach channel (irrespective of the
522 * completion of the (re)connect or check-in operations in question).
523 *
524 * Returns MACH_PORT_NULL if dispatch_mach_connect() has not yet been called or
525 * if the most recently specified check-in message was NULL, and MACH_PORT_DEAD
526 * if the channel has been canceled.
527 *
528 * It is the responsibility of the application to ensure that the port
529 * specified in a check-in message remains valid at the time this function is
530 * called.
531 *
532 * @param channel
533 * The mach channel to query.
534 *
535 * @result
536 * The most recently specified check-in port for the channel.
537 */
538__OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0)
539DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
540mach_port_t
541dispatch_mach_get_checkin_port(dispatch_mach_t channel);
542
543#endif // DISPATCH_MACH_SPI
544
545__END_DECLS
546
547#endif
548