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 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32) 30 #include <windows.h> 31 #include <process.h> 32 #include <fibersapi.h> 33 #endif 34 35 _LIBCPP_PUSH_MACROS 36 #include <__undef_macros> 37 38 39 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 40 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) 41 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 42 #else 43 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 44 #endif 45 46 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 47 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 48 #else 49 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 50 #endif 51 52 _LIBCPP_BEGIN_NAMESPACE_STD 53 54 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 55 // Mutex 56 typedef pthread_mutex_t __libcpp_mutex_t; 57 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 58 59 typedef pthread_mutex_t __libcpp_recursive_mutex_t; 60 61 // Condition Variable 62 typedef pthread_cond_t __libcpp_condvar_t; 63 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 64 65 // Execute once 66 typedef pthread_once_t __libcpp_exec_once_flag; 67 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 68 69 // Thread id 70 typedef pthread_t __libcpp_thread_id; 71 72 // Thread 73 #define _LIBCPP_NULL_THREAD 0U 74 75 typedef pthread_t __libcpp_thread_t; 76 77 // Thrad Local Storage 78 typedef pthread_key_t __libcpp_tls_key; 79 80 #define _LIBCPP_TLS_DESTRUCTOR_CC 81 #else 82 // Mutex 83 typedef SRWLOCK __libcpp_mutex_t; 84 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT 85 86 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; 87 88 // Condition Variable 89 typedef CONDITION_VARIABLE __libcpp_condvar_t; 90 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT 91 92 // Execute Once 93 typedef INIT_ONCE __libcpp_exec_once_flag; 94 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT 95 96 // Thread ID 97 typedef DWORD __libcpp_thread_id; 98 99 // Thread 100 #define _LIBCPP_NULL_THREAD 0U 101 102 typedef HANDLE __libcpp_thread_t; 103 104 // Thread Local Storage 105 typedef DWORD __libcpp_tls_key; 106 107 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI 108 #endif 109 110 // Mutex 111 _LIBCPP_THREAD_ABI_VISIBILITY 112 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 113 114 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 115 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 116 117 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 118 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 119 120 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 121 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 122 123 _LIBCPP_THREAD_ABI_VISIBILITY 124 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 125 126 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 127 int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 128 129 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 130 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 131 132 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 133 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 134 135 _LIBCPP_THREAD_ABI_VISIBILITY 136 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 137 138 // Condition variable 139 _LIBCPP_THREAD_ABI_VISIBILITY 140 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 141 142 _LIBCPP_THREAD_ABI_VISIBILITY 143 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 144 145 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 146 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 147 148 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 149 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 150 timespec *__ts); 151 152 _LIBCPP_THREAD_ABI_VISIBILITY 153 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 154 155 // Execute once 156 _LIBCPP_THREAD_ABI_VISIBILITY 157 int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 158 void (*init_routine)(void)); 159 160 // Thread id 161 _LIBCPP_THREAD_ABI_VISIBILITY 162 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 163 164 _LIBCPP_THREAD_ABI_VISIBILITY 165 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 166 167 // Thread 168 _LIBCPP_THREAD_ABI_VISIBILITY 169 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 170 171 _LIBCPP_THREAD_ABI_VISIBILITY 172 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 173 void *__arg); 174 175 _LIBCPP_THREAD_ABI_VISIBILITY 176 __libcpp_thread_id __libcpp_thread_get_current_id(); 177 178 _LIBCPP_THREAD_ABI_VISIBILITY 179 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 180 181 _LIBCPP_THREAD_ABI_VISIBILITY 182 int __libcpp_thread_join(__libcpp_thread_t *__t); 183 184 _LIBCPP_THREAD_ABI_VISIBILITY 185 int __libcpp_thread_detach(__libcpp_thread_t *__t); 186 187 _LIBCPP_THREAD_ABI_VISIBILITY 188 void __libcpp_thread_yield(); 189 190 _LIBCPP_THREAD_ABI_VISIBILITY 191 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 192 193 // Thread local storage 194 _LIBCPP_THREAD_ABI_VISIBILITY 195 int __libcpp_tls_create(__libcpp_tls_key* __key, 196 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 197 198 _LIBCPP_THREAD_ABI_VISIBILITY 199 void *__libcpp_tls_get(__libcpp_tls_key __key); 200 201 _LIBCPP_THREAD_ABI_VISIBILITY 202 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 203 204 #if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 205 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) 206 207 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 208 209 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 210 { 211 pthread_mutexattr_t attr; 212 int __ec = pthread_mutexattr_init(&attr); 213 if (__ec) 214 return __ec; 215 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 216 if (__ec) { 217 pthread_mutexattr_destroy(&attr); 218 return __ec; 219 } 220 __ec = pthread_mutex_init(__m, &attr); 221 if (__ec) { 222 pthread_mutexattr_destroy(&attr); 223 return __ec; 224 } 225 __ec = pthread_mutexattr_destroy(&attr); 226 if (__ec) { 227 pthread_mutex_destroy(__m); 228 return __ec; 229 } 230 return 0; 231 } 232 233 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 234 { 235 return pthread_mutex_lock(__m); 236 } 237 238 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 239 { 240 return pthread_mutex_trylock(__m) == 0; 241 } 242 243 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 244 { 245 return pthread_mutex_unlock(__m); 246 } 247 248 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 249 { 250 return pthread_mutex_destroy(__m); 251 } 252 253 int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 254 { 255 return pthread_mutex_lock(__m); 256 } 257 258 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 259 { 260 return pthread_mutex_trylock(__m) == 0; 261 } 262 263 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 264 { 265 return pthread_mutex_unlock(__m); 266 } 267 268 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 269 { 270 return pthread_mutex_destroy(__m); 271 } 272 273 // Condition Variable 274 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 275 { 276 return pthread_cond_signal(__cv); 277 } 278 279 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 280 { 281 return pthread_cond_broadcast(__cv); 282 } 283 284 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 285 { 286 return pthread_cond_wait(__cv, __m); 287 } 288 289 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 290 timespec *__ts) 291 { 292 return pthread_cond_timedwait(__cv, __m, __ts); 293 } 294 295 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 296 { 297 return pthread_cond_destroy(__cv); 298 } 299 300 // Execute once 301 int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 302 void (*init_routine)(void)) { 303 return pthread_once(flag, init_routine); 304 } 305 306 // Thread id 307 // Returns non-zero if the thread ids are equal, otherwise 0 308 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 309 { 310 return pthread_equal(t1, t2) != 0; 311 } 312 313 // Returns non-zero if t1 < t2, otherwise 0 314 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 315 { 316 return t1 < t2; 317 } 318 319 // Thread 320 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 321 return *__t == 0; 322 } 323 324 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 325 void *__arg) 326 { 327 return pthread_create(__t, 0, __func, __arg); 328 } 329 330 __libcpp_thread_id __libcpp_thread_get_current_id() 331 { 332 return pthread_self(); 333 } 334 335 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 336 { 337 return *__t; 338 } 339 340 int __libcpp_thread_join(__libcpp_thread_t *__t) 341 { 342 return pthread_join(*__t, 0); 343 } 344 345 int __libcpp_thread_detach(__libcpp_thread_t *__t) 346 { 347 return pthread_detach(*__t); 348 } 349 350 void __libcpp_thread_yield() 351 { 352 sched_yield(); 353 } 354 355 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 356 { 357 using namespace chrono; 358 seconds __s = duration_cast<seconds>(__ns); 359 timespec __ts; 360 typedef decltype(__ts.tv_sec) ts_sec; 361 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max(); 362 363 if (__s.count() < __ts_sec_max) 364 { 365 __ts.tv_sec = static_cast<ts_sec>(__s.count()); 366 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 367 } 368 else 369 { 370 __ts.tv_sec = __ts_sec_max; 371 __ts.tv_nsec = 999999999; // (10^9 - 1) 372 } 373 374 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 375 } 376 377 // Thread local storage 378 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 379 { 380 return pthread_key_create(__key, __at_exit); 381 } 382 383 void *__libcpp_tls_get(__libcpp_tls_key __key) 384 { 385 return pthread_getspecific(__key); 386 } 387 388 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 389 { 390 return pthread_setspecific(__key, __p); 391 } 392 393 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32) 394 395 // Mutex 396 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 397 { 398 InitializeCriticalSection(__m); 399 return 0; 400 } 401 402 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 403 { 404 EnterCriticalSection(__m); 405 return 0; 406 } 407 408 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 409 { 410 return TryEnterCriticalSection(__m) != 0; 411 } 412 413 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 414 { 415 LeaveCriticalSection(__m); 416 return 0; 417 } 418 419 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 420 { 421 DeleteCriticalSection(__m); 422 return 0; 423 } 424 425 int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 426 { 427 AcquireSRWLockExclusive(__m); 428 return 0; 429 } 430 431 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 432 { 433 return TryAcquireSRWLockExclusive(__m) != 0; 434 } 435 436 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 437 { 438 ReleaseSRWLockExclusive(__m); 439 return 0; 440 } 441 442 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 443 { 444 static_cast<void>(__m); 445 return 0; 446 } 447 448 // Condition Variable 449 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 450 { 451 WakeConditionVariable(__cv); 452 return 0; 453 } 454 455 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 456 { 457 WakeAllConditionVariable(__cv); 458 return 0; 459 } 460 461 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 462 { 463 SleepConditionVariableSRW(__cv, __m, INFINITE, 0); 464 return 0; 465 } 466 467 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 468 timespec *__ts) 469 { 470 using namespace _VSTD::chrono; 471 472 auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); 473 auto abstime = 474 system_clock::time_point(duration_cast<system_clock::duration>(duration)); 475 auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now()); 476 477 if (!SleepConditionVariableSRW(__cv, __m, 478 timeout_ms.count() > 0 ? timeout_ms.count() 479 : 0, 480 0)) 481 { 482 auto __ec = GetLastError(); 483 return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec; 484 } 485 return 0; 486 } 487 488 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 489 { 490 static_cast<void>(__cv); 491 return 0; 492 } 493 494 // Execute Once 495 static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK 496 __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, 497 PVOID *__context) 498 { 499 static_cast<void>(__init_once); 500 static_cast<void>(__context); 501 502 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter); 503 init_routine(); 504 return TRUE; 505 } 506 507 int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 508 void (*__init_routine)(void)) 509 { 510 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk, 511 reinterpret_cast<void *>(__init_routine), NULL)) 512 return GetLastError(); 513 return 0; 514 } 515 516 // Thread ID 517 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, 518 __libcpp_thread_id __rhs) 519 { 520 return __lhs == __rhs; 521 } 522 523 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) 524 { 525 return __lhs < __rhs; 526 } 527 528 // Thread 529 struct __libcpp_beginthreadex_thunk_data 530 { 531 void *(*__func)(void *); 532 void *__arg; 533 }; 534 535 static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI 536 __libcpp_beginthreadex_thunk(void *__raw_data) 537 { 538 auto *__data = 539 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data); 540 auto *__func = __data->__func; 541 void *__arg = __data->__arg; 542 delete __data; 543 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg))); 544 } 545 546 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 547 return *__t == 0; 548 } 549 550 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 551 void *__arg) 552 { 553 auto *__data = new __libcpp_beginthreadex_thunk_data; 554 __data->__func = __func; 555 __data->__arg = __arg; 556 557 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, 558 __libcpp_beginthreadex_thunk, 559 __data, 0, nullptr)); 560 561 if (*__t) 562 return 0; 563 return GetLastError(); 564 } 565 566 __libcpp_thread_id __libcpp_thread_get_current_id() 567 { 568 return GetCurrentThreadId(); 569 } 570 571 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 572 { 573 return GetThreadId(*__t); 574 } 575 576 int __libcpp_thread_join(__libcpp_thread_t *__t) 577 { 578 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) 579 return GetLastError(); 580 if (!CloseHandle(*__t)) 581 return GetLastError(); 582 return 0; 583 } 584 585 int __libcpp_thread_detach(__libcpp_thread_t *__t) 586 { 587 if (!CloseHandle(*__t)) 588 return GetLastError(); 589 return 0; 590 } 591 592 void __libcpp_thread_yield() 593 { 594 SwitchToThread(); 595 } 596 597 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 598 { 599 using namespace chrono; 600 // round-up to the nearest milisecond 601 milliseconds __ms = 602 duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999)); 603 // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx) 604 Sleep(__ms.count()); 605 } 606 607 // Thread Local Storage 608 int __libcpp_tls_create(__libcpp_tls_key* __key, 609 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) 610 { 611 *__key = FlsAlloc(__at_exit); 612 if (*__key == FLS_OUT_OF_INDEXES) 613 return GetLastError(); 614 return 0; 615 } 616 617 void *__libcpp_tls_get(__libcpp_tls_key __key) 618 { 619 return FlsGetValue(__key); 620 } 621 622 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 623 { 624 if (!FlsSetValue(__key, __p)) 625 return GetLastError(); 626 return 0; 627 } 628 629 #endif // _LIBCPP_HAS_THREAD_API_PTHREAD 630 631 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 632 633 _LIBCPP_END_NAMESPACE_STD 634 635 _LIBCPP_POP_MACROS 636 637 #endif // !_LIBCPP_HAS_NO_THREADS 638 639 #endif // _LIBCPP_THREADING_SUPPORT 640