2 * Copyright (c) 2008-2009 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__
35 #include "dispatch/dispatch.h"
36 #include "dispatch/base.h"
37 #include "dispatch/time.h"
38 #include "dispatch/queue.h"
39 #include "dispatch/object.h"
40 #include "dispatch/source.h"
41 #include "dispatch/group.h"
42 #include "dispatch/semaphore.h"
43 #include "dispatch/once.h"
44 #include "dispatch/benchmark.h"
46 /* private.h uses #include_next and must be included last to avoid picking
47 * up installed headers. */
48 #include "queue_private.h"
49 #include "source_private.h"
52 #ifndef DISPATCH_NO_LEGACY
55 /* More #includes at EOF (dependent on the contents of internal.h) ... */
57 /* The "_debug" library build */
58 #ifndef DISPATCH_DEBUG
59 #define DISPATCH_DEBUG 0
63 #if HAVE_LIBKERN_OSCROSSENDIAN_H
64 #include <libkern/OSCrossEndian.h>
66 #if HAVE_LIBKERN_OSATOMIC_H
67 #include <libkern/OSAtomic.h>
70 #include <mach/boolean.h>
71 #include <mach/clock_types.h>
72 #include <mach/clock.h>
73 #include <mach/exception.h>
74 #include <mach/mach.h>
75 #include <mach/mach_error.h>
76 #include <mach/mach_host.h>
77 #include <mach/mach_interface.h>
78 #include <mach/mach_time.h>
79 #include <mach/mach_traps.h>
80 #include <mach/message.h>
81 #include <mach/mig_errors.h>
82 #include <mach/host_info.h>
83 #include <mach/notify.h>
84 #endif /* HAVE_MACH */
85 #if HAVE_MALLOC_MALLOC_H
86 #include <malloc/malloc.h>
88 #include <sys/mount.h>
89 #include <sys/queue.h>
92 #include <sys/sysctl.h>
94 #include <sys/socket.h>
96 #include <netinet/in.h>
99 #include <Block_private.h>
101 #endif /* __BLOCKS__ */
109 #include <semaphore.h>
123 #define DISPATCH_NOINLINE __attribute__((noinline))
125 // workaround 6368156
135 #define NSEC_PER_SEC 1000000000ull
136 #define USEC_PER_SEC 1000000ull
137 #define NSEC_PER_USEC 1000ull
139 /* I wish we had __builtin_expect_range() */
141 #define fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
142 #define slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
144 #define fastpath(x) (x)
145 #define slowpath(x) (x)
148 void _dispatch_bug(size_t line, long val) __attribute__((__noinline__));
149 void _dispatch_abort(size_t line, long val) __attribute__((__noinline__,__noreturn__));
150 void _dispatch_log(const char *msg, ...) __attribute__((__noinline__,__format__(printf,1,2)));
151 void _dispatch_logv(const char *msg, va_list) __attribute__((__noinline__,__format__(printf,1,0)));
154 * For reporting bugs within libdispatch when using the "_debug" version of the library.
156 #define dispatch_assert(e) do { \
157 if (__builtin_constant_p(e)) { \
158 char __compile_time_assert__[(bool)(e) ? 1 : -1] __attribute__((unused)); \
160 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
161 if (DISPATCH_DEBUG && !_e) { \
162 _dispatch_abort(__LINE__, (long)_e); \
166 /* A lot of API return zero upon success and not-zero on fail. Let's capture and log the non-zero value */
167 #define dispatch_assert_zero(e) do { \
168 if (__builtin_constant_p(e)) { \
169 char __compile_time_assert__[(bool)(!(e)) ? 1 : -1] __attribute__((unused)); \
171 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
172 if (DISPATCH_DEBUG && _e) { \
173 _dispatch_abort(__LINE__, (long)_e); \
179 * For reporting bugs or impedance mismatches between libdispatch and external subsystems.
180 * These do NOT abort(), and are always compiled into the product.
182 * In particular, we wrap all system-calls with assume() macros.
184 #define dispatch_assume(e) ({ \
185 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
187 if (__builtin_constant_p(e)) { \
188 char __compile_time_assert__[(e) ? 1 : -1]; \
189 (void)__compile_time_assert__; \
191 _dispatch_bug(__LINE__, (long)_e); \
195 /* A lot of API return zero upon success and not-zero on fail. Let's capture and log the non-zero value */
196 #define dispatch_assume_zero(e) ({ \
197 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
199 if (__builtin_constant_p(e)) { \
200 char __compile_time_assert__[(e) ? -1 : 1]; \
201 (void)__compile_time_assert__; \
203 _dispatch_bug(__LINE__, (long)_e); \
209 * For reporting bugs in clients when using the "_debug" version of the library.
211 #define dispatch_debug_assert(e, msg, args...) do { \
212 if (__builtin_constant_p(e)) { \
213 char __compile_time_assert__[(bool)(e) ? 1 : -1] __attribute__((unused)); \
215 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
216 if (DISPATCH_DEBUG && !_e) { \
217 _dispatch_log("%s() 0x%lx: " msg, __func__, (long)_e, ##args); \
224 #define DO_CAST(x) ((struct dispatch_object_s *)(x)._do)
226 #define DO_CAST(x) ((struct dispatch_object_s *)(x))
230 dispatch_block_t _dispatch_Block_copy(dispatch_block_t block);
231 void _dispatch_call_block_and_release(void *block);
232 void _dispatch_call_block_and_release2(void *block, void *ctxt);
233 #endif /* __BLOCKS__ */
235 void dummy_function(void);
236 long dummy_function_r0(void);
239 /* Make sure the debug statments don't get too stale */
240 #define _dispatch_debug(x, args...) \
242 if (DISPATCH_DEBUG) { \
243 _dispatch_log("libdispatch: %u\t%p\t" x, __LINE__, \
244 (void *)_dispatch_thread_self(), ##args); \
249 uint64_t _dispatch_get_nanoseconds(void);
251 #ifndef DISPATCH_NO_LEGACY
253 _dispatch_source_create2(dispatch_source_t ds,
254 dispatch_source_attr_t attr,
256 dispatch_source_handler_function_t handler);
259 void _dispatch_run_timers(void);
260 // Returns howsoon with updated time value, or NULL if no timers active.
261 struct timespec *_dispatch_get_next_timer_fire(struct timespec *howsoon);
263 dispatch_semaphore_t _dispatch_get_thread_semaphore(void);
264 void _dispatch_put_thread_semaphore(dispatch_semaphore_t);
266 bool _dispatch_source_testcancel(dispatch_source_t);
268 uint64_t _dispatch_timeout(dispatch_time_t when);
270 struct timespec _dispatch_timeout_ts(dispatch_time_t when);
273 __private_extern__ bool _dispatch_safe_fork;
275 __private_extern__ struct _dispatch_hw_config_s {
276 uint32_t cc_max_active;
277 uint32_t cc_max_logical;
278 uint32_t cc_max_physical;
279 } _dispatch_hw_config;
281 /* #includes dependent on internal.h */
282 #include "object_internal.h"
283 #include "hw_shims.h"
284 #include "os_shims.h"
285 #include "queue_internal.h"
286 #include "semaphore_internal.h"
287 #include "source_internal.h"
289 #if USE_APPLE_CRASHREPORTER_INFO
292 // MIG_REPLY_MISMATCH means either:
293 // 1) A signal handler is NOT using async-safe API. See the sigaction(2) man page for more info.
294 // 2) A hand crafted call to mach_msg*() screwed up. Use MIG.
295 #define DISPATCH_VERIFY_MIG(x) do { \
296 if ((x) == MIG_REPLY_MISMATCH) { \
297 __crashreporter_info__ = "MIG_REPLY_MISMATCH"; \
298 _dispatch_hardware_crash(); \
303 #if defined(__x86_64__) || defined(__i386__)
304 // total hack to ensure that return register of a function is not trashed
305 #define DISPATCH_CRASH(x) do { \
306 asm("mov %1, %0" : "=m" (__crashreporter_info__) : "c" ("BUG IN LIBDISPATCH: " x)); \
307 _dispatch_hardware_crash(); \
310 #define DISPATCH_CLIENT_CRASH(x) do { \
311 asm("mov %1, %0" : "=m" (__crashreporter_info__) : "c" ("BUG IN CLIENT OF LIBDISPATCH: " x)); \
312 _dispatch_hardware_crash(); \
315 #else /* !(defined(__x86_64__) || defined(__i386__)) */
317 #define DISPATCH_CRASH(x) do { \
318 __crashreporter_info__ = "BUG IN LIBDISPATCH: " x; \
319 _dispatch_hardware_crash(); \
322 #define DISPATCH_CLIENT_CRASH(x) do { \
323 __crashreporter_info__ = "BUG IN CLIENT OF LIBDISPATCH: " x; \
324 _dispatch_hardware_crash(); \
326 #endif /* defined(__x86_64__) || defined(__i386__) */
328 #else /* !USE_APPLE_CRASHREPORTER_INFO */
331 #define DISPATCH_VERIFY_MIG(x) do { \
332 if ((x) == MIG_REPLY_MISMATCH) { \
333 _dispatch_hardware_crash(); \
338 #define DISPATCH_CRASH(x) _dispatch_hardware_crash()
339 #define DISPATCH_CLIENT_CRASH(x) _dispatch_hardware_crash()
341 #endif /* USE_APPLE_CRASHREPORTER_INFO */
343 #endif /* __DISPATCH_INTERNAL__ */