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