]> git.saurik.com Git - apple/libdispatch.git/blob - src/shims/yield.h
libdispatch-913.1.6.tar.gz
[apple/libdispatch.git] / src / shims / yield.h
1 /*
2 * Copyright (c) 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_SHIMS_YIELD__
28 #define __DISPATCH_SHIMS_YIELD__
29
30 #pragma mark -
31 #pragma mark _dispatch_wait_until
32
33 #if DISPATCH_HW_CONFIG_UP
34 #define _dispatch_wait_until(c) ({ \
35 typeof(c) _c; \
36 int _spins = 0; \
37 for (;;) { \
38 if (likely(_c = (c))) break; \
39 _spins++; \
40 _dispatch_preemption_yield(_spins); \
41 } \
42 _c; })
43 #elif TARGET_OS_EMBEDDED
44 // <rdar://problem/15440575>
45 #ifndef DISPATCH_WAIT_SPINS
46 #define DISPATCH_WAIT_SPINS 1024
47 #endif
48 #define _dispatch_wait_until(c) ({ \
49 typeof(c) _c; \
50 int _spins = -(DISPATCH_WAIT_SPINS); \
51 for (;;) { \
52 if (likely(_c = (c))) break; \
53 if (slowpath(_spins++ >= 0)) { \
54 _dispatch_preemption_yield(_spins); \
55 } else { \
56 dispatch_hardware_pause(); \
57 } \
58 } \
59 _c; })
60 #else
61 #define _dispatch_wait_until(c) ({ \
62 typeof(c) _c; \
63 for (;;) { \
64 if (likely(_c = (c))) break; \
65 dispatch_hardware_pause(); \
66 } \
67 _c; })
68 #endif
69
70 #pragma mark -
71 #pragma mark _dispatch_contention_wait_until
72
73 #if DISPATCH_HW_CONFIG_UP
74 #define _dispatch_contention_wait_until(c) false
75 #else
76 #ifndef DISPATCH_CONTENTION_SPINS_MAX
77 #define DISPATCH_CONTENTION_SPINS_MAX (128 - 1)
78 #endif
79 #ifndef DISPATCH_CONTENTION_SPINS_MIN
80 #define DISPATCH_CONTENTION_SPINS_MIN (32 - 1)
81 #endif
82 #if TARGET_OS_EMBEDDED
83 #define _dispatch_contention_spins() \
84 ((DISPATCH_CONTENTION_SPINS_MIN) + ((DISPATCH_CONTENTION_SPINS_MAX) - \
85 (DISPATCH_CONTENTION_SPINS_MIN)) / 2)
86 #else
87 // Use randomness to prevent threads from resonating at the same
88 // frequency and permanently contending. All threads sharing the same
89 // seed value is safe with the FreeBSD rand_r implementation.
90 #define _dispatch_contention_spins() ({ \
91 static unsigned int _seed; \
92 ((unsigned int)rand_r(&_seed) & (DISPATCH_CONTENTION_SPINS_MAX)) | \
93 (DISPATCH_CONTENTION_SPINS_MIN); })
94 #endif
95 #define _dispatch_contention_wait_until(c) ({ \
96 bool _out = false; \
97 unsigned int _spins = _dispatch_contention_spins(); \
98 while (_spins--) { \
99 dispatch_hardware_pause(); \
100 if ((_out = fastpath(c))) break; \
101 }; _out; })
102 #endif
103
104 #pragma mark -
105 #pragma mark dispatch_hardware_pause
106
107 #if defined(__x86_64__) || defined(__i386__)
108 #define dispatch_hardware_pause() __asm__("pause")
109 #elif (defined(__arm__) && defined(_ARM_ARCH_7) && defined(__thumb__)) || \
110 defined(__arm64__)
111 #define dispatch_hardware_pause() __asm__("yield")
112 #define dispatch_hardware_wfe() __asm__("wfe")
113 #else
114 #define dispatch_hardware_pause() __asm__("")
115 #endif
116
117 #pragma mark -
118 #pragma mark _dispatch_preemption_yield
119
120 #if HAVE_MACH
121 #if defined(SWITCH_OPTION_OSLOCK_DEPRESS)
122 #define DISPATCH_YIELD_THREAD_SWITCH_OPTION SWITCH_OPTION_OSLOCK_DEPRESS
123 #else
124 #define DISPATCH_YIELD_THREAD_SWITCH_OPTION SWITCH_OPTION_DEPRESS
125 #endif
126 #define _dispatch_preemption_yield(n) thread_switch(MACH_PORT_NULL, \
127 DISPATCH_YIELD_THREAD_SWITCH_OPTION, (mach_msg_timeout_t)(n))
128 #define _dispatch_preemption_yield_to(th, n) thread_switch(th, \
129 DISPATCH_YIELD_THREAD_SWITCH_OPTION, (mach_msg_timeout_t)(n))
130 #else
131 #define _dispatch_preemption_yield(n) pthread_yield_np()
132 #define _dispatch_preemption_yield_to(th, n) pthread_yield_np()
133 #endif // HAVE_MACH
134
135 #pragma mark -
136 #pragma mark _dispatch_contention_usleep
137
138 #ifndef DISPATCH_CONTENTION_USLEEP_START
139 #define DISPATCH_CONTENTION_USLEEP_START 500
140 #endif
141 #ifndef DISPATCH_CONTENTION_USLEEP_MAX
142 #define DISPATCH_CONTENTION_USLEEP_MAX 100000
143 #endif
144
145 #if HAVE_MACH
146 #if defined(SWITCH_OPTION_DISPATCH_CONTENTION)
147 #define _dispatch_contention_usleep(u) thread_switch(MACH_PORT_NULL, \
148 SWITCH_OPTION_DISPATCH_CONTENTION, (u))
149 #else
150 #define _dispatch_contention_usleep(u) thread_switch(MACH_PORT_NULL, \
151 SWITCH_OPTION_WAIT, (((u)-1)/1000)+1)
152 #endif
153 #else
154 #define _dispatch_contention_usleep(u) usleep((u))
155 #endif // HAVE_MACH
156
157 #endif // __DISPATCH_SHIMS_YIELD__