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 52 typedef pthread_mutex_t __libcpp_mutex_t; 53 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 54 55 typedef pthread_mutex_t __libcpp_recursive_mutex_t; 56 57 // Condition Variable 58 typedef pthread_cond_t __libcpp_condvar_t; 59 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 60 61 // Execute once 62 typedef pthread_once_t __libcpp_exec_once_flag; 63 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 64 65 // Thread id 66 typedef pthread_t __libcpp_thread_id; 67 68 // Thread 69 #define _LIBCPP_NULL_THREAD 0U 70 71 typedef pthread_t __libcpp_thread_t; 72 73 // Thrad Local Storage 74 typedef 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 82 typedef void* __libcpp_mutex_t; 83 #define _LIBCPP_MUTEX_INITIALIZER 0 84 85 #if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__) 86 typedef void* __libcpp_recursive_mutex_t[6]; 87 #elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__) 88 typedef void* __libcpp_recursive_mutex_t[5]; 89 #else 90 # error Unsupported architecture 91 #endif 92 93 // Condition Variable 94 typedef void* __libcpp_condvar_t; 95 #define _LIBCPP_CONDVAR_INITIALIZER 0 96 97 // Execute Once 98 typedef void* __libcpp_exec_once_flag; 99 #define _LIBCPP_EXEC_ONCE_INITIALIZER 0 100 101 // Thread ID 102 typedef long __libcpp_thread_id; 103 104 // Thread 105 #define _LIBCPP_NULL_THREAD 0U 106 107 typedef void* __libcpp_thread_t; 108 109 // Thread Local Storage 110 typedef long __libcpp_tls_key; 111 112 #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall 113 #endif 114 115 // Mutex 116 _LIBCPP_THREAD_ABI_VISIBILITY 117 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 118 119 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 120 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 121 122 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 123 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 124 125 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 126 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 127 128 _LIBCPP_THREAD_ABI_VISIBILITY 129 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 130 131 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 132 int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 133 134 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 135 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 136 137 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 138 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 139 140 _LIBCPP_THREAD_ABI_VISIBILITY 141 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 142 143 // Condition variable 144 _LIBCPP_THREAD_ABI_VISIBILITY 145 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 146 147 _LIBCPP_THREAD_ABI_VISIBILITY 148 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 149 150 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 151 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 152 153 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 154 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 155 timespec *__ts); 156 157 _LIBCPP_THREAD_ABI_VISIBILITY 158 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 159 160 // Execute once 161 _LIBCPP_THREAD_ABI_VISIBILITY 162 int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 163 void (*init_routine)(void)); 164 165 // Thread id 166 _LIBCPP_THREAD_ABI_VISIBILITY 167 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 168 169 _LIBCPP_THREAD_ABI_VISIBILITY 170 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 171 172 // Thread 173 _LIBCPP_THREAD_ABI_VISIBILITY 174 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t); 175 176 _LIBCPP_THREAD_ABI_VISIBILITY 177 int __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 187 int __libcpp_thread_join(__libcpp_thread_t *__t); 188 189 _LIBCPP_THREAD_ABI_VISIBILITY 190 int __libcpp_thread_detach(__libcpp_thread_t *__t); 191 192 _LIBCPP_THREAD_ABI_VISIBILITY 193 void __libcpp_thread_yield(); 194 195 _LIBCPP_THREAD_ABI_VISIBILITY 196 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns); 197 198 // Thread local storage 199 _LIBCPP_THREAD_ABI_VISIBILITY 200 int __libcpp_tls_create(__libcpp_tls_key* __key, 201 void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)); 202 203 _LIBCPP_THREAD_ABI_VISIBILITY 204 void *__libcpp_tls_get(__libcpp_tls_key __key); 205 206 _LIBCPP_THREAD_ABI_VISIBILITY 207 int __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 213 int __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 237 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 238 { 239 return pthread_mutex_lock(__m); 240 } 241 242 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 243 { 244 return pthread_mutex_trylock(__m) == 0; 245 } 246 247 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 248 { 249 return pthread_mutex_unlock(__m); 250 } 251 252 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 253 { 254 return pthread_mutex_destroy(__m); 255 } 256 257 int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 258 { 259 return pthread_mutex_lock(__m); 260 } 261 262 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 263 { 264 return pthread_mutex_trylock(__m) == 0; 265 } 266 267 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 268 { 269 return pthread_mutex_unlock(__m); 270 } 271 272 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 273 { 274 return pthread_mutex_destroy(__m); 275 } 276 277 // Condition Variable 278 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 279 { 280 return pthread_cond_signal(__cv); 281 } 282 283 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 284 { 285 return pthread_cond_broadcast(__cv); 286 } 287 288 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 289 { 290 return pthread_cond_wait(__cv, __m); 291 } 292 293 int __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 299 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 300 { 301 return pthread_cond_destroy(__cv); 302 } 303 304 // Execute once 305 int __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 312 bool __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 318 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 319 { 320 return t1 < t2; 321 } 322 323 // Thread 324 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { 325 return *__t == 0; 326 } 327 328 int __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 344 int __libcpp_thread_join(__libcpp_thread_t *__t) 345 { 346 return pthread_join(*__t, 0); 347 } 348 349 int __libcpp_thread_detach(__libcpp_thread_t *__t) 350 { 351 return pthread_detach(*__t); 352 } 353 354 void __libcpp_thread_yield() 355 { 356 sched_yield(); 357 } 358 359 void __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 382 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 383 { 384 return pthread_key_create(__key, __at_exit); 385 } 386 387 void *__libcpp_tls_get(__libcpp_tls_key __key) 388 { 389 return pthread_getspecific(__key); 390 } 391 392 int __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