]> git.saurik.com Git - apple/libdispatch.git/blob - src/source_internal.h
libdispatch-500.1.5.tar.gz
[apple/libdispatch.git] / src / source_internal.h
1 /*
2 * Copyright (c) 2008-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_SOURCE_INTERNAL__
28 #define __DISPATCH_SOURCE_INTERNAL__
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 #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)
40
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 !
43
44 /*!
45 * @enum dispatch_source_mach_send_flags_t
46 *
47 * @constant DISPATCH_MACH_SEND_DELETED
48 * Port-deleted notification. Disabled for source registration.
49 */
50 enum {
51 DISPATCH_MACH_SEND_DELETED = 0x4,
52 };
53 /*!
54 * @enum dispatch_source_mach_recv_flags_t
55 *
56 * @constant DISPATCH_MACH_RECV_MESSAGE
57 * Receive right has pending messages
58 *
59 * @constant DISPATCH_MACH_RECV_MESSAGE_DIRECT
60 * Receive messages from receive right directly via kevent64()
61 *
62 * @constant DISPATCH_MACH_RECV_NO_SENDERS
63 * Receive right has no more senders. TODO <rdar://problem/8132399>
64 */
65 enum {
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,
70 };
71
72 enum {
73 DISPATCH_TIMER_WALL_CLOCK = 0x4,
74 DISPATCH_TIMER_INTERVAL = 0x8,
75 DISPATCH_TIMER_WITH_AGGREGATE = 0x10,
76 };
77
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)
84
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)
89
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); })
100
101 struct dispatch_kevent_s {
102 TAILQ_ENTRY(dispatch_kevent_s) dk_list;
103 TAILQ_HEAD(, dispatch_source_refs_s) dk_sources;
104 _dispatch_kevent_qos_s dk_kevent;
105 };
106
107 typedef struct dispatch_kevent_s *dispatch_kevent_t;
108
109 struct dispatch_source_type_s {
110 _dispatch_kevent_qos_s ke;
111 uint64_t mask;
112 void (*init)(dispatch_source_t ds, dispatch_source_type_t type,
113 uintptr_t handle, unsigned long mask, dispatch_queue_t q);
114 };
115
116 struct dispatch_timer_source_s {
117 uint64_t target;
118 uint64_t deadline;
119 uint64_t last_fire;
120 uint64_t interval;
121 uint64_t leeway;
122 unsigned long flags; // dispatch_timer_flags_t
123 unsigned long missed;
124 };
125
126 enum {
127 DS_EVENT_HANDLER = 0,
128 DS_CANCEL_HANDLER,
129 DS_REGISTN_HANDLER,
130 };
131
132 // Source state which may contain references to the source object
133 // Separately allocated so that 'leaks' can see sources <rdar://problem/9050566>
134 typedef struct dispatch_source_refs_s {
135 TAILQ_ENTRY(dispatch_source_refs_s) dr_list;
136 uintptr_t dr_source_wref; // "weak" backref to dispatch_source_t
137 dispatch_continuation_t ds_handler[3];
138 } *dispatch_source_refs_t;
139
140 typedef struct dispatch_timer_source_refs_s {
141 struct dispatch_source_refs_s _ds_refs;
142 struct dispatch_timer_source_s _ds_timer;
143 TAILQ_ENTRY(dispatch_timer_source_refs_s) dt_list;
144 } *dispatch_timer_source_refs_t;
145
146 typedef struct dispatch_timer_source_aggregate_refs_s {
147 struct dispatch_timer_source_refs_s _dsa_refs;
148 TAILQ_ENTRY(dispatch_timer_source_aggregate_refs_s) dra_list;
149 TAILQ_ENTRY(dispatch_timer_source_aggregate_refs_s) dta_list;
150 } *dispatch_timer_source_aggregate_refs_t;
151
152 #define _dispatch_ptr2wref(ptr) (~(uintptr_t)(ptr))
153 #define _dispatch_wref2ptr(ref) ((void*)~(ref))
154 #define _dispatch_source_from_refs(dr) \
155 ((dispatch_source_t)_dispatch_wref2ptr((dr)->dr_source_wref))
156 #define ds_timer(dr) \
157 (((dispatch_timer_source_refs_t)(dr))->_ds_timer)
158 #define ds_timer_aggregate(ds) \
159 ((dispatch_timer_aggregate_t)((ds)->dq_specific_q))
160
161 DISPATCH_ALWAYS_INLINE
162 static inline unsigned int
163 _dispatch_source_timer_idx(dispatch_source_refs_t dr)
164 {
165 return DISPATCH_TIMER_IDENT(ds_timer(dr).flags);
166 }
167
168 // ds_atomic_flags bits
169 #define DSF_CANCELED 1u // cancellation has been requested
170 #define DSF_ARMED 2u // source is armed
171 #define DSF_DELETED 4u // source received EV_DELETE event
172 #define DSF_ONESHOT 8u // source received EV_ONESHOT event
173
174 #define DISPATCH_SOURCE_HEADER(refs) \
175 dispatch_kevent_t ds_dkev; \
176 dispatch_##refs##_refs_t ds_refs; \
177 unsigned int ds_atomic_flags; \
178 unsigned int \
179 ds_is_level:1, \
180 ds_is_adder:1, \
181 ds_is_installed:1, \
182 ds_is_direct_kevent:1, \
183 ds_needs_rearm:1, \
184 ds_pending_delete:1, \
185 ds_needs_mgr:1, \
186 ds_is_timer:1, \
187 ds_vmpressure_override:1, \
188 ds_memorystatus_override:1, \
189 dm_handler_is_block:1, \
190 dm_connect_handler_called:1, \
191 dm_cancel_handler_called:1; \
192 unsigned long ds_pending_data_mask;
193
194 DISPATCH_CLASS_DECL(source);
195 struct dispatch_source_s {
196 DISPATCH_STRUCT_HEADER(source);
197 DISPATCH_QUEUE_HEADER;
198 DISPATCH_SOURCE_HEADER(source);
199 unsigned long ds_ident_hack;
200 unsigned long ds_data;
201 unsigned long ds_pending_data;
202 };
203
204 // Mach channel state which may contain references to the channel object
205 // layout must match dispatch_source_refs_s
206 struct dispatch_mach_refs_s {
207 TAILQ_ENTRY(dispatch_mach_refs_s) dr_list;
208 uintptr_t dr_source_wref; // "weak" backref to dispatch_mach_t
209 dispatch_mach_handler_function_t dm_handler_func;
210 void *dm_handler_ctxt;
211 };
212 typedef struct dispatch_mach_refs_s *dispatch_mach_refs_t;
213
214 struct dispatch_mach_reply_refs_s {
215 TAILQ_ENTRY(dispatch_mach_reply_refs_s) dr_list;
216 uintptr_t dr_source_wref; // "weak" backref to dispatch_mach_t
217 dispatch_kevent_t dmr_dkev;
218 void *dmr_ctxt;
219 pthread_priority_t dmr_priority;
220 voucher_t dmr_voucher;
221 TAILQ_ENTRY(dispatch_mach_reply_refs_s) dmr_list;
222 };
223 typedef struct dispatch_mach_reply_refs_s *dispatch_mach_reply_refs_t;
224
225 struct dispatch_mach_send_refs_s {
226 TAILQ_ENTRY(dispatch_mach_send_refs_s) dr_list;
227 uintptr_t dr_source_wref; // "weak" backref to dispatch_mach_t
228 dispatch_mach_msg_t dm_checkin;
229 TAILQ_HEAD(, dispatch_mach_reply_refs_s) dm_replies;
230 uint32_t volatile dm_disconnect_cnt;
231 uint32_t volatile dm_sending;
232 unsigned int dm_needs_mgr:1;
233 struct dispatch_object_s *volatile dm_tail;
234 struct dispatch_object_s *volatile dm_head;
235 mach_port_t dm_send, dm_checkin_port;
236 };
237 typedef struct dispatch_mach_send_refs_s *dispatch_mach_send_refs_t;
238
239 DISPATCH_CLASS_DECL(mach);
240 struct dispatch_mach_s {
241 DISPATCH_STRUCT_HEADER(mach);
242 DISPATCH_QUEUE_HEADER;
243 DISPATCH_SOURCE_HEADER(mach);
244 dispatch_kevent_t dm_dkev;
245 dispatch_mach_send_refs_t dm_refs;
246 };
247
248 DISPATCH_CLASS_DECL(mach_msg);
249 struct dispatch_mach_msg_s {
250 DISPATCH_STRUCT_HEADER(mach_msg);
251 mach_port_t dmsg_reply;
252 pthread_priority_t dmsg_priority;
253 voucher_t dmsg_voucher;
254 dispatch_mach_msg_destructor_t dmsg_destructor;
255 size_t dmsg_size;
256 union {
257 mach_msg_header_t *dmsg_msg;
258 char dmsg_buf[0];
259 };
260 };
261
262 #if TARGET_OS_EMBEDDED
263 #define DSL_HASH_SIZE 64u // must be a power of two
264 #else
265 #define DSL_HASH_SIZE 256u // must be a power of two
266 #endif
267
268 void _dispatch_source_xref_dispose(dispatch_source_t ds);
269 void _dispatch_source_dispose(dispatch_source_t ds);
270 void _dispatch_source_invoke(dispatch_source_t ds, dispatch_object_t dou,
271 dispatch_invoke_flags_t flags);
272 unsigned long _dispatch_source_probe(dispatch_source_t ds);
273 size_t _dispatch_source_debug(dispatch_source_t ds, char* buf, size_t bufsiz);
274 void _dispatch_source_set_interval(dispatch_source_t ds, uint64_t interval);
275 void _dispatch_source_set_event_handler_with_context_f(dispatch_source_t ds,
276 void *ctxt, dispatch_function_t handler);
277
278 void _dispatch_mach_dispose(dispatch_mach_t dm);
279 void _dispatch_mach_invoke(dispatch_mach_t dm, dispatch_object_t dou,
280 dispatch_invoke_flags_t flags);
281 unsigned long _dispatch_mach_probe(dispatch_mach_t dm);
282 size_t _dispatch_mach_debug(dispatch_mach_t dm, char* buf, size_t bufsiz);
283
284 void _dispatch_mach_msg_dispose(dispatch_mach_msg_t dmsg);
285 void _dispatch_mach_msg_invoke(dispatch_mach_msg_t dmsg, dispatch_object_t dou,
286 dispatch_invoke_flags_t flags);
287 size_t _dispatch_mach_msg_debug(dispatch_mach_msg_t dmsg, char* buf, size_t bufsiz);
288
289 void _dispatch_mach_barrier_invoke(void *ctxt);
290
291 unsigned long _dispatch_mgr_wakeup(dispatch_queue_t dq);
292 void _dispatch_mgr_thread(dispatch_queue_t dq, dispatch_object_t dou,
293 dispatch_invoke_flags_t flags);
294
295 #endif /* __DISPATCH_SOURCE_INTERNAL__ */