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