1*4684ddb6SLionel Sambuc //===-------------------- condition_variable.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 #include "condition_variable" 11*4684ddb6SLionel Sambuc #include "thread" 12*4684ddb6SLionel Sambuc #include "system_error" 13*4684ddb6SLionel Sambuc #include "cassert" 14*4684ddb6SLionel Sambuc 15*4684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD 16*4684ddb6SLionel Sambuc 17*4684ddb6SLionel Sambuc condition_variable::~condition_variable() 18*4684ddb6SLionel Sambuc { 19*4684ddb6SLionel Sambuc pthread_cond_destroy(&__cv_); 20*4684ddb6SLionel Sambuc } 21*4684ddb6SLionel Sambuc 22*4684ddb6SLionel Sambuc void 23*4684ddb6SLionel Sambuc condition_variable::notify_one() _NOEXCEPT 24*4684ddb6SLionel Sambuc { 25*4684ddb6SLionel Sambuc pthread_cond_signal(&__cv_); 26*4684ddb6SLionel Sambuc } 27*4684ddb6SLionel Sambuc 28*4684ddb6SLionel Sambuc void 29*4684ddb6SLionel Sambuc condition_variable::notify_all() _NOEXCEPT 30*4684ddb6SLionel Sambuc { 31*4684ddb6SLionel Sambuc pthread_cond_broadcast(&__cv_); 32*4684ddb6SLionel Sambuc } 33*4684ddb6SLionel Sambuc 34*4684ddb6SLionel Sambuc void 35*4684ddb6SLionel Sambuc condition_variable::wait(unique_lock<mutex>& lk) 36*4684ddb6SLionel Sambuc { 37*4684ddb6SLionel Sambuc if (!lk.owns_lock()) 38*4684ddb6SLionel Sambuc __throw_system_error(EPERM, 39*4684ddb6SLionel Sambuc "condition_variable::wait: mutex not locked"); 40*4684ddb6SLionel Sambuc int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle()); 41*4684ddb6SLionel Sambuc if (ec) 42*4684ddb6SLionel Sambuc __throw_system_error(ec, "condition_variable wait failed"); 43*4684ddb6SLionel Sambuc } 44*4684ddb6SLionel Sambuc 45*4684ddb6SLionel Sambuc void 46*4684ddb6SLionel Sambuc condition_variable::__do_timed_wait(unique_lock<mutex>& lk, 47*4684ddb6SLionel Sambuc chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) 48*4684ddb6SLionel Sambuc { 49*4684ddb6SLionel Sambuc #if !defined(__minix) /* LSC: FIXME a loop with yield plus sleep? */ 50*4684ddb6SLionel Sambuc using namespace chrono; 51*4684ddb6SLionel Sambuc if (!lk.owns_lock()) 52*4684ddb6SLionel Sambuc __throw_system_error(EPERM, 53*4684ddb6SLionel Sambuc "condition_variable::timed wait: mutex not locked"); 54*4684ddb6SLionel Sambuc nanoseconds d = tp.time_since_epoch(); 55*4684ddb6SLionel Sambuc if (d > nanoseconds(0x59682F000000E941)) 56*4684ddb6SLionel Sambuc d = nanoseconds(0x59682F000000E941); 57*4684ddb6SLionel Sambuc timespec ts; 58*4684ddb6SLionel Sambuc seconds s = duration_cast<seconds>(d); 59*4684ddb6SLionel Sambuc typedef decltype(ts.tv_sec) ts_sec; 60*4684ddb6SLionel Sambuc _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); 61*4684ddb6SLionel Sambuc if (s.count() < ts_sec_max) 62*4684ddb6SLionel Sambuc { 63*4684ddb6SLionel Sambuc ts.tv_sec = static_cast<ts_sec>(s.count()); 64*4684ddb6SLionel Sambuc ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); 65*4684ddb6SLionel Sambuc } 66*4684ddb6SLionel Sambuc else 67*4684ddb6SLionel Sambuc { 68*4684ddb6SLionel Sambuc ts.tv_sec = ts_sec_max; 69*4684ddb6SLionel Sambuc ts.tv_nsec = giga::num - 1; 70*4684ddb6SLionel Sambuc } 71*4684ddb6SLionel Sambuc int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); 72*4684ddb6SLionel Sambuc if (ec != 0 && ec != ETIMEDOUT) 73*4684ddb6SLionel Sambuc #else 74*4684ddb6SLionel Sambuc int ec = EINVAL; 75*4684ddb6SLionel Sambuc #endif /* !defined(__minix) */ 76*4684ddb6SLionel Sambuc __throw_system_error(ec, "condition_variable timed_wait failed"); 77*4684ddb6SLionel Sambuc } 78*4684ddb6SLionel Sambuc 79*4684ddb6SLionel Sambuc void 80*4684ddb6SLionel Sambuc notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) 81*4684ddb6SLionel Sambuc { 82*4684ddb6SLionel Sambuc __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); 83*4684ddb6SLionel Sambuc } 84*4684ddb6SLionel Sambuc 85*4684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD 86