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)
41 // NOTE: dispatch_source_mach_send_flags_t and dispatch_source_mach_recv_flags_t
42 // bit values must not overlap as they share the same kevent fflags !
45 * @enum dispatch_source_mach_send_flags_t
47 * @constant DISPATCH_MACH_SEND_DELETED
48 * Port-deleted notification. Disabled for source registration.
51 DISPATCH_MACH_SEND_DELETED
= 0x4,
54 * @enum dispatch_source_mach_recv_flags_t
56 * @constant DISPATCH_MACH_RECV_MESSAGE
57 * Receive right has pending messages
59 * @constant DISPATCH_MACH_RECV_MESSAGE_DIRECT
60 * Receive messages from receive right directly via kevent64()
62 * @constant DISPATCH_MACH_RECV_NO_SENDERS
63 * Receive right has no more senders. TODO <rdar://problem/8132399>
66 DISPATCH_MACH_RECV_MESSAGE
= 0x2,
67 DISPATCH_MACH_RECV_MESSAGE_DIRECT
= 0x10,
68 DISPATCH_MACH_RECV_MESSAGE_DIRECT_ONCE
= 0x20,
69 DISPATCH_MACH_RECV_NO_SENDERS
= 0x40,
73 DISPATCH_TIMER_WALL_CLOCK
= 0x4,
74 DISPATCH_TIMER_INTERVAL
= 0x8,
75 DISPATCH_TIMER_WITH_AGGREGATE
= 0x10,
78 // low bits are timer QoS class
79 #define DISPATCH_TIMER_QOS_NORMAL 0u
80 #define DISPATCH_TIMER_QOS_CRITICAL 1u
81 #define DISPATCH_TIMER_QOS_BACKGROUND 2u
82 #define DISPATCH_TIMER_QOS_COUNT (DISPATCH_TIMER_QOS_BACKGROUND + 1)
83 #define DISPATCH_TIMER_QOS(tidx) ((uintptr_t)(tidx) & 0x3ul)
85 #define DISPATCH_TIMER_KIND_WALL 0u
86 #define DISPATCH_TIMER_KIND_MACH 1u
87 #define DISPATCH_TIMER_KIND_COUNT (DISPATCH_TIMER_KIND_MACH + 1)
88 #define DISPATCH_TIMER_KIND(tidx) (((uintptr_t)(tidx) >> 2) & 0x1ul)
90 #define DISPATCH_TIMER_INDEX(kind, qos) (((kind) << 2) | (qos))
91 #define DISPATCH_TIMER_INDEX_DISARM \
92 DISPATCH_TIMER_INDEX(DISPATCH_TIMER_KIND_COUNT, 0)
93 #define DISPATCH_TIMER_INDEX_COUNT (DISPATCH_TIMER_INDEX_DISARM + 1)
94 #define DISPATCH_TIMER_IDENT(flags) ({ unsigned long f = (flags); \
95 DISPATCH_TIMER_INDEX(f & DISPATCH_TIMER_WALL_CLOCK ? \
96 DISPATCH_TIMER_KIND_WALL : DISPATCH_TIMER_KIND_MACH, \
97 f & DISPATCH_TIMER_STRICT ? DISPATCH_TIMER_QOS_CRITICAL : \
98 f & DISPATCH_TIMER_BACKGROUND ? DISPATCH_TIMER_QOS_BACKGROUND : \
99 DISPATCH_TIMER_QOS_NORMAL); })
101 struct dispatch_kevent_s
{
102 TAILQ_ENTRY(dispatch_kevent_s
) dk_list
;
103 TAILQ_HEAD(, dispatch_source_refs_s
) dk_sources
;
104 struct kevent64_s dk_kevent
;
107 typedef struct dispatch_kevent_s
*dispatch_kevent_t
;
109 struct dispatch_source_type_s
{
110 struct kevent64_s ke
;
112 void (*init
)(dispatch_source_t ds
, dispatch_source_type_t type
,
113 uintptr_t handle
, unsigned long mask
, dispatch_queue_t q
);
116 struct dispatch_timer_source_s
{
122 unsigned long flags
; // dispatch_timer_flags_t
123 unsigned long missed
;
126 // Source state which may contain references to the source object
127 // Separately allocated so that 'leaks' can see sources <rdar://problem/9050566>
128 typedef struct dispatch_source_refs_s
{
129 TAILQ_ENTRY(dispatch_source_refs_s
) dr_list
;
130 uintptr_t dr_source_wref
; // "weak" backref to dispatch_source_t
131 dispatch_function_t ds_handler_func
;
132 void *ds_handler_ctxt
;
133 void *ds_cancel_handler
;
134 void *ds_registration_handler
;
135 } *dispatch_source_refs_t
;
137 typedef struct dispatch_timer_source_refs_s
{
138 struct dispatch_source_refs_s _ds_refs
;
139 struct dispatch_timer_source_s _ds_timer
;
140 TAILQ_ENTRY(dispatch_timer_source_refs_s
) dt_list
;
141 } *dispatch_timer_source_refs_t
;
143 typedef struct dispatch_timer_source_aggregate_refs_s
{
144 struct dispatch_timer_source_refs_s _dsa_refs
;
145 TAILQ_ENTRY(dispatch_timer_source_aggregate_refs_s
) dra_list
;
146 TAILQ_ENTRY(dispatch_timer_source_aggregate_refs_s
) dta_list
;
147 } *dispatch_timer_source_aggregate_refs_t
;
149 #define _dispatch_ptr2wref(ptr) (~(uintptr_t)(ptr))
150 #define _dispatch_wref2ptr(ref) ((void*)~(ref))
151 #define _dispatch_source_from_refs(dr) \
152 ((dispatch_source_t)_dispatch_wref2ptr((dr)->dr_source_wref))
153 #define ds_timer(dr) \
154 (((dispatch_timer_source_refs_t)(dr))->_ds_timer)
155 #define ds_timer_aggregate(ds) \
156 ((dispatch_timer_aggregate_t)((ds)->dq_specific_q))
158 DISPATCH_ALWAYS_INLINE
159 static inline unsigned int
160 _dispatch_source_timer_idx(dispatch_source_refs_t dr
)
162 return DISPATCH_TIMER_IDENT(ds_timer(dr
).flags
);
165 // ds_atomic_flags bits
166 #define DSF_CANCELED 1u // cancellation has been requested
167 #define DSF_ARMED 2u // source is armed
169 #define DISPATCH_SOURCE_HEADER(refs) \
170 dispatch_kevent_t ds_dkev; \
171 dispatch_##refs##_refs_t ds_refs; \
172 unsigned int ds_atomic_flags; \
179 ds_cancel_is_block:1, \
180 ds_handler_is_block:1, \
181 ds_registration_is_block:1, \
182 dm_connect_handler_called:1, \
183 dm_cancel_handler_called:1; \
184 unsigned long ds_pending_data_mask;
186 DISPATCH_CLASS_DECL(source
);
187 struct dispatch_source_s
{
188 DISPATCH_STRUCT_HEADER(source
);
189 DISPATCH_QUEUE_HEADER
;
190 DISPATCH_SOURCE_HEADER(source
);
191 unsigned long ds_ident_hack
;
192 unsigned long ds_data
;
193 unsigned long ds_pending_data
;
196 // Mach channel state which may contain references to the channel object
197 // layout must match dispatch_source_refs_s
198 struct dispatch_mach_refs_s
{
199 TAILQ_ENTRY(dispatch_mach_refs_s
) dr_list
;
200 uintptr_t dr_source_wref
; // "weak" backref to dispatch_mach_t
201 dispatch_mach_handler_function_t dm_handler_func
;
202 void *dm_handler_ctxt
;
204 typedef struct dispatch_mach_refs_s
*dispatch_mach_refs_t
;
206 struct dispatch_mach_reply_refs_s
{
207 TAILQ_ENTRY(dispatch_mach_reply_refs_s
) dr_list
;
208 uintptr_t dr_source_wref
; // "weak" backref to dispatch_mach_t
209 dispatch_kevent_t dm_dkev
;
210 TAILQ_ENTRY(dispatch_mach_reply_refs_s
) dm_list
;
212 typedef struct dispatch_mach_reply_refs_s
*dispatch_mach_reply_refs_t
;
214 struct dispatch_mach_send_refs_s
{
215 TAILQ_ENTRY(dispatch_mach_send_refs_s
) dr_list
;
216 uintptr_t dr_source_wref
; // "weak" backref to dispatch_mach_t
217 dispatch_mach_msg_t dm_checkin
;
218 TAILQ_HEAD(, dispatch_mach_reply_refs_s
) dm_replies
;
219 uint32_t volatile dm_disconnect_cnt
;
220 uint32_t volatile dm_sending
;
221 unsigned int dm_needs_mgr
:1;
222 struct dispatch_object_s
*volatile dm_tail
;
223 struct dispatch_object_s
*volatile dm_head
;
224 mach_port_t dm_send
, dm_checkin_port
;
226 typedef struct dispatch_mach_send_refs_s
*dispatch_mach_send_refs_t
;
228 DISPATCH_CLASS_DECL(mach
);
229 struct dispatch_mach_s
{
230 DISPATCH_STRUCT_HEADER(mach
);
231 DISPATCH_QUEUE_HEADER
;
232 DISPATCH_SOURCE_HEADER(mach
);
233 dispatch_kevent_t dm_dkev
;
234 dispatch_mach_send_refs_t dm_refs
;
237 DISPATCH_CLASS_DECL(mach_msg
);
238 struct dispatch_mach_msg_s
{
239 DISPATCH_STRUCT_HEADER(mach_msg
);
240 dispatch_mach_msg_destructor_t destructor
;
243 mach_msg_header_t
*msg
;
248 #if TARGET_OS_EMBEDDED
249 #define DSL_HASH_SIZE 64u // must be a power of two
251 #define DSL_HASH_SIZE 256u // must be a power of two
254 void _dispatch_source_xref_dispose(dispatch_source_t ds
);
255 void _dispatch_source_dispose(dispatch_source_t ds
);
256 void _dispatch_source_invoke(dispatch_source_t ds
);
257 unsigned long _dispatch_source_probe(dispatch_source_t ds
);
258 size_t _dispatch_source_debug(dispatch_source_t ds
, char* buf
, size_t bufsiz
);
259 void _dispatch_source_set_interval(dispatch_source_t ds
, uint64_t interval
);
261 void _dispatch_mach_dispose(dispatch_mach_t dm
);
262 void _dispatch_mach_invoke(dispatch_mach_t dm
);
263 unsigned long _dispatch_mach_probe(dispatch_mach_t dm
);
264 size_t _dispatch_mach_debug(dispatch_mach_t dm
, char* buf
, size_t bufsiz
);
266 void _dispatch_mach_msg_dispose(dispatch_mach_msg_t dmsg
);
267 void _dispatch_mach_msg_invoke(dispatch_mach_msg_t dmsg
);
268 size_t _dispatch_mach_msg_debug(dispatch_mach_msg_t dmsg
, char* buf
, size_t bufsiz
);
270 void _dispatch_mach_barrier_invoke(void *ctxt
);
272 unsigned long _dispatch_mgr_wakeup(dispatch_queue_t dq
);
273 void _dispatch_mgr_thread(dispatch_queue_t dq
);
275 #endif /* __DISPATCH_SOURCE_INTERNAL__ */