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 52typedef pthread_mutex_t __libcpp_mutex_t; 53#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 54 55typedef pthread_mutex_t __libcpp_recursive_mutex_t; 56 57// Condition Variable 58typedef pthread_cond_t __libcpp_condvar_t; 59#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 60 61// Execute once 62typedef pthread_once_t __libcpp_exec_once_flag; 63#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 64 65// Thread id 66typedef pthread_t __libcpp_thread_id; 67 68// Thread 69#define _LIBCPP_NULL_THREAD 0U 70 71typedef pthread_t __libcpp_thread_t; 72 73// Thrad Local Storage 74typedef pthread_key_t __libcpp_tls_key; 75 76#define _LIBCPP_TLS_DESTRUCTOR_CC 77#else 78// Mutex 79typedef SRWLOCK __libcpp_mutex_t; 80#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT 81 82typedef CRITICAL_SECTION __libcpp_recursive_mutex_t; 83 84// Condition Variable 85typedef CONDITION_VARIABLE __libcpp_condvar_t; 86#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT 87 88// Execute Once 89typedef INIT_ONCE __libcpp_exec_once_flag; 90#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT 91 92// Thread ID 93typedef DWORD __libcpp_thread_id; 94 95// Thread 96#define _LIBCPP_NULL_THREAD 0U 97 98typedef HANDLE __libcpp_thread_t; 99 100// Thread Local Storage 101typedef DWORD __libcpp_tls_key; 102 103#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI 104#endif 105 106// Mutex 107_LIBCPP_THREAD_ABI_VISIBILITY 108int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 109 110_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 111int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 112 113_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 114bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 115 116_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 117int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 118 119_LIBCPP_THREAD_ABI_VISIBILITY 120int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 121 122_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 123int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 124 125_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 126bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 127 128_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 129int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 130 131_LIBCPP_THREAD_ABI_VISIBILITY 132int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 133 134// Condition variable 135_LIBCPP_THREAD_ABI_VISIBILITY 136int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 137 138_LIBCPP_THREAD_ABI_VISIBILITY 139int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 140 141_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 142int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 143 144_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 145int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 146 timespec *__ts); 147 148_LIBCPP_THREAD_ABI_VISIBILITY 149int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 150 151// Execute once 152_LIBCPP_THREAD_ABI_VISIBILITY 153int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 154 void (*init_routine)(void)); 155 156// Thread id 157_LIBCPP_THREAD_ABI_VISIBILITY 158bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 159 160_LIBCPP_THREAD_ABI_VISIBILITY 161bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 162 163// Thread 164_LIBCPP_THREAD_ABI_VISIBILITY 165bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 166 167_LIBCPP_THREAD_ABI_VISIBILITY 168int __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 178int __libcpp_thread_join(__libcpp_thread_t *__t); 179 180_LIBCPP_THREAD_ABI_VISIBILITY 181int __libcpp_thread_detach(__libcpp_thread_t *__t); 182 183_LIBCPP_THREAD_ABI_VISIBILITY 184void __libcpp_thread_yield(); 185 186_LIBCPP_THREAD_ABI_VISIBILITY 187void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 188 189// Thread local storage 190_LIBCPP_THREAD_ABI_VISIBILITY 191int __libcpp_tls_create(__libcpp_tls_key* __key, 192 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 193 194_LIBCPP_THREAD_ABI_VISIBILITY 195void *__libcpp_tls_get(__libcpp_tls_key __key); 196 197_LIBCPP_THREAD_ABI_VISIBILITY 198int __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 205int __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 229int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 230{ 231 return pthread_mutex_lock(__m); 232} 233 234bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 235{ 236 return pthread_mutex_trylock(__m) == 0; 237} 238 239int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 240{ 241 return pthread_mutex_unlock(__m); 242} 243 244int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 245{ 246 return pthread_mutex_destroy(__m); 247} 248 249int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 250{ 251 return pthread_mutex_lock(__m); 252} 253 254bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 255{ 256 return pthread_mutex_trylock(__m) == 0; 257} 258 259int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 260{ 261 return pthread_mutex_unlock(__m); 262} 263 264int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 265{ 266 return pthread_mutex_destroy(__m); 267} 268 269// Condition Variable 270int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 271{ 272 return pthread_cond_signal(__cv); 273} 274 275int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 276{ 277 return pthread_cond_broadcast(__cv); 278} 279 280int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 281{ 282 return pthread_cond_wait(__cv, __m); 283} 284 285int __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 291int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 292{ 293 return pthread_cond_destroy(__cv); 294} 295 296// Execute once 297int __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 304bool __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 310bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 311{ 312 return t1 < t2; 313} 314 315// Thread 316bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 317 return *__t == 0; 318} 319 320int __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 336int __libcpp_thread_join(__libcpp_thread_t *__t) 337{ 338 return pthread_join(*__t, 0); 339} 340 341int __libcpp_thread_detach(__libcpp_thread_t *__t) 342{ 343 return pthread_detach(*__t); 344} 345 346void __libcpp_thread_yield() 347{ 348 sched_yield(); 349} 350 351void __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 374int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 375{ 376 return pthread_key_create(__key, __at_exit); 377} 378 379void *__libcpp_tls_get(__libcpp_tls_key __key) 380{ 381 return pthread_getspecific(__key); 382} 383 384int __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 392int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 393{ 394 InitializeCriticalSection(__m); 395 return 0; 396} 397 398int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 399{ 400 EnterCriticalSection(__m); 401 return 0; 402} 403 404bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 405{ 406 return TryEnterCriticalSection(__m) != 0; 407} 408 409int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) 410{ 411 LeaveCriticalSection(__m); 412 return 0; 413} 414 415int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 416{ 417 DeleteCriticalSection(__m); 418 return 0; 419} 420 421int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 422{ 423 AcquireSRWLockExclusive(__m); 424 return 0; 425} 426 427bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 428{ 429 return TryAcquireSRWLockExclusive(__m) != 0; 430} 431 432int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 433{ 434 ReleaseSRWLockExclusive(__m); 435 return 0; 436} 437 438int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 439{ 440 static_cast<void>(__m); 441 return 0; 442} 443 444// Condition Variable 445int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 446{ 447 WakeConditionVariable(__cv); 448 return 0; 449} 450 451int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 452{ 453 WakeAllConditionVariable(__cv); 454 return 0; 455} 456 457int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 458{ 459 SleepConditionVariableSRW(__cv, __m, INFINITE, 0); 460 return 0; 461} 462 463int __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 { 478 auto __ec = GetLastError(); 479 return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec; 480 } 481 return 0; 482} 483 484int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 485{ 486 static_cast<void>(__cv); 487 return 0; 488} 489 490// Execute Once 491static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK 492__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, 493 PVOID *__context) 494{ 495 static_cast<void>(__init_once); 496 static_cast<void>(__context); 497 498 void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter); 499 init_routine(); 500 return TRUE; 501} 502 503int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, 504 void (*__init_routine)(void)) 505{ 506 if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk, 507 reinterpret_cast<void *>(__init_routine), NULL)) 508 return GetLastError(); 509 return 0; 510} 511 512// Thread ID 513bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, 514 __libcpp_thread_id __rhs) 515{ 516 return __lhs == __rhs; 517} 518 519bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) 520{ 521 return __lhs < __rhs; 522} 523 524// Thread 525struct __libcpp_beginthreadex_thunk_data 526{ 527 void *(*__func)(void *); 528 void *__arg; 529}; 530 531static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI 532__libcpp_beginthreadex_thunk(void *__raw_data) 533{ 534 auto *__data = 535 static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data); 536 auto *__func = __data->__func; 537 void *__arg = __data->__arg; 538 delete __data; 539 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg))); 540} 541 542bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 543 return *__t == 0; 544} 545 546int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 547 void *__arg) 548{ 549 auto *__data = new __libcpp_beginthreadex_thunk_data; 550 __data->__func = __func; 551 __data->__arg = __arg; 552 553 *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, 554 __libcpp_beginthreadex_thunk, 555 __data, 0, nullptr)); 556 557 if (*__t) 558 return 0; 559 return GetLastError(); 560} 561 562__libcpp_thread_id __libcpp_thread_get_current_id() 563{ 564 return GetCurrentThreadId(); 565} 566 567__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 568{ 569 return GetThreadId(*__t); 570} 571 572int __libcpp_thread_join(__libcpp_thread_t *__t) 573{ 574 if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) 575 return GetLastError(); 576 if (!CloseHandle(*__t)) 577 return GetLastError(); 578 return 0; 579} 580 581int __libcpp_thread_detach(__libcpp_thread_t *__t) 582{ 583 if (!CloseHandle(*__t)) 584 return GetLastError(); 585 return 0; 586} 587 588void __libcpp_thread_yield() 589{ 590 SwitchToThread(); 591} 592 593void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 594{ 595 using namespace chrono; 596 // round-up to the nearest milisecond 597 milliseconds __ms = 598 duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999)); 599 // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx) 600 Sleep(__ms.count()); 601} 602 603// Thread Local Storage 604int __libcpp_tls_create(__libcpp_tls_key* __key, 605 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) 606{ 607 *__key = FlsAlloc(__at_exit); 608 if (*__key == FLS_OUT_OF_INDEXES) 609 return GetLastError(); 610 return 0; 611} 612 613void *__libcpp_tls_get(__libcpp_tls_key __key) 614{ 615 return FlsGetValue(__key); 616} 617 618int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 619{ 620 if (!FlsSetValue(__key, __p)) 621 return GetLastError(); 622 return 0; 623} 624 625#endif // _LIBCPP_HAS_THREAD_API_PTHREAD 626 627#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 628 629_LIBCPP_END_NAMESPACE_STD 630 631#endif // !_LIBCPP_HAS_NO_THREADS 632 633#endif // _LIBCPP_THREADING_SUPPORT 634