1c7e4239fSAsiri Rathnayake// -*- C++ -*- 2c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===// 3c7e4239fSAsiri Rathnayake// 4c7e4239fSAsiri Rathnayake// The LLVM Compiler Infrastructure 5c7e4239fSAsiri Rathnayake// 6c7e4239fSAsiri Rathnayake// This file is dual licensed under the MIT and the University of Illinois Open 7c7e4239fSAsiri Rathnayake// Source Licenses. See LICENSE.TXT for details. 8c7e4239fSAsiri Rathnayake// 9c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===// 10c7e4239fSAsiri Rathnayake 11c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_THREADING_SUPPORT 12c7e4239fSAsiri Rathnayake#define _LIBCPP_THREADING_SUPPORT 13c7e4239fSAsiri Rathnayake 14c7e4239fSAsiri Rathnayake#include <__config> 15c7e4239fSAsiri Rathnayake 16c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 17c7e4239fSAsiri Rathnayake#pragma GCC system_header 18c7e4239fSAsiri Rathnayake#endif 19c7e4239fSAsiri Rathnayake 20c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_THREADS 21c7e4239fSAsiri Rathnayake 223cf2f7bcSAsiri Rathnayake#ifndef __libcpp_has_include 233cf2f7bcSAsiri Rathnayake #ifndef __has_include 243cf2f7bcSAsiri Rathnayake #define __libcpp_has_include(x) 0 253cf2f7bcSAsiri Rathnayake #else 263cf2f7bcSAsiri Rathnayake #define __libcpp_has_include(x) __has_include(x) 27d547ac0dSAsiri Rathnayake #endif 28d547ac0dSAsiri Rathnayake#endif 29d547ac0dSAsiri Rathnayake 303cf2f7bcSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \ 31*6cb0d41cSAsiri Rathnayake !__libcpp_has_include(<__external_threading>) 32*6cb0d41cSAsiri Rathnayake// If the <__external_threading> header is absent, build libc++ against a 33*6cb0d41cSAsiri Rathnayake// pthread-oriented thread api but leave out its implementation. This setup 34*6cb0d41cSAsiri Rathnayake// allows building+testing of an externally-threaded library variant (on any 35*6cb0d41cSAsiri Rathnayake// platform that supports pthreads). Here, an 'externally-threaded' library 36*6cb0d41cSAsiri Rathnayake// variant is one where the implementation of the libc++ thread api is provided 37*6cb0d41cSAsiri Rathnayake// as a separate library. 38*6cb0d41cSAsiri Rathnayake#define _LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD 39*6cb0d41cSAsiri Rathnayake#endif 40*6cb0d41cSAsiri Rathnayake 41*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \ 423cf2f7bcSAsiri Rathnayake __libcpp_has_include(<__external_threading>) 433cf2f7bcSAsiri Rathnayake#include <__external_threading> 443cf2f7bcSAsiri Rathnayake#else 45790e10f6SSaleem Abdulrasool 46*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \ 47*6cb0d41cSAsiri Rathnayake defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD) 48c7e4239fSAsiri Rathnayake#include <pthread.h> 49c7e4239fSAsiri Rathnayake#include <sched.h> 50790e10f6SSaleem Abdulrasool#endif 51c7e4239fSAsiri Rathnayake 528c2bf45dSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) 538c2bf45dSAsiri Rathnayake#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS 548c2bf45dSAsiri Rathnayake#else 558c2bf45dSAsiri Rathnayake#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY 568c2bf45dSAsiri Rathnayake#endif 578c2bf45dSAsiri Rathnayake 58c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD 59c7e4239fSAsiri Rathnayake 60*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \ 61*6cb0d41cSAsiri Rathnayake defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD) 62c7e4239fSAsiri Rathnayake// Mutex 63c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t; 648c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 65c7e4239fSAsiri Rathnayake 66790e10f6SSaleem Abdulrasool// Condition Variable 67790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t; 68790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 69790e10f6SSaleem Abdulrasool 70790e10f6SSaleem Abdulrasool// THread ID 71790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_id; 72790e10f6SSaleem Abdulrasool 73790e10f6SSaleem Abdulrasool// Thread 74790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t; 75790e10f6SSaleem Abdulrasool 76790e10f6SSaleem Abdulrasool// Thrad Local Storage 77790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key; 78790e10f6SSaleem Abdulrasool#endif 79790e10f6SSaleem Abdulrasool 80790e10f6SSaleem Abdulrasool// Mutex 818c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 828c2bf45dSAsiri Rathnayakeint __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m); 83790e10f6SSaleem Abdulrasool 848c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 858c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m); 86790e10f6SSaleem Abdulrasool 878c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 888c2bf45dSAsiri Rathnayakeint __libcpp_mutex_trylock(__libcpp_mutex_t *__m); 89790e10f6SSaleem Abdulrasool 908c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 918c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m); 92790e10f6SSaleem Abdulrasool 938c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 948c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m); 958c2bf45dSAsiri Rathnayake 968c2bf45dSAsiri Rathnayake// Condition variable 978c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 988c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv); 99790e10f6SSaleem Abdulrasool 1008c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1018c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); 102790e10f6SSaleem Abdulrasool 1038c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1048c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); 105790e10f6SSaleem Abdulrasool 1068c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 107790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 108790e10f6SSaleem Abdulrasool timespec *__ts); 109790e10f6SSaleem Abdulrasool 1108c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1118c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); 1128c2bf45dSAsiri Rathnayake 113790e10f6SSaleem Abdulrasool// Thread ID 1148c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1158c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); 116790e10f6SSaleem Abdulrasool 1178c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1188c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); 1198c2bf45dSAsiri Rathnayake 1208c2bf45dSAsiri Rathnayake// Thread 1218c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 122790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 123790e10f6SSaleem Abdulrasool void *__arg); 124790e10f6SSaleem Abdulrasool 1258c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1268c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id(); 127790e10f6SSaleem Abdulrasool 1288c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1298c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t); 130790e10f6SSaleem Abdulrasool 1318c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1328c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t); 133790e10f6SSaleem Abdulrasool 1348c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1358c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t); 136790e10f6SSaleem Abdulrasool 1378c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1388c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield(); 1398c2bf45dSAsiri Rathnayake 1408c2bf45dSAsiri Rathnayake// Thread local storage 1418c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1428c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)); 143790e10f6SSaleem Abdulrasool 1448c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1458c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key); 146790e10f6SSaleem Abdulrasool 1478c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY 1488c2bf45dSAsiri Rathnayakevoid __libcpp_tls_set(__libcpp_tls_key __key, void *__p); 1498c2bf45dSAsiri Rathnayake 150*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \ 151*6cb0d41cSAsiri Rathnayake defined(_LIBCPP_BUILDING_THREAD_API_EXTERNAL_PTHREAD) 1528c2bf45dSAsiri Rathnayake 153c7e4239fSAsiri Rathnayakeint __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m) 154c7e4239fSAsiri Rathnayake{ 155c7e4239fSAsiri Rathnayake pthread_mutexattr_t attr; 156c7e4239fSAsiri Rathnayake int __ec = pthread_mutexattr_init(&attr); 157c7e4239fSAsiri Rathnayake if (__ec) 158790e10f6SSaleem Abdulrasool return __ec; 159790e10f6SSaleem Abdulrasool __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 160790e10f6SSaleem Abdulrasool if (__ec) { 161c7e4239fSAsiri Rathnayake pthread_mutexattr_destroy(&attr); 162c7e4239fSAsiri Rathnayake return __ec; 163c7e4239fSAsiri Rathnayake } 164c7e4239fSAsiri Rathnayake __ec = pthread_mutex_init(__m, &attr); 165790e10f6SSaleem Abdulrasool if (__ec) { 166c7e4239fSAsiri Rathnayake pthread_mutexattr_destroy(&attr); 167c7e4239fSAsiri Rathnayake return __ec; 168c7e4239fSAsiri Rathnayake } 169c7e4239fSAsiri Rathnayake __ec = pthread_mutexattr_destroy(&attr); 170790e10f6SSaleem Abdulrasool if (__ec) { 171c7e4239fSAsiri Rathnayake pthread_mutex_destroy(__m); 172c7e4239fSAsiri Rathnayake return __ec; 173c7e4239fSAsiri Rathnayake } 174c7e4239fSAsiri Rathnayake return 0; 175c7e4239fSAsiri Rathnayake} 176c7e4239fSAsiri Rathnayake 177c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m) 178c7e4239fSAsiri Rathnayake{ 179c7e4239fSAsiri Rathnayake return pthread_mutex_lock(__m); 180c7e4239fSAsiri Rathnayake} 181c7e4239fSAsiri Rathnayake 182c7e4239fSAsiri Rathnayakeint __libcpp_mutex_trylock(__libcpp_mutex_t *__m) 183c7e4239fSAsiri Rathnayake{ 184c7e4239fSAsiri Rathnayake return pthread_mutex_trylock(__m); 185c7e4239fSAsiri Rathnayake} 186c7e4239fSAsiri Rathnayake 187c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m) 188c7e4239fSAsiri Rathnayake{ 189c7e4239fSAsiri Rathnayake return pthread_mutex_unlock(__m); 190c7e4239fSAsiri Rathnayake} 191c7e4239fSAsiri Rathnayake 192c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m) 193c7e4239fSAsiri Rathnayake{ 194c7e4239fSAsiri Rathnayake return pthread_mutex_destroy(__m); 195c7e4239fSAsiri Rathnayake} 196c7e4239fSAsiri Rathnayake 197790e10f6SSaleem Abdulrasool// Condition Variable 198c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv) 199c7e4239fSAsiri Rathnayake{ 200c7e4239fSAsiri Rathnayake return pthread_cond_signal(__cv); 201c7e4239fSAsiri Rathnayake} 202c7e4239fSAsiri Rathnayake 203c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) 204c7e4239fSAsiri Rathnayake{ 205c7e4239fSAsiri Rathnayake return pthread_cond_broadcast(__cv); 206c7e4239fSAsiri Rathnayake} 207c7e4239fSAsiri Rathnayake 208c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) 209c7e4239fSAsiri Rathnayake{ 210c7e4239fSAsiri Rathnayake return pthread_cond_wait(__cv, __m); 211c7e4239fSAsiri Rathnayake} 212c7e4239fSAsiri Rathnayake 213790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, 214790e10f6SSaleem Abdulrasool timespec *__ts) 215c7e4239fSAsiri Rathnayake{ 216c7e4239fSAsiri Rathnayake return pthread_cond_timedwait(__cv, __m, __ts); 217c7e4239fSAsiri Rathnayake} 218c7e4239fSAsiri Rathnayake 219c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) 220c7e4239fSAsiri Rathnayake{ 221c7e4239fSAsiri Rathnayake return pthread_cond_destroy(__cv); 222c7e4239fSAsiri Rathnayake} 223c7e4239fSAsiri Rathnayake 224c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0 225c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 226c7e4239fSAsiri Rathnayake{ 227c7e4239fSAsiri Rathnayake return pthread_equal(t1, t2) != 0; 228c7e4239fSAsiri Rathnayake} 229c7e4239fSAsiri Rathnayake 230c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0 231c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 232c7e4239fSAsiri Rathnayake{ 233c7e4239fSAsiri Rathnayake return t1 < t2; 234c7e4239fSAsiri Rathnayake} 235c7e4239fSAsiri Rathnayake 236c7e4239fSAsiri Rathnayake// Thread 237790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), 238790e10f6SSaleem Abdulrasool void *__arg) 239c7e4239fSAsiri Rathnayake{ 240c7e4239fSAsiri Rathnayake return pthread_create(__t, 0, __func, __arg); 241c7e4239fSAsiri Rathnayake} 242c7e4239fSAsiri Rathnayake 243c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id() 244c7e4239fSAsiri Rathnayake{ 245c7e4239fSAsiri Rathnayake return pthread_self(); 246c7e4239fSAsiri Rathnayake} 247c7e4239fSAsiri Rathnayake 248c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) 249c7e4239fSAsiri Rathnayake{ 250c7e4239fSAsiri Rathnayake return *__t; 251c7e4239fSAsiri Rathnayake} 252c7e4239fSAsiri Rathnayake 253c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t) 254c7e4239fSAsiri Rathnayake{ 255c7e4239fSAsiri Rathnayake return pthread_join(*__t, 0); 256c7e4239fSAsiri Rathnayake} 257c7e4239fSAsiri Rathnayake 258c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t) 259c7e4239fSAsiri Rathnayake{ 260c7e4239fSAsiri Rathnayake return pthread_detach(*__t); 261c7e4239fSAsiri Rathnayake} 262c7e4239fSAsiri Rathnayake 263c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield() 264c7e4239fSAsiri Rathnayake{ 265c7e4239fSAsiri Rathnayake sched_yield(); 266c7e4239fSAsiri Rathnayake} 267c7e4239fSAsiri Rathnayake 268c7e4239fSAsiri Rathnayake// Thread local storage 2698c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) 270c7e4239fSAsiri Rathnayake{ 271c7e4239fSAsiri Rathnayake return pthread_key_create(__key, __at_exit); 272c7e4239fSAsiri Rathnayake} 273c7e4239fSAsiri Rathnayake 2748c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key) 275c7e4239fSAsiri Rathnayake{ 276c7e4239fSAsiri Rathnayake return pthread_getspecific(__key); 277c7e4239fSAsiri Rathnayake} 278c7e4239fSAsiri Rathnayake 2798c2bf45dSAsiri Rathnayakevoid __libcpp_tls_set(__libcpp_tls_key __key, void *__p) 280c7e4239fSAsiri Rathnayake{ 281c7e4239fSAsiri Rathnayake pthread_setspecific(__key, __p); 282c7e4239fSAsiri Rathnayake} 283c7e4239fSAsiri Rathnayake 284790e10f6SSaleem Abdulrasool#endif // _LIBCPP_HAS_THREAD_API_PTHREAD 285c7e4239fSAsiri Rathnayake 286c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD 287c7e4239fSAsiri Rathnayake 2883cf2f7bcSAsiri Rathnayake#endif // !_LIBCPP_HAS_THREAD_API_EXTERNAL || !__libcpp_has_include(<__external_threading>) 28981c0be3fSAsiri Rathnayake 290c7e4239fSAsiri Rathnayake#endif // _LIBCPP_HAS_NO_THREADS 291c7e4239fSAsiri Rathnayake 292c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT 293