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#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 23#include <pthread.h> 24#include <sched.h> 25#endif 26 27_LIBCPP_BEGIN_NAMESPACE_STD 28 29#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) 30 31// Mutex 32#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 33typedef pthread_mutex_t __libcpp_mutex_t; 34 35inline _LIBCPP_ALWAYS_INLINE 36int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m) 37{ 38 pthread_mutexattr_t attr; 39 int __ec = pthread_mutexattr_init(&attr); 40 if (__ec) return __ec; 41 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 42 if (__ec) 43 { 44 pthread_mutexattr_destroy(&attr); 45 return __ec; 46 } 47 __ec = pthread_mutex_init(__m, &attr); 48 if (__ec) 49 { 50 pthread_mutexattr_destroy(&attr); 51 return __ec; 52 } 53 __ec = pthread_mutexattr_destroy(&attr); 54 if (__ec) 55 { 56 pthread_mutex_destroy(__m); 57 return __ec; 58 } 59 return 0; 60} 61 62inline _LIBCPP_ALWAYS_INLINE 63int __libcpp_mutex_lock(__libcpp_mutex_t* __m) 64{ 65 return pthread_mutex_lock(__m); 66} 67 68inline _LIBCPP_ALWAYS_INLINE 69int __libcpp_mutex_trylock(__libcpp_mutex_t* __m) 70{ 71 return pthread_mutex_trylock(__m); 72} 73 74inline _LIBCPP_ALWAYS_INLINE 75int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) 76{ 77 return pthread_mutex_unlock(__m); 78} 79 80inline _LIBCPP_ALWAYS_INLINE 81int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) 82{ 83 return pthread_mutex_destroy(__m); 84} 85 86// Condition variable 87#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER 88typedef pthread_cond_t __libcpp_condvar_t; 89 90inline _LIBCPP_ALWAYS_INLINE 91int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) 92{ 93 return pthread_cond_signal(__cv); 94} 95 96inline _LIBCPP_ALWAYS_INLINE 97int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) 98{ 99 return pthread_cond_broadcast(__cv); 100} 101 102inline _LIBCPP_ALWAYS_INLINE 103int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) 104{ 105 return pthread_cond_wait(__cv, __m); 106} 107 108inline _LIBCPP_ALWAYS_INLINE 109int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) 110{ 111 return pthread_cond_timedwait(__cv, __m, __ts); 112} 113 114inline _LIBCPP_ALWAYS_INLINE 115int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) 116{ 117 return pthread_cond_destroy(__cv); 118} 119 120// Thread id 121typedef pthread_t __libcpp_thread_id; 122 123// Returns non-zero if the thread ids are equal, otherwise 0 124inline _LIBCPP_ALWAYS_INLINE 125bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) 126{ 127 return pthread_equal(t1, t2) != 0; 128} 129 130// Returns non-zero if t1 < t2, otherwise 0 131inline _LIBCPP_ALWAYS_INLINE 132bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) 133{ 134 return t1 < t2; 135} 136 137// Thread 138typedef pthread_t __libcpp_thread_t; 139 140inline _LIBCPP_ALWAYS_INLINE 141int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) 142{ 143 return pthread_create(__t, 0, __func, __arg); 144} 145 146inline _LIBCPP_ALWAYS_INLINE 147__libcpp_thread_id __libcpp_thread_get_current_id() 148{ 149 return pthread_self(); 150} 151 152inline _LIBCPP_ALWAYS_INLINE 153__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) 154{ 155 return *__t; 156} 157 158inline _LIBCPP_ALWAYS_INLINE 159int __libcpp_thread_join(__libcpp_thread_t* __t) 160{ 161 return pthread_join(*__t, 0); 162} 163 164inline _LIBCPP_ALWAYS_INLINE 165int __libcpp_thread_detach(__libcpp_thread_t* __t) 166{ 167 return pthread_detach(*__t); 168} 169 170inline _LIBCPP_ALWAYS_INLINE 171void __libcpp_thread_yield() 172{ 173 sched_yield(); 174} 175 176// Thread local storage 177typedef pthread_key_t __libcpp_tl_key; 178 179inline _LIBCPP_ALWAYS_INLINE 180int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit)(void*)) 181{ 182 return pthread_key_create(__key, __at_exit); 183} 184 185inline _LIBCPP_ALWAYS_INLINE 186void* __libcpp_tl_get(__libcpp_tl_key __key) 187{ 188 return pthread_getspecific(__key); 189} 190 191inline _LIBCPP_ALWAYS_INLINE 192void __libcpp_tl_set(__libcpp_tl_key __key, void* __p) 193{ 194 pthread_setspecific(__key, __p); 195} 196 197#else // !_LIBCPP_HAS_THREAD_API_PTHREAD 198 #error "No thread API selected." 199#endif 200 201_LIBCPP_END_NAMESPACE_STD 202 203#endif // _LIBCPP_HAS_NO_THREADS 204 205#endif // _LIBCPP_THREADING_SUPPORT 206