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