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