2 * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
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.
27 #ifndef __DISPATCH_INTERNAL__
28 #define __DISPATCH_INTERNAL__
30 #include <config/config.h>
32 #define __DISPATCH_BUILDING_DISPATCH__
33 #define __DISPATCH_INDIRECT__
36 #include <dispatch/dispatch.h>
37 #include <dispatch/base.h>
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>
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"
57 /* More #includes at EOF (dependent on the contents of internal.h) ... */
59 /* The "_debug" library build */
60 #ifndef DISPATCH_DEBUG
61 #define DISPATCH_DEBUG 0
64 #ifndef DISPATCH_PROFILE
65 #define DISPATCH_PROFILE 0
68 #if DISPATCH_DEBUG && !defined(DISPATCH_USE_CLIENT_CALLOUT)
69 #define DISPATCH_USE_CLIENT_CALLOUT 1
72 #if (DISPATCH_DEBUG || DISPATCH_PROFILE) && !defined(DISPATCH_USE_DTRACE)
73 #define DISPATCH_USE_DTRACE 1
76 #if HAVE_LIBKERN_OSCROSSENDIAN_H
77 #include <libkern/OSCrossEndian.h>
79 #if HAVE_LIBKERN_OSATOMIC_H
80 #include <libkern/OSAtomic.h>
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>
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>
111 #include <Block_private.h>
113 #endif /* __BLOCKS__ */
121 #include <semaphore.h>
135 #ifndef __has_builtin
136 #define __has_builtin(x) 0
138 #ifndef __has_include
139 #define __has_include(x) 0
141 #ifndef __has_feature
142 #define __has_feature(x) 0
144 #ifndef __has_attribute
145 #define __has_attribute(x) 0
148 #define DISPATCH_NOINLINE __attribute__((__noinline__))
149 #define DISPATCH_USED __attribute__((__used__))
150 #define DISPATCH_UNUSED __attribute__((__unused__))
151 #define DISPATCH_WEAK __attribute__((__weak__))
153 #define DISPATCH_ALWAYS_INLINE_NDEBUG
155 #define DISPATCH_ALWAYS_INLINE_NDEBUG __attribute__((__always_inline__))
158 // workaround 6368156
168 #define NSEC_PER_SEC 1000000000ull
169 #define USEC_PER_SEC 1000000ull
170 #define NSEC_PER_USEC 1000ull
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))
177 void _dispatch_bug(size_t line
, long val
);
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);
188 * For reporting bugs within libdispatch when using the "_debug" version of the
191 #define dispatch_assert(e) do { \
192 if (__builtin_constant_p(e)) { \
193 char __compile_time_assert__[(bool)(e) ? 1 : -1] DISPATCH_UNUSED; \
195 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
196 if (DISPATCH_DEBUG && !_e) { \
197 _dispatch_abort(__LINE__, (long)_e); \
202 * A lot of API return zero upon success and not-zero on fail. Let's capture
203 * and log the non-zero value
205 #define dispatch_assert_zero(e) do { \
206 if (__builtin_constant_p(e)) { \
207 char __compile_time_assert__[(bool)(e) ? -1 : 1] DISPATCH_UNUSED; \
209 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
210 if (DISPATCH_DEBUG && _e) { \
211 _dispatch_abort(__LINE__, (long)_e); \
217 * For reporting bugs or impedance mismatches between libdispatch and external
218 * subsystems. These do NOT abort(), and are always compiled into the product.
220 * In particular, we wrap all system-calls with assume() macros.
222 #define dispatch_assume(e) ({ \
223 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
225 if (__builtin_constant_p(e)) { \
226 char __compile_time_assert__[(bool)(e) ? 1 : -1]; \
227 (void)__compile_time_assert__; \
229 _dispatch_bug(__LINE__, (long)_e); \
234 * A lot of API return zero upon success and not-zero on fail. Let's capture
235 * and log the non-zero value
237 #define dispatch_assume_zero(e) ({ \
238 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
240 if (__builtin_constant_p(e)) { \
241 char __compile_time_assert__[(bool)(e) ? -1 : 1]; \
242 (void)__compile_time_assert__; \
244 _dispatch_bug(__LINE__, (long)_e); \
250 * For reporting bugs in clients when using the "_debug" version of the library.
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; \
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); \
264 /* Make sure the debug statments don't get too stale */
265 #define _dispatch_debug(x, args...) \
267 if (DISPATCH_DEBUG) { \
268 _dispatch_log("libdispatch: %u\t%p\t" x, __LINE__, \
269 (void *)_dispatch_thread_self(), ##args); \
275 DISPATCH_NOINLINE DISPATCH_USED
276 void dispatch_debug_machport(mach_port_t name
, const char* str
);
278 DISPATCH_NOINLINE DISPATCH_USED
279 void dispatch_debug_kevents(struct kevent
* kev
, size_t count
, const char* str
);
282 dispatch_debug_kevents(struct kevent
* kev DISPATCH_UNUSED
,
283 size_t count DISPATCH_UNUSED
,
284 const char* str DISPATCH_UNUSED
) {}
287 #if DISPATCH_USE_CLIENT_CALLOUT
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));
296 DISPATCH_ALWAYS_INLINE
298 _dispatch_client_callout(void *ctxt
, dispatch_function_t f
)
303 DISPATCH_ALWAYS_INLINE
305 _dispatch_client_callout2(void *ctxt
, size_t i
, void (*f
)(void *, size_t))
313 DISPATCH_ALWAYS_INLINE
315 _dispatch_client_callout_block(dispatch_block_t b
)
317 struct Block_basic
*bb
= (void*)b
;
318 return _dispatch_client_callout(b
, (dispatch_function_t
)bb
->Block_invoke
);
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__ */
326 void dummy_function(void);
327 long dummy_function_r0(void);
329 void _dispatch_source_drain_kevent(struct kevent
*);
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
);
336 bool _dispatch_source_testcancel(dispatch_source_t
);
338 uint64_t _dispatch_timeout(dispatch_time_t when
);
340 extern bool _dispatch_safe_fork
;
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
;
348 /* #includes dependent on internal.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"
358 // SnowLeopard and iOS Simulator fallbacks
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
366 #endif // HAVE_PTHREAD_WORKQUEUES
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
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
381 #ifndef DISPATCH_USE_VM_PRESSURE
382 #define DISPATCH_USE_VM_PRESSURE 1
384 #ifndef DISPATCH_USE_MALLOC_VM_PRESSURE_SOURCE
385 #define DISPATCH_USE_MALLOC_VM_PRESSURE_SOURCE 1
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
394 #ifndef DISPATCH_USE_SETNOSIGPIPE
395 #define DISPATCH_USE_SETNOSIGPIPE 1
397 #endif // F_SETNOSIGPIPE
400 #define _dispatch_set_crash_log_message(x)
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(); \
415 #define DISPATCH_CRASH(x) do { \
416 _dispatch_set_crash_log_message("BUG IN LIBDISPATCH: " x); \
417 _dispatch_hardware_crash(); \
420 #define DISPATCH_CLIENT_CRASH(x) do { \
421 _dispatch_set_crash_log_message("BUG IN CLIENT OF LIBDISPATCH: " x); \
422 _dispatch_hardware_crash(); \
425 #endif /* __DISPATCH_INTERNAL__ */