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#ifndef _LIBCPP_HAS_NO_THREADS 21 22#ifndef __libcpp_has_include 23 #ifndef __has_include 24 #define __libcpp_has_include(x) 0 25 #else 26 #define __libcpp_has_include(x) __has_include(x) 27 #endif 28#endif 29 30#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \ 31 !__libcpp_has_include(<__external_threading>) 32// If the <__external_threading> header is absent, build libc++ against a 33// pthread-oriented thread api but leave out its implementation. This setup 34// allows building+testing of an externally-threaded library variant (on any 35// platform that supports pthreads). Here, an 'externally-threaded' library 36// variant is one where the implementation of the libc++ thread api is provided 37// as a separate library. 38#define _LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD 39#endif 40 41#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \ 42 __libcpp_has_include(<__external_threading>) 43#include <__external_threading> 44#else 45 46#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \ 47 defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD) 48#include <pthread.h> 49#include <sched.h> 50#endif 51 52#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 53#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 54#else 55#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 56#endif 57 58_LIBCPP_BEGIN_NAMESPACE_STD 59 60#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \ 61 defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD) 62// Mutex 63typedef pthread_mutex_t __libcpp_mutex_t; 64#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 65 66typedef pthread_mutex_t __libcpp_recursive_mutex_t; 67 68// Condition Variable 69typedef pthread_cond_t __libcpp_condvar_t; 70#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 71 72// Execute once 73typedef pthread_once_t __libcpp_exec_once_flag; 74#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT 75 76// Thread id 77typedef pthread_t __libcpp_thread_id; 78 79// Thread 80typedef pthread_t __libcpp_thread_t; 81 82// Thrad Local Storage 83typedef pthread_key_t __libcpp_tls_key; 84#endif 85 86// Mutex 87_LIBCPP_THREAD_ABI_VISIBILITY 88int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); 89 90_LIBCPP_THREAD_ABI_VISIBILITY 91int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m); 92 93_LIBCPP_THREAD_ABI_VISIBILITY 94int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m); 95 96_LIBCPP_THREAD_ABI_VISIBILITY 97int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m); 98 99_LIBCPP_THREAD_ABI_VISIBILITY 100int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m); 101 102_LIBCPP_THREAD_ABI_VISIBILITY 103int __libcpp_mutex_lock(__libcpp_mutex_t *__m); 104 105_LIBCPP_THREAD_ABI_VISIBILITY 106int __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 107 108_LIBCPP_THREAD_ABI_VISIBILITY 109int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 110 111_LIBCPP_THREAD_ABI_VISIBILITY 112int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 113 114// Condition variable 115_LIBCPP_THREAD_ABI_VISIBILITY 116int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 117 118_LIBCPP_THREAD_ABI_VISIBILITY 119int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 120 121_LIBCPP_THREAD_ABI_VISIBILITY 122int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 123 124_LIBCPP_THREAD_ABI_VISIBILITY 125int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 126 timespec *__ts); 127 128_LIBCPP_THREAD_ABI_VISIBILITY 129int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 130 131// Execute once 132_LIBCPP_THREAD_ABI_VISIBILITY 133int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 134 void (*init_routine)(void)); 135 136// Thread id 137#if defined(__APPLE__) && !defined(__arm__) 138_LIBCPP_THREAD_ABI_VISIBILITY 139mach_port_t __libcpp_thread_get_port(); 140#endif 141 142_LIBCPP_THREAD_ABI_VISIBILITY 143bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 144 145_LIBCPP_THREAD_ABI_VISIBILITY 146bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 147 148// Thread 149_LIBCPP_THREAD_ABI_VISIBILITY 150int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 151 void *__arg); 152 153_LIBCPP_THREAD_ABI_VISIBILITY 154__libcpp_thread_id __libcpp_thread_get_current_id(); 155 156_LIBCPP_THREAD_ABI_VISIBILITY 157__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 158 159_LIBCPP_THREAD_ABI_VISIBILITY 160int __libcpp_thread_join(__libcpp_thread_t *__t); 161 162_LIBCPP_THREAD_ABI_VISIBILITY 163int __libcpp_thread_detach(__libcpp_thread_t *__t); 164 165_LIBCPP_THREAD_ABI_VISIBILITY 166void __libcpp_thread_yield(); 167 168// Thread local storage 169_LIBCPP_THREAD_ABI_VISIBILITY 170int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)); 171 172_LIBCPP_THREAD_ABI_VISIBILITY 173void *__libcpp_tls_get(__libcpp_tls_key __key); 174 175_LIBCPP_THREAD_ABI_VISIBILITY 176int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 177 178#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \ 179 defined(_LIBCPP_BUILDING_THREAD_API_EXTERNAL_PTHREAD) 180 181int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) 182{ 183 pthread_mutexattr_t attr; 184 int __ec = pthread_mutexattr_init(&attr); 185 if (__ec) 186 return __ec; 187 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 188 if (__ec) { 189 pthread_mutexattr_destroy(&attr); 190 return __ec; 191 } 192 __ec = pthread_mutex_init(__m, &attr); 193 if (__ec) { 194 pthread_mutexattr_destroy(&attr); 195 return __ec; 196 } 197 __ec = pthread_mutexattr_destroy(&attr); 198 if (__ec) { 199 pthread_mutex_destroy(__m); 200 return __ec; 201 } 202 return 0; 203} 204 205int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) 206{ 207 return pthread_mutex_lock(__m); 208} 209 210int __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) 211{ 212 return pthread_mutex_trylock(__m); 213} 214 215int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m) 216{ 217 return pthread_mutex_unlock(__m); 218} 219 220int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) 221{ 222 return pthread_mutex_destroy(__m); 223} 224 225int __libcpp_mutex_lock(__libcpp_mutex_t *__m) 226{ 227 return pthread_mutex_lock(__m); 228} 229 230int __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 231{ 232 return pthread_mutex_trylock(__m); 233} 234 235int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 236{ 237 return pthread_mutex_unlock(__m); 238} 239 240int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 241{ 242 return pthread_mutex_destroy(__m); 243} 244 245// Condition Variable 246int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 247{ 248 return pthread_cond_signal(__cv); 249} 250 251int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 252{ 253 return pthread_cond_broadcast(__cv); 254} 255 256int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 257{ 258 return pthread_cond_wait(__cv, __m); 259} 260 261int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 262 timespec *__ts) 263{ 264 return pthread_cond_timedwait(__cv, __m, __ts); 265} 266 267int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 268{ 269 return pthread_cond_destroy(__cv); 270} 271 272// Execute once 273int __libcpp_execute_once(__libcpp_exec_once_flag *flag, 274 void (*init_routine)(void)) { 275 return pthread_once(flag, init_routine); 276} 277 278// Thread id 279#if defined(__APPLE__) && !defined(__arm__) 280mach_port_t __libcpp_thread_get_port() { 281 return pthread_mach_thread_np(pthread_self()); 282} 283#endif 284 285// Returns non-zero if the thread ids are equal, otherwise 0 286bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 287{ 288 return pthread_equal(t1, t2) != 0; 289} 290 291// Returns non-zero if t1 < t2, otherwise 0 292bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 293{ 294 return t1 < t2; 295} 296 297// Thread 298int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 299 void *__arg) 300{ 301 return pthread_create(__t, 0, __func, __arg); 302} 303 304__libcpp_thread_id __libcpp_thread_get_current_id() 305{ 306 return pthread_self(); 307} 308 309__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 310{ 311 return *__t; 312} 313 314int __libcpp_thread_join(__libcpp_thread_t *__t) 315{ 316 return pthread_join(*__t, 0); 317} 318 319int __libcpp_thread_detach(__libcpp_thread_t *__t) 320{ 321 return pthread_detach(*__t); 322} 323 324void __libcpp_thread_yield() 325{ 326 sched_yield(); 327} 328 329// Thread local storage 330int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 331{ 332 return pthread_key_create(__key, __at_exit); 333} 334 335void *__libcpp_tls_get(__libcpp_tls_key __key) 336{ 337 return pthread_getspecific(__key); 338} 339 340int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 341{ 342 return pthread_setspecific(__key, __p); 343} 344 345#endif // _LIBCPP_HAS_THREAD_API_PTHREAD 346 347_LIBCPP_END_NAMESPACE_STD 348 349#endif // !_LIBCPP_HAS_THREAD_API_EXTERNAL || !__libcpp_has_include(<__external_threading>) 350 351#endif // _LIBCPP_HAS_NO_THREADS 352 353#endif // _LIBCPP_THREADING_SUPPORT 354