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 return GetLastError(); 478 return 0; 479} 480 481int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 482{ 483 static_cast<void>(__cv); 484 return 0; 485} 486 487// Execute Once 488static 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 500int __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 510bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, 511 __libcpp_thread_id __rhs) 512{ 513 return __lhs == __rhs; 514} 515 516bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) 517{ 518 return __lhs < __rhs; 519} 520 521// Thread 522struct __libcpp_beginthreadex_thunk_data 523{ 524 void *(*__func)(void *); 525 void *__arg; 526}; 527 528static 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 539bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 540 return *__t == 0; 541} 542 543int __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 569int __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 578int __libcpp_thread_detach(__libcpp_thread_t *__t) 579{ 580 if (!CloseHandle(*__t)) 581 return GetLastError(); 582 return 0; 583} 584 585void __libcpp_thread_yield() 586{ 587 SwitchToThread(); 588} 589 590void __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 601int __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 610void *__libcpp_tls_get(__libcpp_tls_key __key) 611{ 612 return FlsGetValue(__key); 613} 614 615int __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