]> git.saurik.com Git - apple/libdispatch.git/blob - src/internal.h
libdispatch-84.5.1.tar.gz
[apple/libdispatch.git] / src / internal.h
1 /*
2 * Copyright (c) 2008-2009 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 #define __DISPATCH_BUILDING_DISPATCH__
31 #define __DISPATCH_INDIRECT__
32 #include "dispatch.h"
33 #include "base.h"
34 #include "time.h"
35 #include "queue.h"
36 #include "object.h"
37 #include "source.h"
38 #include "group.h"
39 #include "semaphore.h"
40 #include "once.h"
41 #include "benchmark.h"
42
43 /* private.h uses #include_next and must be included last to avoid picking
44 * up installed headers. */
45 #include "queue_private.h"
46 #include "source_private.h"
47 #include "private.h"
48 #include "legacy.h"
49 /* More #includes at EOF (dependent on the contents of internal.h) ... */
50
51 /* The "_debug" library build */
52 #ifndef DISPATCH_DEBUG
53 #define DISPATCH_DEBUG 0
54 #endif
55
56
57 #include <libkern/OSCrossEndian.h>
58 #include <libkern/OSAtomic.h>
59 #include <mach/boolean.h>
60 #include <mach/clock_types.h>
61 #include <mach/clock.h>
62 #include <mach/exception.h>
63 #include <mach/mach.h>
64 #include <mach/mach_error.h>
65 #include <mach/mach_host.h>
66 #include <mach/mach_interface.h>
67 #include <mach/mach_time.h>
68 #include <mach/mach_traps.h>
69 #include <mach/message.h>
70 #include <mach/mig_errors.h>
71 #include <mach/host_info.h>
72 #include <mach/notify.h>
73 #include <malloc/malloc.h>
74 #include <sys/event.h>
75 #include <sys/mount.h>
76 #include <sys/queue.h>
77 #include <sys/stat.h>
78 #include <sys/sysctl.h>
79 #include <sys/syslimits.h>
80 #include <sys/socket.h>
81 #include <netinet/in.h>
82
83 #ifdef __BLOCKS__
84 #include <Block_private.h>
85 #include <Block.h>
86 #endif /* __BLOCKS__ */
87
88 #include <assert.h>
89 #include <errno.h>
90 #include <fcntl.h>
91 #include <search.h>
92 #include <signal.h>
93 #include <stdarg.h>
94 #include <stdbool.h>
95 #include <stdint.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include <string.h>
99 #include <syslog.h>
100 #include <unistd.h>
101
102 #define DISPATCH_NOINLINE __attribute__((noinline))
103
104 // workaround 6368156
105 #ifdef NSEC_PER_SEC
106 #undef NSEC_PER_SEC
107 #endif
108 #ifdef USEC_PER_SEC
109 #undef USEC_PER_SEC
110 #endif
111 #ifdef NSEC_PER_USEC
112 #undef NSEC_PER_USEC
113 #endif
114 #define NSEC_PER_SEC 1000000000ull
115 #define USEC_PER_SEC 1000000ull
116 #define NSEC_PER_USEC 1000ull
117
118 /* I wish we had __builtin_expect_range() */
119 #define fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
120 #define slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
121
122 void _dispatch_bug(size_t line, long val) __attribute__((__noinline__));
123 void _dispatch_abort(size_t line, long val) __attribute__((__noinline__,__noreturn__));
124 void _dispatch_log(const char *msg, ...) __attribute__((__noinline__,__format__(printf,1,2)));
125 void _dispatch_logv(const char *msg, va_list) __attribute__((__noinline__,__format__(printf,1,0)));
126
127 /*
128 * For reporting bugs within libdispatch when using the "_debug" version of the library.
129 */
130 #define dispatch_assert(e) do { \
131 if (__builtin_constant_p(e)) { \
132 char __compile_time_assert__[(bool)(e) ? 1 : -1] __attribute__((unused)); \
133 } else { \
134 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
135 if (DISPATCH_DEBUG && !_e) { \
136 _dispatch_abort(__LINE__, (long)_e); \
137 } \
138 } \
139 } while (0)
140 /* A lot of API return zero upon success and not-zero on fail. Let's capture and log the non-zero value */
141 #define dispatch_assert_zero(e) do { \
142 if (__builtin_constant_p(e)) { \
143 char __compile_time_assert__[(bool)(!(e)) ? 1 : -1] __attribute__((unused)); \
144 } else { \
145 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
146 if (DISPATCH_DEBUG && _e) { \
147 _dispatch_abort(__LINE__, (long)_e); \
148 } \
149 } \
150 } while (0)
151
152 /*
153 * For reporting bugs or impedance mismatches between libdispatch and external subsystems.
154 * These do NOT abort(), and are always compiled into the product.
155 *
156 * In particular, we wrap all system-calls with assume() macros.
157 */
158 #define dispatch_assume(e) ({ \
159 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
160 if (!_e) { \
161 if (__builtin_constant_p(e)) { \
162 char __compile_time_assert__[(e) ? 1 : -1]; \
163 (void)__compile_time_assert__; \
164 } \
165 _dispatch_bug(__LINE__, (long)_e); \
166 } \
167 _e; \
168 })
169 /* A lot of API return zero upon success and not-zero on fail. Let's capture and log the non-zero value */
170 #define dispatch_assume_zero(e) ({ \
171 typeof(e) _e = slowpath(e); /* always eval 'e' */ \
172 if (_e) { \
173 if (__builtin_constant_p(e)) { \
174 char __compile_time_assert__[(e) ? -1 : 1]; \
175 (void)__compile_time_assert__; \
176 } \
177 _dispatch_bug(__LINE__, (long)_e); \
178 } \
179 _e; \
180 })
181
182 /*
183 * For reporting bugs in clients when using the "_debug" version of the library.
184 */
185 #define dispatch_debug_assert(e, msg, args...) do { \
186 if (__builtin_constant_p(e)) { \
187 char __compile_time_assert__[(bool)(e) ? 1 : -1] __attribute__((unused)); \
188 } else { \
189 typeof(e) _e = fastpath(e); /* always eval 'e' */ \
190 if (DISPATCH_DEBUG && !_e) { \
191 _dispatch_log("%s() 0x%lx: " msg, __func__, (long)_e, ##args); \
192 abort(); \
193 } \
194 } \
195 } while (0)
196
197
198
199 #ifdef __BLOCKS__
200 dispatch_block_t _dispatch_Block_copy(dispatch_block_t block);
201 void _dispatch_call_block_and_release(void *block);
202 void _dispatch_call_block_and_release2(void *block, void *ctxt);
203 #endif /* __BLOCKS__ */
204
205 void dummy_function(void);
206 long dummy_function_r0(void);
207
208
209 /* Make sure the debug statments don't get too stale */
210 #define _dispatch_debug(x, args...) \
211 ({ \
212 if (DISPATCH_DEBUG) { \
213 _dispatch_log("libdispatch: %u\t%p\t" x, __LINE__, _dispatch_thread_self(), ##args); \
214 } \
215 })
216
217
218 #if DISPATCH_DEBUG
219 void dispatch_debug_kevents(struct kevent* kev, size_t count, const char* str);
220 #else
221 #define dispatch_debug_kevents(x, y, z)
222 #endif
223
224 uint64_t _dispatch_get_nanoseconds(void);
225
226 void _dispatch_source_drain_kevent(struct kevent *);
227
228 dispatch_source_t
229 _dispatch_source_create2(dispatch_source_t ds,
230 dispatch_source_attr_t attr,
231 void *context,
232 dispatch_source_handler_function_t handler);
233
234 void _dispatch_update_kq(const struct kevent *);
235 void _dispatch_run_timers(void);
236 // Returns howsoon with updated time value, or NULL if no timers active.
237 struct timespec *_dispatch_get_next_timer_fire(struct timespec *howsoon);
238
239 dispatch_semaphore_t _dispatch_get_thread_semaphore(void);
240 void _dispatch_put_thread_semaphore(dispatch_semaphore_t);
241
242 bool _dispatch_source_testcancel(dispatch_source_t);
243
244 uint64_t _dispatch_timeout(dispatch_time_t when);
245
246 __private_extern__ bool _dispatch_safe_fork;
247
248 __private_extern__ struct _dispatch_hw_config_s {
249 uint32_t cc_max_active;
250 uint32_t cc_max_logical;
251 uint32_t cc_max_physical;
252 } _dispatch_hw_config;
253
254 /* #includes dependent on internal.h */
255 #include "object_internal.h"
256 #include "hw_shims.h"
257 #include "os_shims.h"
258 #include "queue_internal.h"
259 #include "semaphore_internal.h"
260 #include "source_internal.h"
261
262 // MIG_REPLY_MISMATCH means either:
263 // 1) A signal handler is NOT using async-safe API. See the sigaction(2) man page for more info.
264 // 2) A hand crafted call to mach_msg*() screwed up. Use MIG.
265 #define DISPATCH_VERIFY_MIG(x) do { \
266 if ((x) == MIG_REPLY_MISMATCH) { \
267 __crashreporter_info__ = "MIG_REPLY_MISMATCH"; \
268 _dispatch_hardware_crash(); \
269 } \
270 } while (0)
271
272 #if defined(__x86_64__) || defined(__i386__)
273 // total hack to ensure that return register of a function is not trashed
274 #define DISPATCH_CRASH(x) do { \
275 asm("mov %1, %0" : "=m" (__crashreporter_info__) : "c" ("BUG IN LIBDISPATCH: " x)); \
276 _dispatch_hardware_crash(); \
277 } while (0)
278
279 #define DISPATCH_CLIENT_CRASH(x) do { \
280 asm("mov %1, %0" : "=m" (__crashreporter_info__) : "c" ("BUG IN CLIENT OF LIBDISPATCH: " x)); \
281 _dispatch_hardware_crash(); \
282 } while (0)
283
284 #else
285
286 #define DISPATCH_CRASH(x) do { \
287 __crashreporter_info__ = "BUG IN LIBDISPATCH: " x; \
288 _dispatch_hardware_crash(); \
289 } while (0)
290
291 #define DISPATCH_CLIENT_CRASH(x) do { \
292 __crashreporter_info__ = "BUG IN CLIENT OF LIBDISPATCH: " x; \
293 _dispatch_hardware_crash(); \
294 } while (0)
295
296 #endif
297
298
299 #endif /* __DISPATCH_INTERNAL__ */