]> git.saurik.com Git - apple/libdispatch.git/blob - src/shims.h
libdispatch-913.1.6.tar.gz
[apple/libdispatch.git] / src / shims.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_OS_SHIMS__
28 #define __DISPATCH_OS_SHIMS__
29
30 #include <pthread.h>
31 #ifdef __linux__
32 #include "shims/linux_stubs.h"
33 #endif
34
35 #ifdef __ANDROID__
36 #include "shims/android_stubs.h"
37 #endif
38
39 #include "shims/hw_config.h"
40 #include "shims/priority.h"
41
42 #if HAVE_PTHREAD_WORKQUEUES
43 #if __has_include(<pthread/workqueue_private.h>)
44 #include <pthread/workqueue_private.h>
45 #else
46 #include <pthread_workqueue.h>
47 #endif
48 #ifndef WORKQ_FEATURE_MAINTENANCE
49 #define WORKQ_FEATURE_MAINTENANCE 0x10
50 #endif
51 #endif // HAVE_PTHREAD_WORKQUEUES
52
53 #if DISPATCH_USE_INTERNAL_WORKQUEUE
54 #include "event/workqueue_internal.h"
55 #endif
56
57 #if HAVE_PTHREAD_NP_H
58 #include <pthread_np.h>
59 #endif
60
61 #if __has_include(<pthread/private.h>)
62 #include <pthread/private.h>
63 #endif
64
65 #if !HAVE_DECL_FD_COPY
66 #define FD_COPY(f, t) (void)(*(t) = *(f))
67 #endif
68
69 #if TARGET_OS_WIN32
70 #define bzero(ptr,len) memset((ptr), 0, (len))
71 #define snprintf _snprintf
72
73 inline size_t strlcpy(char *dst, const char *src, size_t size) {
74 int res = strlen(dst) + strlen(src) + 1;
75 if (size > 0) {
76 size_t n = size - 1;
77 strncpy(dst, src, n);
78 dst[n] = 0;
79 }
80 return res;
81 }
82 #endif // TARGET_OS_WIN32
83
84 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20140716
85 static inline int
86 _pthread_workqueue_override_start_direct(mach_port_t thread,
87 pthread_priority_t priority)
88 {
89 (void)thread; (void)priority;
90 return 0;
91 }
92 #endif // PTHREAD_WORKQUEUE_SPI_VERSION < 20140716
93
94 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20150319
95 static inline int
96 _pthread_workqueue_override_start_direct_check_owner(mach_port_t thread,
97 pthread_priority_t priority, mach_port_t *ulock_addr)
98 {
99 (void)ulock_addr;
100 return _pthread_workqueue_override_start_direct(thread, priority);
101 }
102 #endif // PTHREAD_WORKQUEUE_SPI_VERSION < 20150319
103
104 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20140707
105 static inline int
106 _pthread_override_qos_class_start_direct(mach_port_t thread,
107 pthread_priority_t priority)
108 {
109 (void)thread; (void)priority;
110 return 0;
111 }
112
113 static inline int
114 _pthread_override_qos_class_end_direct(mach_port_t thread)
115 {
116 (void)thread;
117 return 0;
118 }
119 #endif // PTHREAD_WORKQUEUE_SPI_VERSION < 20140707
120
121 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20150325
122 static inline int
123 _pthread_qos_override_start_direct(mach_port_t thread,
124 pthread_priority_t priority, void *resource)
125 {
126 (void)resource;
127 return _pthread_override_qos_class_start_direct(thread, priority);
128 }
129
130 static inline int
131 _pthread_qos_override_end_direct(mach_port_t thread, void *resource)
132 {
133 (void)resource;
134 return _pthread_override_qos_class_end_direct(thread);
135 }
136 #endif // PTHREAD_WORKQUEUE_SPI_VERSION < 20150325
137
138 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20160427
139 #define _PTHREAD_SET_SELF_WQ_KEVENT_UNBIND 0
140 #endif
141
142 #if PTHREAD_WORKQUEUE_SPI_VERSION < 20160427
143 static inline bool
144 _pthread_workqueue_should_narrow(pthread_priority_t priority)
145 {
146 (void)priority;
147 return false;
148 }
149 #endif
150
151 #if HAVE_PTHREAD_QOS_H && __has_include(<pthread/qos_private.h>) && \
152 defined(PTHREAD_MAX_PARALLELISM_PHYSICAL) && \
153 DISPATCH_HAVE_HW_CONFIG_COMMPAGE && \
154 DISPATCH_MIN_REQUIRED_OSX_AT_LEAST(109900)
155 #define DISPATCH_USE_PTHREAD_QOS_MAX_PARALLELISM 1
156 #define DISPATCH_MAX_PARALLELISM_PHYSICAL PTHREAD_MAX_PARALLELISM_PHYSICAL
157 #else
158 #define DISPATCH_MAX_PARALLELISM_PHYSICAL 0x1
159 #endif
160 #define DISPATCH_MAX_PARALLELISM_ACTIVE 0x2
161 _Static_assert(!(DISPATCH_MAX_PARALLELISM_PHYSICAL &
162 DISPATCH_MAX_PARALLELISM_ACTIVE), "Overlapping parallelism flags");
163
164 DISPATCH_ALWAYS_INLINE
165 static inline uint32_t
166 _dispatch_qos_max_parallelism(dispatch_qos_t qos, unsigned long flags)
167 {
168 uint32_t p;
169 int r = 0;
170
171 if (qos) {
172 #if DISPATCH_USE_PTHREAD_QOS_MAX_PARALLELISM
173 r = pthread_qos_max_parallelism(_dispatch_qos_to_qos_class(qos),
174 flags & PTHREAD_MAX_PARALLELISM_PHYSICAL);
175 #endif
176 }
177 if (likely(r > 0)) {
178 p = (uint32_t)r;
179 } else {
180 p = (flags & DISPATCH_MAX_PARALLELISM_PHYSICAL) ?
181 dispatch_hw_config(physical_cpus) :
182 dispatch_hw_config(logical_cpus);
183 }
184 if (flags & DISPATCH_MAX_PARALLELISM_ACTIVE) {
185 uint32_t active_cpus = dispatch_hw_config(active_cpus);
186 if ((flags & DISPATCH_MAX_PARALLELISM_PHYSICAL) &&
187 active_cpus < dispatch_hw_config(logical_cpus)) {
188 active_cpus /= dispatch_hw_config(logical_cpus) /
189 dispatch_hw_config(physical_cpus);
190 }
191 if (active_cpus < p) p = active_cpus;
192 }
193 return p;
194 }
195
196 #if !HAVE_NORETURN_BUILTIN_TRAP
197 /*
198 * XXXRW: Work-around for possible clang bug in which __builtin_trap() is not
199 * marked noreturn, leading to a build error as dispatch_main() *is* marked
200 * noreturn. Mask by marking __builtin_trap() as noreturn locally.
201 */
202 DISPATCH_NORETURN
203 void __builtin_trap(void);
204 #endif
205
206 #if DISPATCH_HW_CONFIG_UP
207 #define OS_ATOMIC_UP 1
208 #else
209 #define OS_ATOMIC_UP 0
210 #endif
211
212
213 #ifndef __OS_INTERNAL_ATOMIC__
214 #include "shims/atomic.h"
215 #endif
216 #define DISPATCH_ATOMIC64_ALIGN __attribute__((aligned(8)))
217
218 #include "shims/atomic_sfb.h"
219 #include "shims/tsd.h"
220 #include "shims/yield.h"
221 #include "shims/lock.h"
222
223 #include "shims/perfmon.h"
224
225 #include "shims/getprogname.h"
226 #include "shims/time.h"
227
228 #if __has_include(<os/overflow.h>)
229 #include <os/overflow.h>
230 #elif __has_builtin(__builtin_add_overflow)
231 #define os_add_overflow(a, b, c) __builtin_add_overflow(a, b, c)
232 #define os_sub_overflow(a, b, c) __builtin_sub_overflow(a, b, c)
233 #define os_mul_overflow(a, b, c) __builtin_mul_overflow(a, b, c)
234 #else
235 #error unsupported compiler
236 #endif
237
238 #ifndef os_mul_and_add_overflow
239 #define os_mul_and_add_overflow(a, x, b, res) __extension__({ \
240 __typeof(*(res)) _tmp; \
241 bool _s, _t; \
242 _s = os_mul_overflow((a), (x), &_tmp); \
243 _t = os_add_overflow((b), _tmp, (res)); \
244 _s | _t; \
245 })
246 #endif
247
248
249 #if __has_feature(c_static_assert)
250 #define __dispatch_is_array(x) \
251 _Static_assert(!__builtin_types_compatible_p(typeof((x)[0]) *, typeof(x)), \
252 #x " isn't an array")
253 #define countof(x) \
254 ({ __dispatch_is_array(x); sizeof(x) / sizeof((x)[0]); })
255 #else
256 #define countof(x) (sizeof(x) / sizeof(x[0]))
257 #endif
258
259 DISPATCH_ALWAYS_INLINE
260 static inline void *
261 _dispatch_mempcpy(void *ptr, const void *data, size_t len)
262 {
263 memcpy(ptr, data, len);
264 return (char *)ptr + len;
265 }
266 #define _dispatch_memappend(ptr, e) \
267 _dispatch_mempcpy(ptr, e, sizeof(*(e)))
268
269 #ifdef __APPLE__
270 // Clear the stack before calling long-running thread-handler functions that
271 // never return (and don't take arguments), to facilitate leak detection and
272 // provide cleaner backtraces. <rdar://problem/9050566>
273 #define _dispatch_clear_stack(s) do { \
274 void *a[(s)/sizeof(void*) ? (s)/sizeof(void*) : 1]; \
275 a[0] = pthread_get_stackaddr_np(pthread_self()); \
276 void* volatile const p = (void*)&a[1]; /* <rdar://32604885> */ \
277 bzero((void*)p, (size_t)(a[0] - (void*)&a[1])); \
278 } while (0)
279 #else
280 #define _dispatch_clear_stack(s)
281 #endif
282
283 #endif