]> git.saurik.com Git - apple/libdispatch.git/blob - src/internal.h
libdispatch-187.9.tar.gz
[apple/libdispatch.git] / src / internal.h
1 /*
2 * Copyright (c) 2008-2011 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_INTERNAL__
28 #define __DISPATCH_INTERNAL__
29
30 #include <config/config.h>
31
32 #define __DISPATCH_BUILDING_DISPATCH__
33 #define __DISPATCH_INDIRECT__
34
35
36 #include <dispatch/dispatch.h>
37 #include <dispatch/base.h>
38
39
40 #include <dispatch/time.h>
41 #include <dispatch/queue.h>
42 #include <dispatch/object.h>
43 #include <dispatch/source.h>
44 #include <dispatch/group.h>
45 #include <dispatch/semaphore.h>
46 #include <dispatch/once.h>
47 #include <dispatch/data.h>
48 #include <dispatch/io.h>
49
50 /* private.h uses #include_next and must be included last to avoid picking
51 * up installed headers. */
52 #include "queue_private.h"
53 #include "source_private.h"
54 #include "benchmark.h"
55 #include "private.h"
56
57 /* More #includes at EOF (dependent on the contents of internal.h) ... */
58
59 /* The "_debug" library build */
60 #ifndef DISPATCH_DEBUG
61 #define DISPATCH_DEBUG 0
62 #endif
63
64 #ifndef DISPATCH_PROFILE
65 #define DISPATCH_PROFILE 0
66 #endif
67
68 #if DISPATCH_DEBUG && !defined(DISPATCH_USE_CLIENT_CALLOUT)
69 #define DISPATCH_USE_CLIENT_CALLOUT 1
70 #endif
71
72 #if (DISPATCH_DEBUG || DISPATCH_PROFILE) && !defined(DISPATCH_USE_DTRACE)
73 #define DISPATCH_USE_DTRACE 1
74 #endif
75
76 #if HAVE_LIBKERN_OSCROSSENDIAN_H
77 #include <libkern/OSCrossEndian.h>
78 #endif
79 #if HAVE_LIBKERN_OSATOMIC_H
80 #include <libkern/OSAtomic.h>
81 #endif
82 #if HAVE_MACH
83 #include <mach/boolean.h>
84 #include <mach/clock_types.h>
85 #include <mach/clock.h>
86 #include <mach/exception.h>
87 #include <mach/mach.h>
88 #include <mach/mach_error.h>
89 #include <mach/mach_host.h>
90 #include <mach/mach_interface.h>
91 #include <mach/mach_time.h>
92 #include <mach/mach_traps.h>
93 #include <mach/message.h>
94 #include <mach/mig_errors.h>
95 #include <mach/host_info.h>
96 #include <mach/notify.h>
97 #endif /* HAVE_MACH */
98 #if HAVE_MALLOC_MALLOC_H
99 #include <malloc/malloc.h>
100 #endif
101 #include <sys/event.h>
102 #include <sys/mount.h>
103 #include <sys/queue.h>
104 #include <sys/stat.h>
105 #include <sys/sysctl.h>
106 #include <sys/socket.h>
107 #include <sys/time.h>
108 #include <netinet/in.h>
109
110 #ifdef __BLOCKS__
111 #include <Block_private.h>
112 #include <Block.h>
113 #endif /* __BLOCKS__ */
114
115 #include <assert.h>
116 #include <errno.h>
117 #include <fcntl.h>
118 #include <limits.h>
119 #include <search.h>
120 #if USE_POSIX_SEM
121 #include <semaphore.h>
122 #endif
123 #include <signal.h>
124 #include <stdarg.h>
125 #include <stdbool.h>
126 #include <stdint.h>
127 #include <stdio.h>
128 #include <stdlib.h>
129 #include <string.h>
130 #include <syslog.h>
131 #if HAVE_UNISTD_H
132 #include <unistd.h>
133 #endif
134
135 #ifndef __has_builtin
136 #define __has_builtin(x) 0
137 #endif
138 #ifndef __has_include
139 #define __has_include(x) 0
140 #endif
141 #ifndef __has_feature
142 #define __has_feature(x) 0
143 #endif
144 #ifndef __has_attribute
145 #define __has_attribute(x) 0
146 #endif
147
148 #define DISPATCH_NOINLINE __attribute__((__noinline__))
149 #define DISPATCH_USED __attribute__((__used__))
150 #define DISPATCH_UNUSED __attribute__((__unused__))
151 #define DISPATCH_WEAK __attribute__((__weak__))
152 #if DISPATCH_DEBUG
153 #define DISPATCH_ALWAYS_INLINE_NDEBUG
154 #else
155 #define DISPATCH_ALWAYS_INLINE_NDEBUG __attribute__((__always_inline__))
156 #endif
157
158 // workaround 6368156
159 #ifdef NSEC_PER_SEC
160 #undef NSEC_PER_SEC
161 #endif
162 #ifdef USEC_PER_SEC
163 #undef USEC_PER_SEC
164 #endif
165 #ifdef NSEC_PER_USEC
166 #undef NSEC_PER_USEC
167 #endif
168 #define NSEC_PER_SEC 1000000000ull
169 #define USEC_PER_SEC 1000000ull
170 #define NSEC_PER_USEC 1000ull
171
172 /* I wish we had __builtin_expect_range() */
173 #define fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
174 #define slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
175
176 DISPATCH_NOINLINE
177 void _dispatch_bug(size_t line, long val);
178 DISPATCH_NOINLINE
179 void _dispatch_bug_mach_client(const char *msg, mach_msg_return_t kr);
180 DISPATCH_NOINLINE DISPATCH_NORETURN
181 void _dispatch_abort(size_t line, long val);
182 DISPATCH_NOINLINE __attribute__((__format__(printf,1,2)))
183 void _dispatch_log(const char *msg, ...);
184 DISPATCH_NOINLINE __attribute__((__format__(printf,1,0)))
185 void _dispatch_logv(const char *msg, va_list);
186
187 /*
188 * For reporting bugs within libdispatch when using the "_debug" version of the
189 * library.
190 */
191 #define dispatch_assert(e) do { \
192 if (__builtin_constant_p(e)) { \
193 char __compile_time_assert__[(bool)(e) ? 1 : -1] DISPATCH_UNUSED; \
194 } else { \
195 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
196 if (DISPATCH_DEBUG && !_e) { \
197 _dispatch_abort(__LINE__, (long)_e); \
198 } \
199 } \
200 } while (0)
201 /*
202 * A lot of API return zero upon success and not-zero on fail. Let's capture
203 * and log the non-zero value
204 */
205 #define dispatch_assert_zero(e) do { \
206 if (__builtin_constant_p(e)) { \
207 char __compile_time_assert__[(bool)(e) ? -1 : 1] DISPATCH_UNUSED; \
208 } else { \
209 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
210 if (DISPATCH_DEBUG && _e) { \
211 _dispatch_abort(__LINE__, (long)_e); \
212 } \
213 } \
214 } while (0)
215
216 /*
217 * For reporting bugs or impedance mismatches between libdispatch and external
218 * subsystems. These do NOT abort(), and are always compiled into the product.
219 *
220 * In particular, we wrap all system-calls with assume() macros.
221 */
222 #define dispatch_assume(e) ({ \
223 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
224 if (!_e) { \
225 if (__builtin_constant_p(e)) { \
226 char __compile_time_assert__[(bool)(e) ? 1 : -1]; \
227 (void)__compile_time_assert__; \
228 } \
229 _dispatch_bug(__LINE__, (long)_e); \
230 } \
231 _e; \
232 })
233 /*
234 * A lot of API return zero upon success and not-zero on fail. Let's capture
235 * and log the non-zero value
236 */
237 #define dispatch_assume_zero(e) ({ \
238 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
239 if (_e) { \
240 if (__builtin_constant_p(e)) { \
241 char __compile_time_assert__[(bool)(e) ? -1 : 1]; \
242 (void)__compile_time_assert__; \
243 } \
244 _dispatch_bug(__LINE__, (long)_e); \
245 } \
246 _e; \
247 })
248
249 /*
250 * For reporting bugs in clients when using the "_debug" version of the library.
251 */
252 #define dispatch_debug_assert(e, msg, args...) do { \
253 if (__builtin_constant_p(e)) { \
254 char __compile_time_assert__[(bool)(e) ? 1 : -1] DISPATCH_UNUSED; \
255 } else { \
256 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
257 if (DISPATCH_DEBUG && !_e) { \
258 _dispatch_log("%s() 0x%lx: " msg, __func__, (long)_e, ##args); \
259 abort(); \
260 } \
261 } \
262 } while (0)
263
264 /* Make sure the debug statments don't get too stale */
265 #define _dispatch_debug(x, args...) \
266 ({ \
267 if (DISPATCH_DEBUG) { \
268 _dispatch_log("libdispatch: %u\t%p\t" x, __LINE__, \
269 (void *)_dispatch_thread_self(), ##args); \
270 } \
271 })
272
273 #if DISPATCH_DEBUG
274 #if HAVE_MACH
275 DISPATCH_NOINLINE DISPATCH_USED
276 void dispatch_debug_machport(mach_port_t name, const char* str);
277 #endif
278 DISPATCH_NOINLINE DISPATCH_USED
279 void dispatch_debug_kevents(struct kevent* kev, size_t count, const char* str);
280 #else
281 static inline void
282 dispatch_debug_kevents(struct kevent* kev DISPATCH_UNUSED,
283 size_t count DISPATCH_UNUSED,
284 const char* str DISPATCH_UNUSED) {}
285 #endif
286
287 #if DISPATCH_USE_CLIENT_CALLOUT
288
289 DISPATCH_NOTHROW void
290 _dispatch_client_callout(void *ctxt, dispatch_function_t f);
291 DISPATCH_NOTHROW void
292 _dispatch_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t));
293
294 #else
295
296 DISPATCH_ALWAYS_INLINE
297 static inline void
298 _dispatch_client_callout(void *ctxt, dispatch_function_t f)
299 {
300 return f(ctxt);
301 }
302
303 DISPATCH_ALWAYS_INLINE
304 static inline void
305 _dispatch_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t))
306 {
307 return f(ctxt, i);
308 }
309
310 #endif
311
312 #ifdef __BLOCKS__
313 DISPATCH_ALWAYS_INLINE
314 static inline void
315 _dispatch_client_callout_block(dispatch_block_t b)
316 {
317 struct Block_basic *bb = (void*)b;
318 return _dispatch_client_callout(b, (dispatch_function_t)bb->Block_invoke);
319 }
320
321 dispatch_block_t _dispatch_Block_copy(dispatch_block_t block);
322 #define _dispatch_Block_copy(x) ((typeof(x))_dispatch_Block_copy(x))
323 void _dispatch_call_block_and_release(void *block);
324 #endif /* __BLOCKS__ */
325
326 void dummy_function(void);
327 long dummy_function_r0(void);
328
329 void _dispatch_source_drain_kevent(struct kevent *);
330
331 long _dispatch_update_kq(const struct kevent *);
332 void _dispatch_run_timers(void);
333 // Returns howsoon with updated time value, or NULL if no timers active.
334 struct timespec *_dispatch_get_next_timer_fire(struct timespec *howsoon);
335
336 bool _dispatch_source_testcancel(dispatch_source_t);
337
338 uint64_t _dispatch_timeout(dispatch_time_t when);
339
340 extern bool _dispatch_safe_fork;
341
342 extern struct _dispatch_hw_config_s {
343 uint32_t cc_max_active;
344 uint32_t cc_max_logical;
345 uint32_t cc_max_physical;
346 } _dispatch_hw_config;
347
348 /* #includes dependent on internal.h */
349 #include "shims.h"
350 #include "object_internal.h"
351 #include "queue_internal.h"
352 #include "semaphore_internal.h"
353 #include "source_internal.h"
354 #include "data_internal.h"
355 #include "io_internal.h"
356 #include "trace.h"
357
358 // SnowLeopard and iOS Simulator fallbacks
359
360 #if HAVE_PTHREAD_WORKQUEUES
361 #if !defined(WORKQ_BG_PRIOQUEUE) || \
362 (TARGET_IPHONE_SIMULATOR && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
363 #undef WORKQ_BG_PRIOQUEUE
364 #define WORKQ_BG_PRIOQUEUE WORKQ_LOW_PRIOQUEUE
365 #endif
366 #endif // HAVE_PTHREAD_WORKQUEUES
367
368 #if HAVE_MACH
369 #if !defined(MACH_NOTIFY_SEND_POSSIBLE) || \
370 (TARGET_IPHONE_SIMULATOR && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
371 #undef MACH_NOTIFY_SEND_POSSIBLE
372 #define MACH_NOTIFY_SEND_POSSIBLE MACH_NOTIFY_DEAD_NAME
373 #endif
374 #endif // HAVE_MACH
375
376 #ifdef EVFILT_VM
377 #if TARGET_IPHONE_SIMULATOR && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
378 #undef DISPATCH_USE_MALLOC_VM_PRESSURE_SOURCE
379 #define DISPATCH_USE_MALLOC_VM_PRESSURE_SOURCE 0
380 #endif
381 #ifndef DISPATCH_USE_VM_PRESSURE
382 #define DISPATCH_USE_VM_PRESSURE 1
383 #endif
384 #ifndef DISPATCH_USE_MALLOC_VM_PRESSURE_SOURCE
385 #define DISPATCH_USE_MALLOC_VM_PRESSURE_SOURCE 1
386 #endif
387 #endif // EVFILT_VM
388
389 #if defined(F_SETNOSIGPIPE) && defined(F_GETNOSIGPIPE)
390 #if TARGET_IPHONE_SIMULATOR && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
391 #undef DISPATCH_USE_SETNOSIGPIPE
392 #define DISPATCH_USE_SETNOSIGPIPE 0
393 #endif
394 #ifndef DISPATCH_USE_SETNOSIGPIPE
395 #define DISPATCH_USE_SETNOSIGPIPE 1
396 #endif
397 #endif // F_SETNOSIGPIPE
398
399
400 #define _dispatch_set_crash_log_message(x)
401
402 #if HAVE_MACH
403 // MIG_REPLY_MISMATCH means either:
404 // 1) A signal handler is NOT using async-safe API. See the sigaction(2) man
405 // page for more info.
406 // 2) A hand crafted call to mach_msg*() screwed up. Use MIG.
407 #define DISPATCH_VERIFY_MIG(x) do { \
408 if ((x) == MIG_REPLY_MISMATCH) { \
409 _dispatch_set_crash_log_message("MIG_REPLY_MISMATCH"); \
410 _dispatch_hardware_crash(); \
411 } \
412 } while (0)
413 #endif
414
415 #define DISPATCH_CRASH(x) do { \
416 _dispatch_set_crash_log_message("BUG IN LIBDISPATCH: " x); \
417 _dispatch_hardware_crash(); \
418 } while (0)
419
420 #define DISPATCH_CLIENT_CRASH(x) do { \
421 _dispatch_set_crash_log_message("BUG IN CLIENT OF LIBDISPATCH: " x); \
422 _dispatch_hardware_crash(); \
423 } while (0)
424
425 #endif /* __DISPATCH_INTERNAL__ */