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