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 56typedef pthread_mutex_t __libcpp_mutex_t; 57#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 58 59typedef pthread_mutex_t __libcpp_recursive_mutex_t; 60 61// Condition Variable 62typedef pthread_cond_t __libcpp_condvar_t; 63#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 64 65// Execute once 66typedef pthread_once_t __libcpp_exec_once_flag; 67#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 68 69// Thread id 70typedef pthread_t __libcpp_thread_id; 71 72// Thread 73#define _LIBCPP_NULL_THREAD 0U 74 75typedef pthread_t __libcpp_thread_t; 76 77// Thrad Local Storage 78typedef pthread_key_t __libcpp_tls_key; 79 80#define _LIBCPP_TLS_DESTRUCTOR_CC 81#else 82// Mutex 83typedef SRWLOCK __libcpp_mutex_t; 84#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT 85 86typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; 87 88// Condition Variable 89typedef CONDITION_VARIABLE __libcpp_condvar_t; 90#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT 91 92// Execute Once 93typedef INIT_ONCE __libcpp_exec_once_flag; 94#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT 95 96// Thread ID 97typedef DWORD __libcpp_thread_id; 98 99// Thread 100#define _LIBCPP_NULL_THREAD 0U 101 102typedef HANDLE __libcpp_thread_t; 103 104// Thread Local Storage 105typedef DWORD __libcpp_tls_key; 106 107#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI 108#endif 109 110// Mutex 111_LIBCPP_THREAD_ABI_VISIBILITY 112int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 113 114_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 115int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 116 117_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 118bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 119 120_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 121int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 122 123_LIBCPP_THREAD_ABI_VISIBILITY 124int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 125 126_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 127int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 128 129_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 130bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 131 132_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 133int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 134 135_LIBCPP_THREAD_ABI_VISIBILITY 136int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 137 138// Condition variable 139_LIBCPP_THREAD_ABI_VISIBILITY 140int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 141 142_LIBCPP_THREAD_ABI_VISIBILITY 143int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 144 145_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 146int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 147 148_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 149int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 150 timespec *__ts); 151 152_LIBCPP_THREAD_ABI_VISIBILITY 153int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 154 155// Execute once 156_LIBCPP_THREAD_ABI_VISIBILITY 157int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 158 void (*init_routine)(void)); 159 160// Thread id 161_LIBCPP_THREAD_ABI_VISIBILITY 162bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 163 164_LIBCPP_THREAD_ABI_VISIBILITY 165bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 166 167// Thread 168_LIBCPP_THREAD_ABI_VISIBILITY 169bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 170 171_LIBCPP_THREAD_ABI_VISIBILITY 172int __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 182int __libcpp_thread_join(__libcpp_thread_t *__t); 183 184_LIBCPP_THREAD_ABI_VISIBILITY 185int __libcpp_thread_detach(__libcpp_thread_t *__t); 186 187_LIBCPP_THREAD_ABI_VISIBILITY 188void __libcpp_thread_yield(); 189 190_LIBCPP_THREAD_ABI_VISIBILITY 191void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 192 193// Thread local storage 194_LIBCPP_THREAD_ABI_VISIBILITY 195int __libcpp_tls_create(__libcpp_tls_key* __key, 196 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 197 198_LIBCPP_THREAD_ABI_VISIBILITY 199void *__libcpp_tls_get(__libcpp_tls_key __key); 200 201_LIBCPP_THREAD_ABI_VISIBILITY 202int __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 209int __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 233int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 234{ 235 return pthread_mutex_lock(__m); 236} 237 238bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 239{ 240 return pthread_mutex_trylock(__m) == 0; 241} 242 243int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 244{ 245 return pthread_mutex_unlock(__m); 246} 247 248int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 249{ 250 return pthread_mutex_destroy(__m); 251} 252 253int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 254{ 255 return pthread_mutex_lock(__m); 256} 257 258bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 259{ 260 return pthread_mutex_trylock(__m) == 0; 261} 262 263int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 264{ 265 return pthread_mutex_unlock(__m); 266} 267 268int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 269{ 270 return pthread_mutex_destroy(__m); 271} 272 273// Condition Variable 274int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 275{ 276 return pthread_cond_signal(__cv); 277} 278 279int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 280{ 281 return pthread_cond_broadcast(__cv); 282} 283 284int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 285{ 286 return pthread_cond_wait(__cv, __m); 287} 288 289int __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 295int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 296{ 297 return pthread_cond_destroy(__cv); 298} 299 300// Execute once 301int __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 308bool __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 314bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 315{ 316 return t1 < t2; 317} 318 319// Thread 320bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 321 return *__t == 0; 322} 323 324int __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 340int __libcpp_thread_join(__libcpp_thread_t *__t) 341{ 342 return pthread_join(*__t, 0); 343} 344 345int __libcpp_thread_detach(__libcpp_thread_t *__t) 346{ 347 return pthread_detach(*__t); 348} 349 350void __libcpp_thread_yield() 351{ 352 sched_yield(); 353} 354 355void __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 378int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 379{ 380 return pthread_key_create(__key, __at_exit); 381} 382 383void *__libcpp_tls_get(__libcpp_tls_key __key) 384{ 385 return pthread_getspecific(__key); 386} 387 388int __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 396int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 397{ 398 InitializeCriticalSection(__m); 399 return 0; 400} 401 402int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 403{ 404 EnterCriticalSection(__m); 405 return 0; 406} 407 408bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 409{ 410 return TryEnterCriticalSection(__m) != 0; 411} 412 413int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 414{ 415 LeaveCriticalSection(__m); 416 return 0; 417} 418 419int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 420{ 421 DeleteCriticalSection(__m); 422 return 0; 423} 424 425int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 426{ 427 AcquireSRWLockExclusive(__m); 428 return 0; 429} 430 431bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 432{ 433 return TryAcquireSRWLockExclusive(__m) != 0; 434} 435 436int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 437{ 438 ReleaseSRWLockExclusive(__m); 439 return 0; 440} 441 442int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 443{ 444 static_cast<void>(__m); 445 return 0; 446} 447 448// Condition Variable 449int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 450{ 451 WakeConditionVariable(__cv); 452 return 0; 453} 454 455int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 456{ 457 WakeAllConditionVariable(__cv); 458 return 0; 459} 460 461int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 462{ 463 SleepConditionVariableSRW(__cv, __m, INFINITE, 0); 464 return 0; 465} 466 467int __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 488int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 489{ 490 static_cast<void>(__cv); 491 return 0; 492} 493 494// Execute Once 495static 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 507int __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 517bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, 518 __libcpp_thread_id __rhs) 519{ 520 return __lhs == __rhs; 521} 522 523bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) 524{ 525 return __lhs < __rhs; 526} 527 528// Thread 529struct __libcpp_beginthreadex_thunk_data 530{ 531 void *(*__func)(void *); 532 void *__arg; 533}; 534 535static 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 546bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 547 return *__t == 0; 548} 549 550int __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 576int __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 585int __libcpp_thread_detach(__libcpp_thread_t *__t) 586{ 587 if (!CloseHandle(*__t)) 588 return GetLastError(); 589 return 0; 590} 591 592void __libcpp_thread_yield() 593{ 594 SwitchToThread(); 595} 596 597void __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 608int __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 617void *__libcpp_tls_get(__libcpp_tls_key __key) 618{ 619 return FlsGetValue(__key); 620} 621 622int __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