]> git.saurik.com Git - apple/libdispatch.git/blob - src/internal.h
libdispatch-501.20.1.tar.gz
[apple/libdispatch.git] / src / 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_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 !defined(DISPATCH_MACH_SPI) && TARGET_OS_MAC
42 #define DISPATCH_MACH_SPI 1
43 #endif
44 #if !defined(OS_VOUCHER_CREATION_SPI) && TARGET_OS_MAC
45 #define OS_VOUCHER_CREATION_SPI 1
46 #endif
47 #if !defined(OS_VOUCHER_ACTIVITY_SPI) && TARGET_OS_MAC
48 #define OS_VOUCHER_ACTIVITY_SPI 1
49 #endif
50 #if !defined(OS_VOUCHER_ACTIVITY_BUFFER_SPI) && TARGET_OS_MAC && \
51 __has_include(<atm/atm_types.h>)
52 #define OS_VOUCHER_ACTIVITY_BUFFER_SPI 1
53 #endif
54 #if !defined(DISPATCH_LAYOUT_SPI) && TARGET_OS_MAC
55 #define DISPATCH_LAYOUT_SPI 1
56 #endif
57
58 #if !defined(USE_OBJC) && HAVE_OBJC
59 #define USE_OBJC 1
60 #endif
61
62 #if USE_OBJC && ((!TARGET_IPHONE_SIMULATOR && defined(__i386__)) || \
63 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 1080))
64 // Disable Objective-C support on platforms with legacy objc runtime
65 #undef USE_OBJC
66 #define USE_OBJC 0
67 #endif
68
69 #if USE_OBJC
70 #define OS_OBJECT_HAVE_OBJC_SUPPORT 1
71 #if __OBJC__
72 #define OS_OBJECT_USE_OBJC 1
73 #else
74 #define OS_OBJECT_USE_OBJC 0
75 #endif // __OBJC__
76 #else
77 #define OS_OBJECT_HAVE_OBJC_SUPPORT 0
78 #endif // USE_OBJC
79
80 #include <dispatch/dispatch.h>
81 #include <dispatch/base.h>
82
83
84 #include <os/object.h>
85 #include <dispatch/time.h>
86 #include <dispatch/object.h>
87 #include <dispatch/queue.h>
88 #include <dispatch/block.h>
89 #include <dispatch/source.h>
90 #include <dispatch/group.h>
91 #include <dispatch/semaphore.h>
92 #include <dispatch/once.h>
93 #include <dispatch/data.h>
94 #if !TARGET_OS_WIN32
95 #include <dispatch/io.h>
96 #endif
97
98 #define DISPATCH_STRUCT_DECL(type, name, ...) \
99 struct type __VA_ARGS__ name
100
101 // Visual Studio C++ does not support C99 designated initializers.
102 // This means that static declarations should be zero initialized and cannot
103 // be const since we must fill in the values during DLL initialization.
104 #if !TARGET_OS_WIN32
105 #define DISPATCH_STRUCT_INSTANCE(type, name, ...) \
106 struct type name = { \
107 __VA_ARGS__ \
108 }
109 #else
110 #define DISPATCH_STRUCT_INSTANCE(type, name, ...) \
111 struct type name = { 0 }
112 #endif
113
114 #if !TARGET_OS_WIN32
115 #define DISPATCH_CONST_STRUCT_DECL(type, name, ...) \
116 const DISPATCH_STRUCT_DECL(type, name, __VA_ARGS__)
117
118 #define DISPATCH_CONST_STRUCT_INSTANCE(type, name, ...) \
119 const DISPATCH_STRUCT_INSTANCE(type, name, __VA_ARGS__)
120 #else
121 #define DISPATCH_CONST_STRUCT_DECL(type, name, ...) \
122 DISPATCH_STRUCT_DECL(type, name, __VA_ARGS__)
123
124 #define DISPATCH_CONST_STRUCT_INSTANCE(type, name, ...) \
125 DISPATCH_STRUCT_INSTANCE(type, name, __VA_ARGS__)
126 #endif
127
128 /* private.h must be included last to avoid picking up installed headers. */
129 #include "object_private.h"
130 #include "queue_private.h"
131 #include "source_private.h"
132 #include "mach_private.h"
133 #include "data_private.h"
134 #if !TARGET_OS_WIN32
135 #include "io_private.h"
136 #endif
137 #include "voucher_private.h"
138 #include "voucher_activity_private.h"
139 #include "layout_private.h"
140 #include "benchmark.h"
141 #include "private.h"
142
143 /* SPI for Libsystem-internal use */
144 DISPATCH_EXPORT DISPATCH_NOTHROW void libdispatch_init(void);
145 #if !TARGET_OS_WIN32
146 DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_prepare(void);
147 DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_parent(void);
148 DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_child(void);
149 #endif
150
151 /* More #includes at EOF (dependent on the contents of internal.h) ... */
152
153 // Abort on uncaught exceptions thrown from client callouts rdar://8577499
154 #if !defined(DISPATCH_USE_CLIENT_CALLOUT)
155 #define DISPATCH_USE_CLIENT_CALLOUT 1
156 #endif
157
158 /* The "_debug" library build */
159 #ifndef DISPATCH_DEBUG
160 #define DISPATCH_DEBUG 0
161 #endif
162
163 #ifndef DISPATCH_PROFILE
164 #define DISPATCH_PROFILE 0
165 #endif
166
167 #if (!TARGET_OS_EMBEDDED || DISPATCH_DEBUG || DISPATCH_PROFILE) && \
168 !defined(DISPATCH_USE_DTRACE)
169 #define DISPATCH_USE_DTRACE 1
170 #endif
171
172 #if DISPATCH_USE_DTRACE && (DISPATCH_INTROSPECTION || DISPATCH_DEBUG || \
173 DISPATCH_PROFILE) && !defined(DISPATCH_USE_DTRACE_INTROSPECTION)
174 #define DISPATCH_USE_DTRACE_INTROSPECTION 1
175 #endif
176
177 #if HAVE_LIBKERN_OSCROSSENDIAN_H
178 #include <libkern/OSCrossEndian.h>
179 #endif
180 #if HAVE_LIBKERN_OSATOMIC_H
181 #include <libkern/OSAtomic.h>
182 #endif
183 #if HAVE_MACH
184 #include <mach/boolean.h>
185 #include <mach/clock_types.h>
186 #include <mach/clock.h>
187 #include <mach/exception.h>
188 #include <mach/mach.h>
189 #include <mach/mach_error.h>
190 #include <mach/mach_host.h>
191 #include <mach/mach_interface.h>
192 #include <mach/mach_time.h>
193 #include <mach/mach_traps.h>
194 #include <mach/message.h>
195 #include <mach/mig_errors.h>
196 #include <mach/host_special_ports.h>
197 #include <mach/host_info.h>
198 #include <mach/notify.h>
199 #include <mach/mach_vm.h>
200 #include <mach/vm_map.h>
201 #endif /* HAVE_MACH */
202 #if HAVE_MALLOC_MALLOC_H
203 #include <malloc/malloc.h>
204 #endif
205
206 #include <sys/stat.h>
207
208 #if !TARGET_OS_WIN32
209 #include <sys/event.h>
210 #include <sys/mount.h>
211 #include <sys/queue.h>
212 #include <sys/sysctl.h>
213 #include <sys/socket.h>
214 #include <sys/time.h>
215 #include <sys/mman.h>
216 #include <netinet/in.h>
217 #else
218 #include "sys_queue.h"
219 #endif
220
221 #ifdef __BLOCKS__
222 #include <Block_private.h>
223 #include <Block.h>
224 #endif /* __BLOCKS__ */
225
226 #include <assert.h>
227 #include <errno.h>
228 #if HAVE_FCNTL_H
229 #include <fcntl.h>
230 #endif
231 #include <limits.h>
232 #include <search.h>
233 #if USE_POSIX_SEM
234 #include <semaphore.h>
235 #endif
236 #include <signal.h>
237 #include <stdarg.h>
238 #include <stdbool.h>
239 #include <stdint.h>
240 #include <stdio.h>
241 #include <stdlib.h>
242 #include <string.h>
243 #if HAVE_UNISTD_H
244 #include <unistd.h>
245 #endif
246
247 #ifndef __has_builtin
248 #define __has_builtin(x) 0
249 #endif
250 #ifndef __has_include
251 #define __has_include(x) 0
252 #endif
253 #ifndef __has_feature
254 #define __has_feature(x) 0
255 #endif
256 #ifndef __has_attribute
257 #define __has_attribute(x) 0
258 #endif
259
260 #if __GNUC__
261 #define DISPATCH_NOINLINE __attribute__((__noinline__))
262 #define DISPATCH_USED __attribute__((__used__))
263 #define DISPATCH_UNUSED __attribute__((__unused__))
264 #define DISPATCH_WEAK __attribute__((__weak__))
265 #define DISPATCH_OVERLOADABLE __attribute__((__overloadable__))
266 #if DISPATCH_DEBUG
267 #define DISPATCH_ALWAYS_INLINE_NDEBUG
268 #else
269 #define DISPATCH_ALWAYS_INLINE_NDEBUG __attribute__((__always_inline__))
270 #endif
271 #else /* __GNUC__ */
272 #define DISPATCH_NOINLINE
273 #define DISPATCH_USED
274 #define DISPATCH_UNUSED
275 #define DISPATCH_WEAK
276 #define DISPATCH_ALWAYS_INLINE_NDEBUG
277 #endif /* __GNUC__ */
278
279 #define DISPATCH_CONCAT(x,y) DISPATCH_CONCAT1(x,y)
280 #define DISPATCH_CONCAT1(x,y) x ## y
281
282 // workaround 6368156
283 #ifdef NSEC_PER_SEC
284 #undef NSEC_PER_SEC
285 #endif
286 #ifdef USEC_PER_SEC
287 #undef USEC_PER_SEC
288 #endif
289 #ifdef NSEC_PER_USEC
290 #undef NSEC_PER_USEC
291 #endif
292 #define NSEC_PER_SEC 1000000000ull
293 #define USEC_PER_SEC 1000000ull
294 #define NSEC_PER_USEC 1000ull
295
296 /* I wish we had __builtin_expect_range() */
297 #if __GNUC__
298 #define fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
299 #define slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
300 #else
301 #define fastpath(x) (x)
302 #define slowpath(x) (x)
303 #endif // __GNUC__
304
305 #if DISPATCH_DEBUG
306 // sys/queue.h debugging
307 #undef TRASHIT
308 #define TRASHIT(x) do {(x) = (void *)-1;} while (0)
309 #endif // DISPATCH_DEBUG
310 #define _TAILQ_TRASH_ENTRY(elm, field) do { \
311 TRASHIT((elm)->field.tqe_next); \
312 TRASHIT((elm)->field.tqe_prev); \
313 } while (0)
314 #define _TAILQ_TRASH_HEAD(head) do { \
315 TRASHIT((head)->tqh_first); \
316 TRASHIT((head)->tqh_last); \
317 } while (0)
318
319 DISPATCH_NOINLINE
320 void _dispatch_bug(size_t line, long val);
321
322 #if HAVE_MACH
323 DISPATCH_NOINLINE
324 void _dispatch_bug_client(const char* msg);
325 DISPATCH_NOINLINE
326 void _dispatch_bug_mach_client(const char *msg, mach_msg_return_t kr);
327 DISPATCH_NOINLINE
328 void _dispatch_bug_kevent_client(const char* msg, const char* filter,
329 const char *operation, int err);
330 #endif
331
332 DISPATCH_NOINLINE DISPATCH_NORETURN
333 void _dispatch_abort(size_t line, long val);
334
335 #if !defined(DISPATCH_USE_OS_DEBUG_LOG) && DISPATCH_DEBUG
336 #if __has_include(<os/debug_private.h>)
337 #define DISPATCH_USE_OS_DEBUG_LOG 1
338 #include <os/debug_private.h>
339 #endif
340 #endif // DISPATCH_USE_OS_DEBUG_LOG
341
342 #if !defined(DISPATCH_USE_SIMPLE_ASL) && !DISPATCH_USE_OS_DEBUG_LOG
343 #if __has_include(<_simple.h>)
344 #define DISPATCH_USE_SIMPLE_ASL 1
345 #include <_simple.h>
346 #endif
347 #endif // DISPATCH_USE_SIMPLE_ASL
348
349 #if !DISPATCH_USE_SIMPLE_ASL && !DISPATCH_USE_OS_DEBUG_LOG && !TARGET_OS_WIN32
350 #include <syslog.h>
351 #endif
352
353 #if DISPATCH_USE_OS_DEBUG_LOG
354 #define _dispatch_log(msg, ...) os_debug_log("libdispatch", msg, ## __VA_ARGS__)
355 #else
356 DISPATCH_NOINLINE __attribute__((__format__(__printf__,1,2)))
357 void _dispatch_log(const char *msg, ...);
358 #endif // DISPATCH_USE_OS_DEBUG_LOG
359
360 #define dsnprintf(...) \
361 ({ int _r = snprintf(__VA_ARGS__); _r < 0 ? 0u : (size_t)_r; })
362
363 #if __GNUC__
364 #define dispatch_static_assert(e) ({ \
365 char __compile_time_assert__[(bool)(e) ? 1 : -1] DISPATCH_UNUSED; \
366 })
367 #else
368 #define dispatch_static_assert(e)
369 #endif
370
371 /*
372 * For reporting bugs within libdispatch when using the "_debug" version of the
373 * library.
374 */
375 #if __GNUC__
376 #define dispatch_assert(e) do { \
377 if (__builtin_constant_p(e)) { \
378 dispatch_static_assert(e); \
379 } else { \
380 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
381 if (DISPATCH_DEBUG && !_e) { \
382 _dispatch_abort(__LINE__, (long)_e); \
383 } \
384 } \
385 } while (0)
386 #else
387 static inline void _dispatch_assert(long e, long line) {
388 if (DISPATCH_DEBUG && !e) _dispatch_abort(line, e);
389 }
390 #define dispatch_assert(e) _dispatch_assert((long)(e), __LINE__)
391 #endif /* __GNUC__ */
392
393 #if __GNUC__
394 /*
395 * A lot of API return zero upon success and not-zero on fail. Let's capture
396 * and log the non-zero value
397 */
398 #define dispatch_assert_zero(e) do { \
399 if (__builtin_constant_p(e)) { \
400 dispatch_static_assert(e); \
401 } else { \
402 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
403 if (DISPATCH_DEBUG && _e) { \
404 _dispatch_abort(__LINE__, (long)_e); \
405 } \
406 } \
407 } while (0)
408 #else
409 static inline void _dispatch_assert_zero(long e, long line) {
410 if (DISPATCH_DEBUG && e) _dispatch_abort(line, e);
411 }
412 #define dispatch_assert_zero(e) _dispatch_assert((long)(e), __LINE__)
413 #endif /* __GNUC__ */
414
415 /*
416 * For reporting bugs or impedance mismatches between libdispatch and external
417 * subsystems. These do NOT abort(), and are always compiled into the product.
418 *
419 * In particular, we wrap all system-calls with assume() macros.
420 */
421 #if __GNUC__
422 #define dispatch_assume(e) ({ \
423 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
424 if (!_e) { \
425 if (__builtin_constant_p(e)) { \
426 dispatch_static_assert(e); \
427 } \
428 _dispatch_bug(__LINE__, (long)_e); \
429 } \
430 _e; \
431 })
432 #else
433 static inline long _dispatch_assume(long e, long line) {
434 if (!e) _dispatch_bug(line, e);
435 return e;
436 }
437 #define dispatch_assume(e) _dispatch_assume((long)(e), __LINE__)
438 #endif /* __GNUC__ */
439
440 /*
441 * A lot of API return zero upon success and not-zero on fail. Let's capture
442 * and log the non-zero value
443 */
444 #if __GNUC__
445 #define dispatch_assume_zero(e) ({ \
446 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
447 if (_e) { \
448 if (__builtin_constant_p(e)) { \
449 dispatch_static_assert(e); \
450 } \
451 _dispatch_bug(__LINE__, (long)_e); \
452 } \
453 _e; \
454 })
455 #else
456 static inline long _dispatch_assume_zero(long e, long line) {
457 if (e) _dispatch_bug(line, e);
458 return e;
459 }
460 #define dispatch_assume_zero(e) _dispatch_assume_zero((long)(e), __LINE__)
461 #endif /* __GNUC__ */
462
463 /*
464 * For reporting bugs in clients when using the "_debug" version of the library.
465 */
466 #if __GNUC__
467 #define dispatch_debug_assert(e, msg, args...) do { \
468 if (__builtin_constant_p(e)) { \
469 dispatch_static_assert(e); \
470 } else { \
471 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
472 if (DISPATCH_DEBUG && !_e) { \
473 _dispatch_log("%s() 0x%lx: " msg, __func__, (long)_e, ##args); \
474 abort(); \
475 } \
476 } \
477 } while (0)
478 #else
479 #define dispatch_debug_assert(e, msg, args...) do { \
480 long _e = (long)fastpath(e); /* always eval 'e' */ \
481 if (DISPATCH_DEBUG && !_e) { \
482 _dispatch_log("%s() 0x%lx: " msg, __FUNCTION__, _e, ##args); \
483 abort(); \
484 } \
485 } while (0)
486 #endif /* __GNUC__ */
487
488 /* Make sure the debug statments don't get too stale */
489 #define _dispatch_debug(x, args...) do { \
490 if (DISPATCH_DEBUG) { \
491 _dispatch_log("%u\t%p\t" x, __LINE__, \
492 (void *)_dispatch_thread_self(), ##args); \
493 } \
494 } while (0)
495
496 #if DISPATCH_DEBUG
497 #if HAVE_MACH
498 DISPATCH_NOINLINE DISPATCH_USED
499 void dispatch_debug_machport(mach_port_t name, const char* str);
500 #endif
501 #endif
502
503 #if DISPATCH_DEBUG
504 /* This is the private version of the deprecated dispatch_debug() */
505 DISPATCH_NONNULL2 DISPATCH_NOTHROW
506 __attribute__((__format__(printf,2,3)))
507 void
508 _dispatch_object_debug(dispatch_object_t object, const char *message, ...);
509 #else
510 #define _dispatch_object_debug(object, message, ...)
511 #endif // DISPATCH_DEBUG
512
513 #ifdef __BLOCKS__
514 #define _dispatch_Block_invoke(bb) \
515 ((dispatch_function_t)((struct Block_layout *)bb)->invoke)
516 #if __GNUC__
517 dispatch_block_t _dispatch_Block_copy(dispatch_block_t block);
518 #define _dispatch_Block_copy(x) ((typeof(x))_dispatch_Block_copy(x))
519 #else
520 dispatch_block_t _dispatch_Block_copy(const void *block);
521 #endif
522 void _dispatch_call_block_and_release(void *block);
523 #endif /* __BLOCKS__ */
524
525 void _dispatch_temporary_resource_shortage(void);
526 void *_dispatch_calloc(size_t num_items, size_t size);
527 void _dispatch_vtable_init(void);
528 char *_dispatch_get_build(void);
529
530 uint64_t _dispatch_timeout(dispatch_time_t when);
531
532 extern bool _dispatch_safe_fork, _dispatch_child_of_unsafe_fork;
533
534 #if !defined(DISPATCH_USE_OS_SEMAPHORE_CACHE) && !(TARGET_IPHONE_SIMULATOR)
535 // rdar://problem/15492045
536 #if __has_include(<os/semaphore_private.h>)
537 #define DISPATCH_USE_OS_SEMAPHORE_CACHE 1
538 #include <os/semaphore_private.h>
539 #endif
540 #endif
541
542 /* #includes dependent on internal.h */
543 #include "shims.h"
544
545 // Older Mac OS X and iOS Simulator fallbacks
546
547 #if HAVE_PTHREAD_WORKQUEUES
548 #ifndef WORKQ_ADDTHREADS_OPTION_OVERCOMMIT
549 #define WORKQ_ADDTHREADS_OPTION_OVERCOMMIT 0x00000001
550 #endif
551 #if TARGET_IPHONE_SIMULATOR && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1080
552 #ifndef DISPATCH_USE_LEGACY_WORKQUEUE_FALLBACK
553 #define DISPATCH_USE_LEGACY_WORKQUEUE_FALLBACK 1
554 #endif
555 #endif
556 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 1080
557 #undef HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP
558 #define HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP 0
559 #endif
560 #if TARGET_IPHONE_SIMULATOR && \
561 IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 101000
562 #ifndef DISPATCH_USE_NOQOS_WORKQUEUE_FALLBACK
563 #define DISPATCH_USE_NOQOS_WORKQUEUE_FALLBACK 1
564 #endif
565 #endif
566 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000
567 #undef HAVE__PTHREAD_WORKQUEUE_INIT
568 #define HAVE__PTHREAD_WORKQUEUE_INIT 0
569 #endif
570 #endif // HAVE_PTHREAD_WORKQUEUES
571 #if HAVE__PTHREAD_WORKQUEUE_INIT && PTHREAD_WORKQUEUE_SPI_VERSION >= 20140213 \
572 && !defined(HAVE_PTHREAD_WORKQUEUE_QOS)
573 #define HAVE_PTHREAD_WORKQUEUE_QOS 1
574 #endif
575
576 #if HAVE_MACH
577 #if !defined(MACH_NOTIFY_SEND_POSSIBLE) || (TARGET_IPHONE_SIMULATOR && \
578 IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1070)
579 #undef MACH_NOTIFY_SEND_POSSIBLE
580 #define MACH_NOTIFY_SEND_POSSIBLE MACH_NOTIFY_DEAD_NAME
581 #endif
582 #endif // HAVE_MACH
583
584 #ifdef EVFILT_MEMORYSTATUS
585 #ifndef DISPATCH_USE_MEMORYSTATUS
586 #define DISPATCH_USE_MEMORYSTATUS 1
587 #endif
588 #endif // EVFILT_MEMORYSTATUS
589
590 #if defined(EVFILT_VM) && !DISPATCH_USE_MEMORYSTATUS
591 #ifndef DISPATCH_USE_VM_PRESSURE
592 #define DISPATCH_USE_VM_PRESSURE 1
593 #endif
594 #endif // EVFILT_VM
595
596 #if TARGET_IPHONE_SIMULATOR
597 #undef DISPATCH_USE_MEMORYSTATUS_SOURCE
598 #define DISPATCH_USE_MEMORYSTATUS_SOURCE 0
599 #undef DISPATCH_USE_VM_PRESSURE_SOURCE
600 #define DISPATCH_USE_VM_PRESSURE_SOURCE 0
601 #endif // TARGET_IPHONE_SIMULATOR
602 #if !defined(DISPATCH_USE_MEMORYSTATUS_SOURCE) && DISPATCH_USE_MEMORYSTATUS
603 #define DISPATCH_USE_MEMORYSTATUS_SOURCE 1
604 #elif !defined(DISPATCH_USE_VM_PRESSURE_SOURCE) && DISPATCH_USE_VM_PRESSURE
605 #define DISPATCH_USE_VM_PRESSURE_SOURCE 1
606 #endif
607
608 #if !defined(NOTE_LEEWAY) || (TARGET_IPHONE_SIMULATOR && \
609 IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090)
610 #undef NOTE_LEEWAY
611 #define NOTE_LEEWAY 0
612 #undef NOTE_CRITICAL
613 #define NOTE_CRITICAL 0
614 #undef NOTE_BACKGROUND
615 #define NOTE_BACKGROUND 0
616 #endif // NOTE_LEEWAY
617
618 #if HAVE_DECL_NOTE_REAP
619 #if defined(NOTE_REAP) && defined(__APPLE__)
620 #undef NOTE_REAP
621 #define NOTE_REAP 0x10000000 // <rdar://problem/13338526>
622 #endif
623 #endif // HAVE_DECL_NOTE_REAP
624
625 #if !defined(EV_UDATA_SPECIFIC) || (TARGET_IPHONE_SIMULATOR && \
626 IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 101100) || \
627 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100)
628 #undef DISPATCH_USE_EV_UDATA_SPECIFIC
629 #define DISPATCH_USE_EV_UDATA_SPECIFIC 0
630 #elif !defined(DISPATCH_USE_EV_UDATA_SPECIFIC)
631 #define DISPATCH_USE_EV_UDATA_SPECIFIC 1
632 #endif // EV_UDATA_SPECIFIC
633
634 #if !DISPATCH_USE_EV_UDATA_SPECIFIC
635 #undef EV_UDATA_SPECIFIC
636 #define EV_UDATA_SPECIFIC 0
637 #undef DISPATCH_DYNAMIC_SELECT_FALLBACK
638 #define DISPATCH_DYNAMIC_SELECT_FALLBACK 0
639 #undef DISPATCH_USE_SELECT_FALLBACK
640 #define DISPATCH_USE_SELECT_FALLBACK 1
641 #endif // !DISPATCH_USE_EV_UDATA_SPECIFIC
642
643 #if !defined(EV_SET_QOS) || (TARGET_IPHONE_SIMULATOR && \
644 IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 101100) || \
645 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100)
646 #undef DISPATCH_USE_KEVENT_QOS
647 #define DISPATCH_USE_KEVENT_QOS 0
648 #elif !defined(DISPATCH_USE_KEVENT_QOS)
649 #define DISPATCH_USE_KEVENT_QOS 1
650 #endif // EV_SET_QOS
651
652 #if DISPATCH_USE_KEVENT_QOS
653 typedef struct kevent_qos_s _dispatch_kevent_qos_s;
654 #else // DISPATCH_USE_KEVENT_QOS
655 #ifndef KEVENT_FLAG_IMMEDIATE
656 #define KEVENT_FLAG_NONE 0x00
657 #define KEVENT_FLAG_IMMEDIATE 0x01
658 #define KEVENT_FLAG_ERROR_EVENTS 0x02
659 #endif // KEVENT_FLAG_IMMEDIATE
660 typedef struct kevent64_s _dispatch_kevent_qos_s;
661 #define kevent_qos(_kq, _changelist, _nchanges, _eventlist, _nevents, \
662 _data_out, _data_available, _flags) \
663 ({ unsigned int _f = (_flags); _dispatch_kevent_qos_s _kev_copy; \
664 const _dispatch_kevent_qos_s *_cl = (_changelist); \
665 int _n = (_nchanges); const struct timespec _timeout_immediately = {}; \
666 dispatch_static_assert(!(_data_out) && !(_data_available)); \
667 if (_f & KEVENT_FLAG_ERROR_EVENTS) { \
668 dispatch_static_assert(_n == 1); \
669 _kev_copy = *_cl; _kev_copy.flags |= EV_RECEIPT; } \
670 kevent64((_kq), _f & KEVENT_FLAG_ERROR_EVENTS ? &_kev_copy : _cl, _n, \
671 (_eventlist), (_nevents), 0, \
672 _f & KEVENT_FLAG_IMMEDIATE ? &_timeout_immediately : NULL); })
673 #endif // DISPATCH_USE_KEVENT_QOS
674
675 #if defined(F_SETNOSIGPIPE) && defined(F_GETNOSIGPIPE)
676 #if TARGET_IPHONE_SIMULATOR && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1070
677 #undef DISPATCH_USE_SETNOSIGPIPE
678 #define DISPATCH_USE_SETNOSIGPIPE 0
679 #endif
680 #ifndef DISPATCH_USE_SETNOSIGPIPE
681 #define DISPATCH_USE_SETNOSIGPIPE 1
682 #endif
683 #endif // F_SETNOSIGPIPE
684
685 #if defined(MACH_SEND_NOIMPORTANCE)
686 #ifndef DISPATCH_USE_CHECKIN_NOIMPORTANCE
687 #define DISPATCH_USE_CHECKIN_NOIMPORTANCE 1 // rdar://problem/16996737
688 #endif
689 #ifndef DISPATCH_USE_NOIMPORTANCE_QOS
690 #define DISPATCH_USE_NOIMPORTANCE_QOS 1 // rdar://problem/21414476
691 #endif
692 #endif // MACH_SEND_NOIMPORTANCE
693
694
695 #if HAVE_LIBPROC_INTERNAL_H
696 #include <libproc.h>
697 #include <libproc_internal.h>
698 #if TARGET_IPHONE_SIMULATOR && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090
699 #undef DISPATCH_USE_IMPORTANCE_ASSERTION
700 #define DISPATCH_USE_IMPORTANCE_ASSERTION 0
701 #endif
702 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED < 1090
703 #undef DISPATCH_USE_IMPORTANCE_ASSERTION
704 #define DISPATCH_USE_IMPORTANCE_ASSERTION 0
705 #endif
706 #ifndef DISPATCH_USE_IMPORTANCE_ASSERTION
707 #define DISPATCH_USE_IMPORTANCE_ASSERTION 1
708 #endif
709 #endif // HAVE_LIBPROC_INTERNAL_H
710
711 #if HAVE_SYS_GUARDED_H
712 #include <sys/guarded.h>
713 #if TARGET_IPHONE_SIMULATOR && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090
714 #undef DISPATCH_USE_GUARDED_FD
715 #define DISPATCH_USE_GUARDED_FD 0
716 #endif
717 #ifndef DISPATCH_USE_GUARDED_FD
718 #define DISPATCH_USE_GUARDED_FD 1
719 #endif
720 // change_fdguard_np() requires GUARD_DUP <rdar://problem/11814513>
721 #if DISPATCH_USE_GUARDED_FD && RDAR_11814513
722 #define DISPATCH_USE_GUARDED_FD_CHANGE_FDGUARD 1
723 #endif
724 #endif // HAVE_SYS_GUARDED_H
725
726
727 #ifndef MACH_MSGH_BITS_VOUCHER_MASK
728 #define MACH_MSGH_BITS_VOUCHER_MASK 0x001f0000
729 #define MACH_MSGH_BITS_SET_PORTS(remote, local, voucher) \
730 (((remote) & MACH_MSGH_BITS_REMOTE_MASK) | \
731 (((local) << 8) & MACH_MSGH_BITS_LOCAL_MASK) | \
732 (((voucher) << 16) & MACH_MSGH_BITS_VOUCHER_MASK))
733 #define MACH_MSGH_BITS_VOUCHER(bits) \
734 (((bits) & MACH_MSGH_BITS_VOUCHER_MASK) >> 16)
735 #define MACH_MSGH_BITS_HAS_VOUCHER(bits) \
736 (MACH_MSGH_BITS_VOUCHER(bits) != MACH_MSGH_BITS_ZERO)
737 #define msgh_voucher_port msgh_reserved
738 #define mach_voucher_t mach_port_t
739 #define MACH_VOUCHER_NULL MACH_PORT_NULL
740 #define MACH_SEND_INVALID_VOUCHER 0x10000005
741 #endif
742
743 #define _dispatch_hardware_crash() \
744 __asm__(""); __builtin_trap() // <rdar://problem/17464981>
745
746 #define _dispatch_set_crash_log_message(msg)
747 #define _dispatch_set_crash_log_message_dynamic(msg)
748
749 #if HAVE_MACH
750 // MIG_REPLY_MISMATCH means either:
751 // 1) A signal handler is NOT using async-safe API. See the sigaction(2) man
752 // page for more info.
753 // 2) A hand crafted call to mach_msg*() screwed up. Use MIG.
754 #define DISPATCH_VERIFY_MIG(x) do { \
755 if ((x) == MIG_REPLY_MISMATCH) { \
756 _dispatch_set_crash_log_message("MIG_REPLY_MISMATCH"); \
757 _dispatch_hardware_crash(); \
758 } \
759 } while (0)
760 #endif
761
762 #define DISPATCH_CRASH(x) do { \
763 _dispatch_set_crash_log_message("BUG IN LIBDISPATCH: " x); \
764 _dispatch_hardware_crash(); \
765 } while (0)
766
767 #define DISPATCH_CLIENT_CRASH(x) do { \
768 _dispatch_set_crash_log_message("BUG IN CLIENT OF LIBDISPATCH: " x); \
769 _dispatch_hardware_crash(); \
770 } while (0)
771
772 #define _OS_OBJECT_CLIENT_CRASH(x) do { \
773 _dispatch_set_crash_log_message("API MISUSE: " x); \
774 _dispatch_hardware_crash(); \
775 } while (0)
776
777 extern int _dispatch_set_qos_class_enabled;
778 #define DISPATCH_NO_VOUCHER ((voucher_t)(void*)~0ul)
779 #define DISPATCH_NO_PRIORITY ((pthread_priority_t)~0ul)
780 #define DISPATCH_PRIORITY_ENFORCE 0x1
781 #define DISPATCH_VOUCHER_IGNORE_QUEUE_OVERRIDE 0x2
782 static inline void _dispatch_adopt_priority_and_replace_voucher(
783 pthread_priority_t priority, voucher_t voucher, unsigned long flags);
784 #if HAVE_MACH
785 static inline void _dispatch_set_priority_and_mach_voucher(
786 pthread_priority_t priority, mach_voucher_t kv);
787 mach_port_t _dispatch_get_mach_host_port(void);
788 #endif
789
790
791 /* #includes dependent on internal.h */
792 #include "object_internal.h"
793 #include "semaphore_internal.h"
794 #include "introspection_internal.h"
795 #include "queue_internal.h"
796 #include "source_internal.h"
797 #include "voucher_internal.h"
798 #include "data_internal.h"
799 #if !TARGET_OS_WIN32
800 #include "io_internal.h"
801 #endif
802 #include "inline_internal.h"
803
804 #endif /* __DISPATCH_INTERNAL__ */