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