1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is dual licensed under the MIT and the University of Illinois Open 7 // Source Licenses. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #ifndef _LIBCPP_THREADING_SUPPORT 12 #define _LIBCPP_THREADING_SUPPORT 13 14 #include <__config> 15 #include <chrono> 16 #include <errno.h> 17 18 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 19 #pragma GCC system_header 20 #endif 21 22 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 23 # include <__external_threading> 24 #elif !defined(_LIBCPP_HAS_NO_THREADS) 25 26 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 27 # include <pthread.h> 28 # include <sched.h> 29 #endif 30 31 _LIBCPP_PUSH_MACROS 32 #include <__undef_macros> 33 34 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 35 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ 36 defined(_LIBCPP_HAS_THREAD_API_WIN32) 37 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 38 #else 39 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 40 #endif 41 42 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 43 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 44 #else 45 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 46 #endif 47 48 _LIBCPP_BEGIN_NAMESPACE_STD 49 50 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 51 // Mutex 52 typedef pthread_mutex_t __libcpp_mutex_t; 53 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 54 55 typedef pthread_mutex_t __libcpp_recursive_mutex_t; 56 57 // Condition Variable 58 typedef pthread_cond_t __libcpp_condvar_t; 59 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 60 61 // Execute once 62 typedef pthread_once_t __libcpp_exec_once_flag; 63 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 64 65 // Thread id 66 typedef pthread_t __libcpp_thread_id; 67 68 // Thread 69 #define _LIBCPP_NULL_THREAD 0U 70 71 typedef pthread_t __libcpp_thread_t; 72 73 // Thread Local Storage 74 typedef pthread_key_t __libcpp_tls_key; 75 76 #define _LIBCPP_TLS_DESTRUCTOR_CC 77 #else 78 // Mutex 79 typedef void* __libcpp_mutex_t; 80 #define _LIBCPP_MUTEX_INITIALIZER 0 81 82 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 83 typedef void* __libcpp_recursive_mutex_t[6]; 84 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 85 typedef void* __libcpp_recursive_mutex_t[5]; 86 #else 87 # error Unsupported architecture 88 #endif 89 90 // Condition Variable 91 typedef void* __libcpp_condvar_t; 92 #define _LIBCPP_CONDVAR_INITIALIZER 0 93 94 // Execute Once 95 typedef void* __libcpp_exec_once_flag; 96 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0 97 98 // Thread ID 99 typedef long __libcpp_thread_id; 100 101 // Thread 102 #define _LIBCPP_NULL_THREAD 0U 103 104 typedef void* __libcpp_thread_t; 105 106 // Thread Local Storage 107 typedef long __libcpp_tls_key; 108 109 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 110 #endif 111 112 // Mutex 113 _LIBCPP_THREAD_ABI_VISIBILITY 114 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 115 116 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 117 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 118 119 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 120 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 121 122 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 123 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 124 125 _LIBCPP_THREAD_ABI_VISIBILITY 126 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 127 128 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 129 int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 130 131 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 132 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 133 134 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 135 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 136 137 _LIBCPP_THREAD_ABI_VISIBILITY 138 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 139 140 // Condition variable 141 _LIBCPP_THREAD_ABI_VISIBILITY 142 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 143 144 _LIBCPP_THREAD_ABI_VISIBILITY 145 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 146 147 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 148 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 149 150 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 151 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 152 timespec *__ts); 153 154 _LIBCPP_THREAD_ABI_VISIBILITY 155 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 156 157 // Execute once 158 _LIBCPP_THREAD_ABI_VISIBILITY 159 int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 160 void (*init_routine)(void)); 161 162 // Thread id 163 _LIBCPP_THREAD_ABI_VISIBILITY 164 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 165 166 _LIBCPP_THREAD_ABI_VISIBILITY 167 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 168 169 // Thread 170 _LIBCPP_THREAD_ABI_VISIBILITY 171 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 172 173 _LIBCPP_THREAD_ABI_VISIBILITY 174 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 175 void *__arg); 176 177 _LIBCPP_THREAD_ABI_VISIBILITY 178 __libcpp_thread_id __libcpp_thread_get_current_id(); 179 180 _LIBCPP_THREAD_ABI_VISIBILITY 181 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 182 183 _LIBCPP_THREAD_ABI_VISIBILITY 184 int __libcpp_thread_join(__libcpp_thread_t *__t); 185 186 _LIBCPP_THREAD_ABI_VISIBILITY 187 int __libcpp_thread_detach(__libcpp_thread_t *__t); 188 189 _LIBCPP_THREAD_ABI_VISIBILITY 190 void __libcpp_thread_yield(); 191 192 _LIBCPP_THREAD_ABI_VISIBILITY 193 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 194 195 // Thread local storage 196 _LIBCPP_THREAD_ABI_VISIBILITY 197 int __libcpp_tls_create(__libcpp_tls_key* __key, 198 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 199 200 _LIBCPP_THREAD_ABI_VISIBILITY 201 void *__libcpp_tls_get(__libcpp_tls_key __key); 202 203 _LIBCPP_THREAD_ABI_VISIBILITY 204 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 205 206 #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 207 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ 208 defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 209 210 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 211 { 212 pthread_mutexattr_t attr; 213 int __ec = pthread_mutexattr_init(&attr); 214 if (__ec) 215 return __ec; 216 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 217 if (__ec) { 218 pthread_mutexattr_destroy(&attr); 219 return __ec; 220 } 221 __ec = pthread_mutex_init(__m, &attr); 222 if (__ec) { 223 pthread_mutexattr_destroy(&attr); 224 return __ec; 225 } 226 __ec = pthread_mutexattr_destroy(&attr); 227 if (__ec) { 228 pthread_mutex_destroy(__m); 229 return __ec; 230 } 231 return 0; 232 } 233 234 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 235 { 236 return pthread_mutex_lock(__m); 237 } 238 239 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 240 { 241 return pthread_mutex_trylock(__m) == 0; 242 } 243 244 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 245 { 246 return pthread_mutex_unlock(__m); 247 } 248 249 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 250 { 251 return pthread_mutex_destroy(__m); 252 } 253 254 int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 255 { 256 return pthread_mutex_lock(__m); 257 } 258 259 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 260 { 261 return pthread_mutex_trylock(__m) == 0; 262 } 263 264 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 265 { 266 return pthread_mutex_unlock(__m); 267 } 268 269 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 270 { 271 return pthread_mutex_destroy(__m); 272 } 273 274 // Condition Variable 275 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 276 { 277 return pthread_cond_signal(__cv); 278 } 279 280 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 281 { 282 return pthread_cond_broadcast(__cv); 283 } 284 285 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 286 { 287 return pthread_cond_wait(__cv, __m); 288 } 289 290 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 291 timespec *__ts) 292 { 293 return pthread_cond_timedwait(__cv, __m, __ts); 294 } 295 296 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 297 { 298 return pthread_cond_destroy(__cv); 299 } 300 301 // Execute once 302 int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 303 void (*init_routine)(void)) { 304 return pthread_once(flag, init_routine); 305 } 306 307 // Thread id 308 // Returns non-zero if the thread ids are equal, otherwise 0 309 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 310 { 311 return pthread_equal(t1, t2) != 0; 312 } 313 314 // Returns non-zero if t1 < t2, otherwise 0 315 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 316 { 317 return t1 < t2; 318 } 319 320 // Thread 321 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 322 return *__t == 0; 323 } 324 325 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 326 void *__arg) 327 { 328 return pthread_create(__t, 0, __func, __arg); 329 } 330 331 __libcpp_thread_id __libcpp_thread_get_current_id() 332 { 333 return pthread_self(); 334 } 335 336 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 337 { 338 return *__t; 339 } 340 341 int __libcpp_thread_join(__libcpp_thread_t *__t) 342 { 343 return pthread_join(*__t, 0); 344 } 345 346 int __libcpp_thread_detach(__libcpp_thread_t *__t) 347 { 348 return pthread_detach(*__t); 349 } 350 351 void __libcpp_thread_yield() 352 { 353 sched_yield(); 354 } 355 356 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 357 { 358 using namespace chrono; 359 seconds __s = duration_cast<seconds>(__ns); 360 timespec __ts; 361 typedef decltype(__ts.tv_sec) ts_sec; 362 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max(); 363 364 if (__s.count() < __ts_sec_max) 365 { 366 __ts.tv_sec = static_cast<ts_sec>(__s.count()); 367 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 368 } 369 else 370 { 371 __ts.tv_sec = __ts_sec_max; 372 __ts.tv_nsec = 999999999; // (10^9 - 1) 373 } 374 375 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 376 } 377 378 // Thread local storage 379 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 380 { 381 return pthread_key_create(__key, __at_exit); 382 } 383 384 void *__libcpp_tls_get(__libcpp_tls_key __key) 385 { 386 return pthread_getspecific(__key); 387 } 388 389 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 390 { 391 return pthread_setspecific(__key, __p); 392 } 393 394 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 395 396 _LIBCPP_END_NAMESPACE_STD 397 398 _LIBCPP_POP_MACROS 399 400 #endif // !_LIBCPP_HAS_NO_THREADS 401 402 #endif // _LIBCPP_THREADING_SUPPORT 403