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#endif 30 31_LIBCPP_PUSH_MACROS 32#include <__undef_macros> 33 34#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) 35#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) 36#else 37#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 38#endif 39 40_LIBCPP_BEGIN_NAMESPACE_STD 41 42#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 43 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) 44 45#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 46 47#elif defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 48 49#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 50 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 79#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 80 81// Mutex 82typedef void* __libcpp_mutex_t; 83#define _LIBCPP_MUTEX_INITIALIZER 0 84 85#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 86typedef void* __libcpp_recursive_mutex_t[6]; 87#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 88typedef void* __libcpp_recursive_mutex_t[5]; 89#else 90# error Unsupported architecture 91#endif 92 93// Condition Variable 94typedef void* __libcpp_condvar_t; 95#define _LIBCPP_CONDVAR_INITIALIZER 0 96 97// Execute Once 98typedef void* __libcpp_exec_once_flag; 99#define _LIBCPP_EXEC_ONCE_INITIALIZER 0 100 101// Thread ID 102typedef long __libcpp_thread_id; 103 104// Thread 105#define _LIBCPP_NULL_THREAD 0U 106 107typedef void* __libcpp_thread_t; 108 109// Thread Local Storage 110typedef long __libcpp_tls_key; 111 112#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 113#endif 114 115// Mutex 116_LIBCPP_THREAD_ABI_VISIBILITY 117int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 118 119_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 120int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 121 122_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 123bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 124 125_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 126int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 127 128_LIBCPP_THREAD_ABI_VISIBILITY 129int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 130 131_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 132int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 133 134_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 135bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 136 137_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 138int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 139 140_LIBCPP_THREAD_ABI_VISIBILITY 141int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 142 143// Condition variable 144_LIBCPP_THREAD_ABI_VISIBILITY 145int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 146 147_LIBCPP_THREAD_ABI_VISIBILITY 148int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 149 150_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 151int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 152 153_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 154int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 155 timespec *__ts); 156 157_LIBCPP_THREAD_ABI_VISIBILITY 158int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 159 160// Execute once 161_LIBCPP_THREAD_ABI_VISIBILITY 162int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 163 void (*init_routine)(void)); 164 165// Thread id 166_LIBCPP_THREAD_ABI_VISIBILITY 167bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 168 169_LIBCPP_THREAD_ABI_VISIBILITY 170bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 171 172// Thread 173_LIBCPP_THREAD_ABI_VISIBILITY 174bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 175 176_LIBCPP_THREAD_ABI_VISIBILITY 177int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 178 void *__arg); 179 180_LIBCPP_THREAD_ABI_VISIBILITY 181__libcpp_thread_id __libcpp_thread_get_current_id(); 182 183_LIBCPP_THREAD_ABI_VISIBILITY 184__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 185 186_LIBCPP_THREAD_ABI_VISIBILITY 187int __libcpp_thread_join(__libcpp_thread_t *__t); 188 189_LIBCPP_THREAD_ABI_VISIBILITY 190int __libcpp_thread_detach(__libcpp_thread_t *__t); 191 192_LIBCPP_THREAD_ABI_VISIBILITY 193void __libcpp_thread_yield(); 194 195_LIBCPP_THREAD_ABI_VISIBILITY 196void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 197 198// Thread local storage 199_LIBCPP_THREAD_ABI_VISIBILITY 200int __libcpp_tls_create(__libcpp_tls_key* __key, 201 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 202 203_LIBCPP_THREAD_ABI_VISIBILITY 204void *__libcpp_tls_get(__libcpp_tls_key __key); 205 206_LIBCPP_THREAD_ABI_VISIBILITY 207int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 208 209#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ 210 defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ 211 defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 212 213int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 214{ 215 pthread_mutexattr_t attr; 216 int __ec = pthread_mutexattr_init(&attr); 217 if (__ec) 218 return __ec; 219 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 220 if (__ec) { 221 pthread_mutexattr_destroy(&attr); 222 return __ec; 223 } 224 __ec = pthread_mutex_init(__m, &attr); 225 if (__ec) { 226 pthread_mutexattr_destroy(&attr); 227 return __ec; 228 } 229 __ec = pthread_mutexattr_destroy(&attr); 230 if (__ec) { 231 pthread_mutex_destroy(__m); 232 return __ec; 233 } 234 return 0; 235} 236 237int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 238{ 239 return pthread_mutex_lock(__m); 240} 241 242bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 243{ 244 return pthread_mutex_trylock(__m) == 0; 245} 246 247int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 248{ 249 return pthread_mutex_unlock(__m); 250} 251 252int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 253{ 254 return pthread_mutex_destroy(__m); 255} 256 257int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 258{ 259 return pthread_mutex_lock(__m); 260} 261 262bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 263{ 264 return pthread_mutex_trylock(__m) == 0; 265} 266 267int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 268{ 269 return pthread_mutex_unlock(__m); 270} 271 272int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 273{ 274 return pthread_mutex_destroy(__m); 275} 276 277// Condition Variable 278int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 279{ 280 return pthread_cond_signal(__cv); 281} 282 283int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 284{ 285 return pthread_cond_broadcast(__cv); 286} 287 288int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 289{ 290 return pthread_cond_wait(__cv, __m); 291} 292 293int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 294 timespec *__ts) 295{ 296 return pthread_cond_timedwait(__cv, __m, __ts); 297} 298 299int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 300{ 301 return pthread_cond_destroy(__cv); 302} 303 304// Execute once 305int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 306 void (*init_routine)(void)) { 307 return pthread_once(flag, init_routine); 308} 309 310// Thread id 311// Returns non-zero if the thread ids are equal, otherwise 0 312bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 313{ 314 return pthread_equal(t1, t2) != 0; 315} 316 317// Returns non-zero if t1 < t2, otherwise 0 318bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 319{ 320 return t1 < t2; 321} 322 323// Thread 324bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 325 return *__t == 0; 326} 327 328int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 329 void *__arg) 330{ 331 return pthread_create(__t, 0, __func, __arg); 332} 333 334__libcpp_thread_id __libcpp_thread_get_current_id() 335{ 336 return pthread_self(); 337} 338 339__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 340{ 341 return *__t; 342} 343 344int __libcpp_thread_join(__libcpp_thread_t *__t) 345{ 346 return pthread_join(*__t, 0); 347} 348 349int __libcpp_thread_detach(__libcpp_thread_t *__t) 350{ 351 return pthread_detach(*__t); 352} 353 354void __libcpp_thread_yield() 355{ 356 sched_yield(); 357} 358 359void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) 360{ 361 using namespace chrono; 362 seconds __s = duration_cast<seconds>(__ns); 363 timespec __ts; 364 typedef decltype(__ts.tv_sec) ts_sec; 365 _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max(); 366 367 if (__s.count() < __ts_sec_max) 368 { 369 __ts.tv_sec = static_cast<ts_sec>(__s.count()); 370 __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); 371 } 372 else 373 { 374 __ts.tv_sec = __ts_sec_max; 375 __ts.tv_nsec = 999999999; // (10^9 - 1) 376 } 377 378 while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); 379} 380 381// Thread local storage 382int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 383{ 384 return pthread_key_create(__key, __at_exit); 385} 386 387void *__libcpp_tls_get(__libcpp_tls_key __key) 388{ 389 return pthread_getspecific(__key); 390} 391 392int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 393{ 394 return pthread_setspecific(__key, __p); 395} 396 397#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL 398 399_LIBCPP_END_NAMESPACE_STD 400 401_LIBCPP_POP_MACROS 402 403#endif // !_LIBCPP_HAS_NO_THREADS 404 405#endif // _LIBCPP_THREADING_SUPPORT 406