1*4684ddb6SLionel Sambuc //===------------------------- mutex.cpp ----------------------------------===// 2*4684ddb6SLionel Sambuc // 3*4684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure 4*4684ddb6SLionel Sambuc // 5*4684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open 6*4684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details. 7*4684ddb6SLionel Sambuc // 8*4684ddb6SLionel Sambuc //===----------------------------------------------------------------------===// 9*4684ddb6SLionel Sambuc 10*4684ddb6SLionel Sambuc #define _LIBCPP_BUILDING_MUTEX 11*4684ddb6SLionel Sambuc #include "mutex" 12*4684ddb6SLionel Sambuc #include "limits" 13*4684ddb6SLionel Sambuc #include "system_error" 14*4684ddb6SLionel Sambuc #include "cassert" 15*4684ddb6SLionel Sambuc 16*4684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD 17*4684ddb6SLionel Sambuc 18*4684ddb6SLionel Sambuc const defer_lock_t defer_lock = {}; 19*4684ddb6SLionel Sambuc const try_to_lock_t try_to_lock = {}; 20*4684ddb6SLionel Sambuc const adopt_lock_t adopt_lock = {}; 21*4684ddb6SLionel Sambuc 22*4684ddb6SLionel Sambuc mutex::~mutex() 23*4684ddb6SLionel Sambuc { 24*4684ddb6SLionel Sambuc pthread_mutex_destroy(&__m_); 25*4684ddb6SLionel Sambuc } 26*4684ddb6SLionel Sambuc 27*4684ddb6SLionel Sambuc void 28*4684ddb6SLionel Sambuc mutex::lock() 29*4684ddb6SLionel Sambuc { 30*4684ddb6SLionel Sambuc int ec = pthread_mutex_lock(&__m_); 31*4684ddb6SLionel Sambuc if (ec) 32*4684ddb6SLionel Sambuc __throw_system_error(ec, "mutex lock failed"); 33*4684ddb6SLionel Sambuc } 34*4684ddb6SLionel Sambuc 35*4684ddb6SLionel Sambuc bool 36*4684ddb6SLionel Sambuc mutex::try_lock() _NOEXCEPT 37*4684ddb6SLionel Sambuc { 38*4684ddb6SLionel Sambuc return pthread_mutex_trylock(&__m_) == 0; 39*4684ddb6SLionel Sambuc } 40*4684ddb6SLionel Sambuc 41*4684ddb6SLionel Sambuc void 42*4684ddb6SLionel Sambuc mutex::unlock() _NOEXCEPT 43*4684ddb6SLionel Sambuc { 44*4684ddb6SLionel Sambuc int ec = pthread_mutex_unlock(&__m_); 45*4684ddb6SLionel Sambuc (void)ec; 46*4684ddb6SLionel Sambuc assert(ec == 0); 47*4684ddb6SLionel Sambuc } 48*4684ddb6SLionel Sambuc 49*4684ddb6SLionel Sambuc // recursive_mutex 50*4684ddb6SLionel Sambuc 51*4684ddb6SLionel Sambuc recursive_mutex::recursive_mutex() 52*4684ddb6SLionel Sambuc { 53*4684ddb6SLionel Sambuc pthread_mutexattr_t attr; 54*4684ddb6SLionel Sambuc int ec = pthread_mutexattr_init(&attr); 55*4684ddb6SLionel Sambuc if (ec) 56*4684ddb6SLionel Sambuc goto fail; 57*4684ddb6SLionel Sambuc ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 58*4684ddb6SLionel Sambuc if (ec) 59*4684ddb6SLionel Sambuc { 60*4684ddb6SLionel Sambuc pthread_mutexattr_destroy(&attr); 61*4684ddb6SLionel Sambuc goto fail; 62*4684ddb6SLionel Sambuc } 63*4684ddb6SLionel Sambuc ec = pthread_mutex_init(&__m_, &attr); 64*4684ddb6SLionel Sambuc if (ec) 65*4684ddb6SLionel Sambuc { 66*4684ddb6SLionel Sambuc pthread_mutexattr_destroy(&attr); 67*4684ddb6SLionel Sambuc goto fail; 68*4684ddb6SLionel Sambuc } 69*4684ddb6SLionel Sambuc ec = pthread_mutexattr_destroy(&attr); 70*4684ddb6SLionel Sambuc if (ec) 71*4684ddb6SLionel Sambuc { 72*4684ddb6SLionel Sambuc pthread_mutex_destroy(&__m_); 73*4684ddb6SLionel Sambuc goto fail; 74*4684ddb6SLionel Sambuc } 75*4684ddb6SLionel Sambuc return; 76*4684ddb6SLionel Sambuc fail: 77*4684ddb6SLionel Sambuc __throw_system_error(ec, "recursive_mutex constructor failed"); 78*4684ddb6SLionel Sambuc } 79*4684ddb6SLionel Sambuc 80*4684ddb6SLionel Sambuc recursive_mutex::~recursive_mutex() 81*4684ddb6SLionel Sambuc { 82*4684ddb6SLionel Sambuc int e = pthread_mutex_destroy(&__m_); 83*4684ddb6SLionel Sambuc (void)e; 84*4684ddb6SLionel Sambuc assert(e == 0); 85*4684ddb6SLionel Sambuc } 86*4684ddb6SLionel Sambuc 87*4684ddb6SLionel Sambuc void 88*4684ddb6SLionel Sambuc recursive_mutex::lock() 89*4684ddb6SLionel Sambuc { 90*4684ddb6SLionel Sambuc int ec = pthread_mutex_lock(&__m_); 91*4684ddb6SLionel Sambuc if (ec) 92*4684ddb6SLionel Sambuc __throw_system_error(ec, "recursive_mutex lock failed"); 93*4684ddb6SLionel Sambuc } 94*4684ddb6SLionel Sambuc 95*4684ddb6SLionel Sambuc void 96*4684ddb6SLionel Sambuc recursive_mutex::unlock() _NOEXCEPT 97*4684ddb6SLionel Sambuc { 98*4684ddb6SLionel Sambuc int e = pthread_mutex_unlock(&__m_); 99*4684ddb6SLionel Sambuc (void)e; 100*4684ddb6SLionel Sambuc assert(e == 0); 101*4684ddb6SLionel Sambuc } 102*4684ddb6SLionel Sambuc 103*4684ddb6SLionel Sambuc bool 104*4684ddb6SLionel Sambuc recursive_mutex::try_lock() _NOEXCEPT 105*4684ddb6SLionel Sambuc { 106*4684ddb6SLionel Sambuc return pthread_mutex_trylock(&__m_) == 0; 107*4684ddb6SLionel Sambuc } 108*4684ddb6SLionel Sambuc 109*4684ddb6SLionel Sambuc // timed_mutex 110*4684ddb6SLionel Sambuc 111*4684ddb6SLionel Sambuc timed_mutex::timed_mutex() 112*4684ddb6SLionel Sambuc : __locked_(false) 113*4684ddb6SLionel Sambuc { 114*4684ddb6SLionel Sambuc } 115*4684ddb6SLionel Sambuc 116*4684ddb6SLionel Sambuc timed_mutex::~timed_mutex() 117*4684ddb6SLionel Sambuc { 118*4684ddb6SLionel Sambuc lock_guard<mutex> _(__m_); 119*4684ddb6SLionel Sambuc } 120*4684ddb6SLionel Sambuc 121*4684ddb6SLionel Sambuc void 122*4684ddb6SLionel Sambuc timed_mutex::lock() 123*4684ddb6SLionel Sambuc { 124*4684ddb6SLionel Sambuc unique_lock<mutex> lk(__m_); 125*4684ddb6SLionel Sambuc while (__locked_) 126*4684ddb6SLionel Sambuc __cv_.wait(lk); 127*4684ddb6SLionel Sambuc __locked_ = true; 128*4684ddb6SLionel Sambuc } 129*4684ddb6SLionel Sambuc 130*4684ddb6SLionel Sambuc bool 131*4684ddb6SLionel Sambuc timed_mutex::try_lock() _NOEXCEPT 132*4684ddb6SLionel Sambuc { 133*4684ddb6SLionel Sambuc unique_lock<mutex> lk(__m_, try_to_lock); 134*4684ddb6SLionel Sambuc if (lk.owns_lock() && !__locked_) 135*4684ddb6SLionel Sambuc { 136*4684ddb6SLionel Sambuc __locked_ = true; 137*4684ddb6SLionel Sambuc return true; 138*4684ddb6SLionel Sambuc } 139*4684ddb6SLionel Sambuc return false; 140*4684ddb6SLionel Sambuc } 141*4684ddb6SLionel Sambuc 142*4684ddb6SLionel Sambuc void 143*4684ddb6SLionel Sambuc timed_mutex::unlock() _NOEXCEPT 144*4684ddb6SLionel Sambuc { 145*4684ddb6SLionel Sambuc lock_guard<mutex> _(__m_); 146*4684ddb6SLionel Sambuc __locked_ = false; 147*4684ddb6SLionel Sambuc __cv_.notify_one(); 148*4684ddb6SLionel Sambuc } 149*4684ddb6SLionel Sambuc 150*4684ddb6SLionel Sambuc // recursive_timed_mutex 151*4684ddb6SLionel Sambuc 152*4684ddb6SLionel Sambuc recursive_timed_mutex::recursive_timed_mutex() 153*4684ddb6SLionel Sambuc : __count_(0), 154*4684ddb6SLionel Sambuc __id_(0) 155*4684ddb6SLionel Sambuc { 156*4684ddb6SLionel Sambuc } 157*4684ddb6SLionel Sambuc 158*4684ddb6SLionel Sambuc recursive_timed_mutex::~recursive_timed_mutex() 159*4684ddb6SLionel Sambuc { 160*4684ddb6SLionel Sambuc lock_guard<mutex> _(__m_); 161*4684ddb6SLionel Sambuc } 162*4684ddb6SLionel Sambuc 163*4684ddb6SLionel Sambuc void 164*4684ddb6SLionel Sambuc recursive_timed_mutex::lock() 165*4684ddb6SLionel Sambuc { 166*4684ddb6SLionel Sambuc pthread_t id = pthread_self(); 167*4684ddb6SLionel Sambuc unique_lock<mutex> lk(__m_); 168*4684ddb6SLionel Sambuc if (pthread_equal(id, __id_)) 169*4684ddb6SLionel Sambuc { 170*4684ddb6SLionel Sambuc if (__count_ == numeric_limits<size_t>::max()) 171*4684ddb6SLionel Sambuc __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); 172*4684ddb6SLionel Sambuc ++__count_; 173*4684ddb6SLionel Sambuc return; 174*4684ddb6SLionel Sambuc } 175*4684ddb6SLionel Sambuc while (__count_ != 0) 176*4684ddb6SLionel Sambuc __cv_.wait(lk); 177*4684ddb6SLionel Sambuc __count_ = 1; 178*4684ddb6SLionel Sambuc __id_ = id; 179*4684ddb6SLionel Sambuc } 180*4684ddb6SLionel Sambuc 181*4684ddb6SLionel Sambuc bool 182*4684ddb6SLionel Sambuc recursive_timed_mutex::try_lock() _NOEXCEPT 183*4684ddb6SLionel Sambuc { 184*4684ddb6SLionel Sambuc pthread_t id = pthread_self(); 185*4684ddb6SLionel Sambuc unique_lock<mutex> lk(__m_, try_to_lock); 186*4684ddb6SLionel Sambuc if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_))) 187*4684ddb6SLionel Sambuc { 188*4684ddb6SLionel Sambuc if (__count_ == numeric_limits<size_t>::max()) 189*4684ddb6SLionel Sambuc return false; 190*4684ddb6SLionel Sambuc ++__count_; 191*4684ddb6SLionel Sambuc __id_ = id; 192*4684ddb6SLionel Sambuc return true; 193*4684ddb6SLionel Sambuc } 194*4684ddb6SLionel Sambuc return false; 195*4684ddb6SLionel Sambuc } 196*4684ddb6SLionel Sambuc 197*4684ddb6SLionel Sambuc void 198*4684ddb6SLionel Sambuc recursive_timed_mutex::unlock() _NOEXCEPT 199*4684ddb6SLionel Sambuc { 200*4684ddb6SLionel Sambuc unique_lock<mutex> lk(__m_); 201*4684ddb6SLionel Sambuc if (--__count_ == 0) 202*4684ddb6SLionel Sambuc { 203*4684ddb6SLionel Sambuc __id_ = 0; 204*4684ddb6SLionel Sambuc lk.unlock(); 205*4684ddb6SLionel Sambuc __cv_.notify_one(); 206*4684ddb6SLionel Sambuc } 207*4684ddb6SLionel Sambuc } 208*4684ddb6SLionel Sambuc 209*4684ddb6SLionel Sambuc // If dispatch_once_f ever handles C++ exceptions, and if one can get to it 210*4684ddb6SLionel Sambuc // without illegal macros (unexpected macros not beginning with _UpperCase or 211*4684ddb6SLionel Sambuc // __lowercase), and if it stops spinning waiting threads, then call_once should 212*4684ddb6SLionel Sambuc // call into dispatch_once_f instead of here. Relevant radar this code needs to 213*4684ddb6SLionel Sambuc // keep in sync with: 7741191. 214*4684ddb6SLionel Sambuc 215*4684ddb6SLionel Sambuc static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 216*4684ddb6SLionel Sambuc static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; 217*4684ddb6SLionel Sambuc 218*4684ddb6SLionel Sambuc void 219*4684ddb6SLionel Sambuc __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) 220*4684ddb6SLionel Sambuc { 221*4684ddb6SLionel Sambuc pthread_mutex_lock(&mut); 222*4684ddb6SLionel Sambuc while (flag == 1) 223*4684ddb6SLionel Sambuc pthread_cond_wait(&cv, &mut); 224*4684ddb6SLionel Sambuc if (flag == 0) 225*4684ddb6SLionel Sambuc { 226*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 227*4684ddb6SLionel Sambuc try 228*4684ddb6SLionel Sambuc { 229*4684ddb6SLionel Sambuc #endif // _LIBCPP_NO_EXCEPTIONS 230*4684ddb6SLionel Sambuc flag = 1; 231*4684ddb6SLionel Sambuc pthread_mutex_unlock(&mut); 232*4684ddb6SLionel Sambuc func(arg); 233*4684ddb6SLionel Sambuc pthread_mutex_lock(&mut); 234*4684ddb6SLionel Sambuc flag = ~0ul; 235*4684ddb6SLionel Sambuc pthread_mutex_unlock(&mut); 236*4684ddb6SLionel Sambuc pthread_cond_broadcast(&cv); 237*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 238*4684ddb6SLionel Sambuc } 239*4684ddb6SLionel Sambuc catch (...) 240*4684ddb6SLionel Sambuc { 241*4684ddb6SLionel Sambuc pthread_mutex_lock(&mut); 242*4684ddb6SLionel Sambuc flag = 0ul; 243*4684ddb6SLionel Sambuc pthread_mutex_unlock(&mut); 244*4684ddb6SLionel Sambuc pthread_cond_broadcast(&cv); 245*4684ddb6SLionel Sambuc throw; 246*4684ddb6SLionel Sambuc } 247*4684ddb6SLionel Sambuc #endif // _LIBCPP_NO_EXCEPTIONS 248*4684ddb6SLionel Sambuc } 249*4684ddb6SLionel Sambuc else 250*4684ddb6SLionel Sambuc pthread_mutex_unlock(&mut); 251*4684ddb6SLionel Sambuc } 252*4684ddb6SLionel Sambuc 253*4684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD 254