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