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