2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
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.
27 #ifndef __DISPATCH_SOURCE_INTERNAL__
28 #define __DISPATCH_SOURCE_INTERNAL__
30 #ifndef __DISPATCH_INDIRECT__
31 #error "Please #include <dispatch/dispatch.h> instead of this file directly."
32 #include <dispatch/base.h> // for HeaderDoc
35 #define DISPATCH_EVFILT_TIMER (-EVFILT_SYSCOUNT - 1)
36 #define DISPATCH_EVFILT_CUSTOM_ADD (-EVFILT_SYSCOUNT - 2)
37 #define DISPATCH_EVFILT_CUSTOM_OR (-EVFILT_SYSCOUNT - 3)
38 #define DISPATCH_EVFILT_MACH_NOTIFICATION (-EVFILT_SYSCOUNT - 4)
39 #define DISPATCH_EVFILT_SYSCOUNT ( EVFILT_SYSCOUNT + 4)
42 // NOTE: dispatch_source_mach_send_flags_t and dispatch_source_mach_recv_flags_t
43 // bit values must not overlap as they share the same kevent fflags !
46 * @enum dispatch_source_mach_send_flags_t
48 * @constant DISPATCH_MACH_SEND_DELETED
49 * Port-deleted notification. Disabled for source registration.
52 DISPATCH_MACH_SEND_DELETED
= 0x4,
55 * @enum dispatch_source_mach_recv_flags_t
57 * @constant DISPATCH_MACH_RECV_MESSAGE
58 * Receive right has pending messages
60 * @constant DISPATCH_MACH_RECV_MESSAGE_DIRECT
61 * Receive messages from receive right directly via kevent64()
63 * @constant DISPATCH_MACH_RECV_NO_SENDERS
64 * Receive right has no more senders. TODO <rdar://problem/8132399>
67 DISPATCH_MACH_RECV_MESSAGE
= 0x2,
68 DISPATCH_MACH_RECV_MESSAGE_DIRECT
= 0x10,
69 DISPATCH_MACH_RECV_MESSAGE_DIRECT_ONCE
= 0x20,
70 DISPATCH_MACH_RECV_NO_SENDERS
= 0x40,
75 /* DISPATCH_TIMER_STRICT 0x1 */
76 /* DISPATCH_TIMER_BACKGROUND = 0x2, */
77 DISPATCH_TIMER_WALL_CLOCK
= 0x4,
78 DISPATCH_TIMER_INTERVAL
= 0x8,
79 DISPATCH_TIMER_WITH_AGGREGATE
= 0x10,
80 /* DISPATCH_INTERVAL_UI_ANIMATION = 0x20 */
81 DISPATCH_TIMER_AFTER
= 0x40,
84 #define DISPATCH_TIMER_QOS_NORMAL 0u
85 #define DISPATCH_TIMER_QOS_CRITICAL 1u
86 #define DISPATCH_TIMER_QOS_BACKGROUND 2u
87 #define DISPATCH_TIMER_QOS_COUNT (DISPATCH_TIMER_QOS_BACKGROUND + 1)
88 #define DISPATCH_TIMER_QOS(tidx) (((uintptr_t)(tidx) >> 1) & 0x3ul)
90 #define DISPATCH_TIMER_CLOCK(tidx) ((dispatch_clock_t)((uintptr_t)(tidx) & 1))
92 #define DISPATCH_TIMER_INDEX(clock, qos) ((qos) << 1 | (clock))
93 #define DISPATCH_TIMER_INDEX_DISARM \
94 DISPATCH_TIMER_INDEX(0, DISPATCH_TIMER_QOS_COUNT)
95 #define DISPATCH_TIMER_INDEX_COUNT (DISPATCH_TIMER_INDEX_DISARM + 1)
96 #define DISPATCH_TIMER_IDENT(flags) ({ unsigned long f = (flags); \
97 DISPATCH_TIMER_INDEX(f & DISPATCH_TIMER_WALL_CLOCK ? \
98 DISPATCH_CLOCK_WALL : DISPATCH_CLOCK_MACH, \
99 f & DISPATCH_TIMER_STRICT ? DISPATCH_TIMER_QOS_CRITICAL : \
100 f & DISPATCH_TIMER_BACKGROUND ? DISPATCH_TIMER_QOS_BACKGROUND : \
101 DISPATCH_TIMER_QOS_NORMAL); })
103 struct dispatch_kevent_s
{
104 TAILQ_ENTRY(dispatch_kevent_s
) dk_list
;
105 TAILQ_HEAD(, dispatch_source_refs_s
) dk_sources
;
106 _dispatch_kevent_qos_s dk_kevent
;
109 typedef struct dispatch_kevent_s
*dispatch_kevent_t
;
111 typedef typeof(((dispatch_kevent_t
)NULL
)->dk_kevent
.udata
) _dispatch_kevent_qos_udata_t
;
113 #define DISPATCH_KEV_CUSTOM_ADD ((dispatch_kevent_t)DISPATCH_EVFILT_CUSTOM_ADD)
114 #define DISPATCH_KEV_CUSTOM_OR ((dispatch_kevent_t)DISPATCH_EVFILT_CUSTOM_OR)
116 struct dispatch_source_type_s
{
117 _dispatch_kevent_qos_s ke
;
119 void (*init
)(dispatch_source_t ds
, dispatch_source_type_t type
,
120 uintptr_t handle
, unsigned long mask
);
123 struct dispatch_timer_source_s
{
129 unsigned long flags
; // dispatch_timer_flags_t
130 unsigned long missed
;
134 DS_EVENT_HANDLER
= 0,
139 // Source state which may contain references to the source object
140 // Separately allocated so that 'leaks' can see sources <rdar://problem/9050566>
141 typedef struct dispatch_source_refs_s
{
142 TAILQ_ENTRY(dispatch_source_refs_s
) dr_list
;
143 uintptr_t dr_source_wref
; // "weak" backref to dispatch_source_t
144 dispatch_continuation_t
volatile ds_handler
[3];
145 } *dispatch_source_refs_t
;
147 typedef struct dispatch_timer_source_refs_s
{
148 struct dispatch_source_refs_s _ds_refs
;
149 struct dispatch_timer_source_s _ds_timer
;
150 TAILQ_ENTRY(dispatch_timer_source_refs_s
) dt_list
;
151 } *dispatch_timer_source_refs_t
;
153 typedef struct dispatch_timer_source_aggregate_refs_s
{
154 struct dispatch_timer_source_refs_s _dsa_refs
;
155 TAILQ_ENTRY(dispatch_timer_source_aggregate_refs_s
) dra_list
;
156 TAILQ_ENTRY(dispatch_timer_source_aggregate_refs_s
) dta_list
;
157 } *dispatch_timer_source_aggregate_refs_t
;
159 #define _dispatch_ptr2wref(ptr) (~(uintptr_t)(ptr))
160 #define _dispatch_wref2ptr(ref) ((void*)~(ref))
161 #define _dispatch_source_from_refs(dr) \
162 ((dispatch_source_t)_dispatch_wref2ptr((dr)->dr_source_wref))
163 #define ds_timer(dr) \
164 (((dispatch_timer_source_refs_t)(dr))->_ds_timer)
165 #define ds_timer_aggregate(ds) \
166 ((dispatch_timer_aggregate_t)((ds)->dq_specific_q))
168 DISPATCH_ALWAYS_INLINE
169 static inline unsigned int
170 _dispatch_source_timer_idx(dispatch_source_refs_t dr
)
172 return DISPATCH_TIMER_IDENT(ds_timer(dr
).flags
);
175 #define _DISPATCH_SOURCE_HEADER(refs) \
176 DISPATCH_QUEUE_HEADER(refs); \
177 /* LP64: fills 32bit hole in QUEUE_HEADER */ \
182 ds_is_direct_kevent:1, \
183 ds_is_custom_source:1, \
186 ds_vmpressure_override:1, \
187 ds_memorypressure_override:1, \
188 dm_handler_is_block:1, \
189 dm_connect_handler_called:1, \
190 dm_cancel_handler_called:1; \
191 dispatch_kevent_t ds_dkev; \
192 dispatch_##refs##_refs_t ds_refs; \
193 unsigned long ds_pending_data_mask;
195 #define DISPATCH_SOURCE_HEADER(refs) \
196 struct dispatch_source_s _as_ds[0]; \
197 _DISPATCH_SOURCE_HEADER(refs)
199 DISPATCH_CLASS_DECL_BARE(source
);
200 _OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(dispatch_source
, dispatch_object
);
203 struct dispatch_source_s
{
204 _DISPATCH_SOURCE_HEADER(source
);
205 unsigned long ds_ident_hack
;
206 unsigned long ds_data
;
207 unsigned long ds_pending_data
;
208 } DISPATCH_QUEUE_ALIGN
;
212 // Mach channel state which may contain references to the channel object
213 // layout must match dispatch_source_refs_s
214 struct dispatch_mach_refs_s
{
215 TAILQ_ENTRY(dispatch_mach_refs_s
) dr_list
;
216 uintptr_t dr_source_wref
; // "weak" backref to dispatch_mach_t
217 dispatch_mach_handler_function_t dm_handler_func
;
218 void *dm_handler_ctxt
;
220 typedef struct dispatch_mach_refs_s
*dispatch_mach_refs_t
;
222 struct dispatch_mach_reply_refs_s
{
223 TAILQ_ENTRY(dispatch_mach_reply_refs_s
) dr_list
;
224 uintptr_t dr_source_wref
; // "weak" backref to dispatch_mach_t
225 dispatch_kevent_t dmr_dkev
;
227 mach_port_t dmr_reply
;
228 dispatch_priority_t dmr_priority
;
229 voucher_t dmr_voucher
;
230 TAILQ_ENTRY(dispatch_mach_reply_refs_s
) dmr_list
;
232 typedef struct dispatch_mach_reply_refs_s
*dispatch_mach_reply_refs_t
;
234 #define _DISPATCH_MACH_STATE_UNUSED_MASK_2 0xff00000000000000ull
235 #define DISPATCH_MACH_STATE_OVERRIDE_MASK 0x00ffff0000000000ull
236 #define _DISPATCH_MACH_STATE_UNUSED_MASK_1 0x000000f000000000ull
237 #define DISPATCH_MACH_STATE_DIRTY 0x0000000800000000ull
238 #define DISPATCH_MACH_STATE_RECEIVED_OVERRIDE 0x0000000400000000ull
239 #define _DISPATCH_MACH_STATE_UNUSED_MASK_0 0x0000000200000000ull
240 #define DISPATCH_MACH_STATE_PENDING_BARRIER 0x0000000100000000ull
241 #define DISPATCH_MACH_STATE_UNLOCK_MASK 0x00000000ffffffffull
243 struct dispatch_mach_send_refs_s
{
244 TAILQ_ENTRY(dispatch_mach_send_refs_s
) dr_list
;
245 uintptr_t dr_source_wref
; // "weak" backref to dispatch_mach_t
246 dispatch_mach_msg_t dm_checkin
;
247 TAILQ_HEAD(, dispatch_mach_reply_refs_s
) dm_replies
;
248 dispatch_unfair_lock_s dm_replies_lock
;
249 #define DISPATCH_MACH_DISCONNECT_MAGIC_BASE (0x80000000)
250 #define DISPATCH_MACH_NEVER_INSTALLED (DISPATCH_MACH_DISCONNECT_MAGIC_BASE + 0)
251 #define DISPATCH_MACH_NEVER_CONNECTED (DISPATCH_MACH_DISCONNECT_MAGIC_BASE + 1)
252 uint32_t volatile dm_disconnect_cnt
;
254 uint64_t volatile dm_state
;
255 DISPATCH_STRUCT_LITTLE_ENDIAN_2(
256 dispatch_unfair_lock_s dm_state_lock
,
257 uint32_t dm_state_bits
260 unsigned int dm_needs_mgr
:1;
261 struct dispatch_object_s
*volatile dm_tail
;
262 struct dispatch_object_s
*volatile dm_head
;
263 mach_port_t dm_send
, dm_checkin_port
;
265 typedef struct dispatch_mach_send_refs_s
*dispatch_mach_send_refs_t
;
267 DISPATCH_CLASS_DECL(mach
);
269 struct dispatch_mach_s
{
270 DISPATCH_SOURCE_HEADER(mach
);
271 dispatch_kevent_t dm_dkev
;
272 dispatch_mach_send_refs_t dm_refs
;
273 } DISPATCH_QUEUE_ALIGN
;
276 DISPATCH_CLASS_DECL(mach_msg
);
277 struct dispatch_mach_msg_s
{
278 DISPATCH_OBJECT_HEADER(mach_msg
);
280 mach_msg_option_t dmsg_options
;
281 mach_error_t dmsg_error
;
283 mach_port_t dmsg_reply
;
284 pthread_priority_t dmsg_priority
;
285 voucher_t dmsg_voucher
;
286 dispatch_mach_msg_destructor_t dmsg_destructor
;
289 mach_msg_header_t
*dmsg_msg
;
295 extern const struct dispatch_source_type_s _dispatch_source_type_after
;
297 #if TARGET_OS_EMBEDDED
298 #define DSL_HASH_SIZE 64u // must be a power of two
300 #define DSL_HASH_SIZE 256u // must be a power of two
304 _dispatch_source_create_mach_msg_direct_recv(mach_port_t recvp
,
305 const struct dispatch_continuation_s
*dc
);
306 void _dispatch_source_xref_dispose(dispatch_source_t ds
);
307 void _dispatch_source_dispose(dispatch_source_t ds
);
308 void _dispatch_source_finalize_activation(dispatch_source_t ds
);
309 void _dispatch_source_invoke(dispatch_source_t ds
, dispatch_invoke_flags_t flags
);
310 void _dispatch_source_wakeup(dispatch_source_t ds
, pthread_priority_t pp
,
311 dispatch_wakeup_flags_t flags
);
312 size_t _dispatch_source_debug(dispatch_source_t ds
, char* buf
, size_t bufsiz
);
313 void _dispatch_source_set_interval(dispatch_source_t ds
, uint64_t interval
);
314 void _dispatch_source_set_event_handler_continuation(dispatch_source_t ds
,
315 dispatch_continuation_t dc
);
316 DISPATCH_EXPORT
// for firehose server
317 void _dispatch_source_merge_data(dispatch_source_t ds
, pthread_priority_t pp
,
321 void _dispatch_mach_dispose(dispatch_mach_t dm
);
322 void _dispatch_mach_finalize_activation(dispatch_mach_t dm
);
323 void _dispatch_mach_invoke(dispatch_mach_t dm
, dispatch_invoke_flags_t flags
);
324 void _dispatch_mach_wakeup(dispatch_mach_t dm
, pthread_priority_t pp
,
325 dispatch_wakeup_flags_t flags
);
326 size_t _dispatch_mach_debug(dispatch_mach_t dm
, char* buf
, size_t bufsiz
);
328 void _dispatch_mach_msg_dispose(dispatch_mach_msg_t dmsg
);
329 void _dispatch_mach_msg_invoke(dispatch_mach_msg_t dmsg
,
330 dispatch_invoke_flags_t flags
);
331 size_t _dispatch_mach_msg_debug(dispatch_mach_msg_t dmsg
, char* buf
,
334 void _dispatch_mach_send_barrier_drain_invoke(dispatch_continuation_t dc
,
335 dispatch_invoke_flags_t flags
);
336 void _dispatch_mach_barrier_invoke(dispatch_continuation_t dc
,
337 dispatch_invoke_flags_t flags
);
340 void _dispatch_mgr_queue_wakeup(dispatch_queue_t dq
, pthread_priority_t pp
,
341 dispatch_wakeup_flags_t flags
);
342 void _dispatch_mgr_thread(dispatch_queue_t dq
, dispatch_invoke_flags_t flags
);
343 #if DISPATCH_USE_KEVENT_WORKQUEUE
344 void _dispatch_kevent_worker_thread(_dispatch_kevent_qos_s
**events
,
348 #endif /* __DISPATCH_SOURCE_INTERNAL__ */