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