Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -812,6 +812,20 @@ # define _LIBCPP_WEAK __attribute__((__weak__)) #endif +// Thread API +#ifndef _LIBCPP_HAS_NO_THREADS +# if defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__linux__) || \ + defined(__APPLE__) || \ + defined(__CloudABI__) +# define _LIBCPP_THREAD_API_PTHREAD +# else +# error "No thread API" +# endif // _LIBCPP_THREAD_API +#endif // _LIBCPP_HAS_NO_THREADS + + #if defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(_LIBCPP_HAS_NO_THREADS) # error _LIBCPP_HAS_NO_MONOTONIC_CLOCK may only be defined when \ _LIBCPP_HAS_NO_THREADS is defined. Index: include/__mutex_base =================================================================== --- include/__mutex_base +++ include/__mutex_base @@ -14,9 +14,7 @@ #include <__config> #include #include -#ifndef _LIBCPP_HAS_NO_THREADS -#include -#endif +#include <__os_support> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -36,16 +34,17 @@ class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { - pthread_mutex_t __m_; + typedef __libcpp_os_support::__os_mutex __mutex_type; + __mutex_type __m_; public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_CONSTEXPR - constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {} + constexpr mutex() _NOEXCEPT : __m_(__OS_MUTEX_INITIALIZER) {} #else - mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;} + mutex() _NOEXCEPT {__m_ = (__mutex_type)__OS_MUTEX_INITIALIZER;} #endif - ~mutex(); + ~mutex(); private: mutex(const mutex&);// = delete; @@ -56,7 +55,7 @@ bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); - typedef pthread_mutex_t* native_handle_type; + typedef __mutex_type* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; @@ -276,13 +275,14 @@ class _LIBCPP_TYPE_VIS condition_variable { - pthread_cond_t __cv_; + typedef __libcpp_os_support::__os_cond_var __cond_var_type; + __cond_var_type __cv_; public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_CONSTEXPR - constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {} + constexpr condition_variable() : __cv_(__OS_COND_INITIALIZER) {} #else - condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;} + condition_variable() {__cv_ = (__os_cond_var)__OS_COND_INITIALIZER;} #endif ~condition_variable(); @@ -321,7 +321,7 @@ const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); - typedef pthread_cond_t* native_handle_type; + typedef __cond_var_type* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} private: Index: include/__os_support =================================================================== --- /dev/null +++ include/__os_support @@ -0,0 +1,106 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_OS_SUPPORT +#define _LIBCPP_OS_SUPPORT + +#ifndef _LIBCPP_HAS_NO_THREADS + +#if defined(_LIBCPP_THREAD_API_PTHREAD) + +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __libcpp_os_support +{ +// Mutex +#define __OS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t __os_mutex; + +// Recursive mutex +typedef pthread_mutex_t __os_recursive_mutex; + +// Condition variable +#define __OS_COND_INITIALIZER PTHREAD_COND_INITIALIZER +typedef pthread_cond_t __os_cond_var; + +// Thread id +typedef pthread_t __os_thread_id; + +inline _LIBCPP_INLINE_VISIBILITY +int __os_thread_id_compare(__os_thread_id t1, __os_thread_id t2) +{ + return pthread_equal(t1, t2) != 0 ? 0 : (t1 < t2 ? -1 : 1); +} + +// Thread +typedef pthread_t __os_thread; +_LIBCPP_CONSTEXPR pthread_t __os_thread_init = 0; + +template +inline _LIBCPP_INLINE_VISIBILITY +int __os_thread_create(__os_thread* __t, _Func&& __f, _Arg&& __arg) +{ + return pthread_create(__t, 0, __f, __arg); +} + +inline _LIBCPP_INLINE_VISIBILITY +__os_thread_id __os_thread_get_current_id() +{ + return pthread_self(); +} + +inline _LIBCPP_INLINE_VISIBILITY +__os_thread_id __os_thread_get_id(__os_thread __t) +{ + return __t; +} + +inline _LIBCPP_INLINE_VISIBILITY +void __os_thread_yield() +{ + sched_yield(); +} + +// Thread local storage +typedef pthread_key_t __os_tl_key; + +template +inline _LIBCPP_INLINE_VISIBILITY +int __os_tl_create(__os_tl_key* __key, _Func&& __at_exit) +{ + return pthread_key_create(__key, __at_exit); +} + +inline _LIBCPP_INLINE_VISIBILITY +void* __os_tl_get(__os_tl_key __key) +{ + return pthread_getspecific(__key); +} + +inline _LIBCPP_INLINE_VISIBILITY +void __os_tl_set(__os_tl_key __key, void* __p) +{ + pthread_setspecific(__key, __p); +} + +} // namespace __libcpp_os_support + +_LIBCPP_END_NAMESPACE_STD + +#else // !_LIBCPP_THREAD_API_PTHREAD + #error "No thread API selected." +#endif + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP_OS_SUPPORT Index: include/mutex =================================================================== --- include/mutex +++ include/mutex @@ -179,9 +179,8 @@ #ifndef _LIBCPP_HAS_NO_VARIADICS #include #endif -#ifndef _LIBCPP_HAS_NO_THREADS -#include -#endif +#include <__os_support> +#include #include <__undef_min_max> @@ -195,7 +194,8 @@ class _LIBCPP_TYPE_VIS recursive_mutex { - pthread_mutex_t __m_; + typedef __libcpp_os_support::__os_mutex __mutex_type; + __mutex_type __m_; public: recursive_mutex(); @@ -208,9 +208,9 @@ public: void lock(); bool try_lock() _NOEXCEPT; - void unlock() _NOEXCEPT; + void unlock() _NOEXCEPT; - typedef pthread_mutex_t* native_handle_type; + typedef __mutex_type* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; @@ -259,10 +259,10 @@ class _LIBCPP_TYPE_VIS recursive_timed_mutex { - mutex __m_; - condition_variable __cv_; - size_t __count_; - pthread_t __id_; + mutex __m_; + condition_variable __cv_; + size_t __count_; + __libcpp_os_support::__os_thread_id __id_; public: recursive_timed_mutex(); ~recursive_timed_mutex(); @@ -288,9 +288,10 @@ recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; - pthread_t __id = pthread_self(); + using namespace __libcpp_os_support; + __os_thread_id __id = __os_thread_get_current_id(); unique_lock lk(__m_); - if (pthread_equal(__id, __id_)) + if (__os_thread_id_compare(__id, __id_) == 0) { if (__count_ == numeric_limits::max()) return false; @@ -362,7 +363,7 @@ break; } } - sched_yield(); + __libcpp_os_support::__os_thread_yield(); { unique_lock<_L1> __u1(__l1); if (__l0.try_lock()) @@ -371,7 +372,7 @@ break; } } - sched_yield(); + __libcpp_os_support::__os_thread_yield(); } } @@ -396,7 +397,7 @@ } } ++__i; - sched_yield(); + __libcpp_os_support::__os_thread_yield(); break; case 1: { @@ -412,7 +413,7 @@ __i = 0; else __i += 2; - sched_yield(); + __libcpp_os_support::__os_thread_yield(); break; default: __lock_first(__i - 2, __l2, __l3..., __l0, __l1); Index: include/thread =================================================================== --- include/thread +++ include/thread @@ -98,8 +98,7 @@ #ifndef _LIBCPP_HAS_NO_VARIADICS #include #endif -#include -#include +#include <__os_support> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -137,7 +136,7 @@ template class __thread_specific_ptr { - pthread_key_t __key_; + __libcpp_os_support::__os_tl_key __key_; // Only __thread_local_data() may construct a __thread_specific_ptr // and only with _Tp == __thread_struct. @@ -155,7 +154,7 @@ ~__thread_specific_ptr(); _LIBCPP_INLINE_VISIBILITY - pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));} + pointer get() const {return static_cast<_Tp*>(__libcpp_os_support::__os_tl_get(__key_));} _LIBCPP_INLINE_VISIBILITY pointer operator*() const {return *get();} _LIBCPP_INLINE_VISIBILITY @@ -174,7 +173,9 @@ template __thread_specific_ptr<_Tp>::__thread_specific_ptr() { - int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); + int __ec = __libcpp_os_support::__os_tl_create( + &__key_, + &__thread_specific_ptr::__at_thread_exit); #ifndef _LIBCPP_NO_EXCEPTIONS if (__ec) throw system_error(error_code(__ec, system_category()), @@ -196,7 +197,7 @@ __thread_specific_ptr<_Tp>::release() { pointer __p = get(); - pthread_setspecific(__key_, 0); + __libcpp_os_support::__os_tl_set(__key_, 0); return __p; } @@ -205,7 +206,7 @@ __thread_specific_ptr<_Tp>::reset(pointer __p) { pointer __p_old = get(); - pthread_setspecific(__key_, __p); + __libcpp_os_support::__os_tl_set(__key_, __p); delete __p_old; } @@ -226,7 +227,7 @@ // FIXME: pthread_t is a pointer on Darwin but a long on Linux. // NULL is the no-thread value on Darwin. Someone needs to check // on other platforms. We assume 0 works everywhere for now. - pthread_t __id_; + __libcpp_os_support::__os_thread_id __id_; public: _LIBCPP_INLINE_VISIBILITY @@ -234,13 +235,13 @@ friend _LIBCPP_INLINE_VISIBILITY bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - {return __x.__id_ == __y.__id_;} + {return __libcpp_os_support::__os_thread_id_compare(__x.__id_, __y.__id_) == 0;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__x == __y);} friend _LIBCPP_INLINE_VISIBILITY bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __x.__id_ < __y.__id_;} + {return __libcpp_os_support::__os_thread_id_compare(__x.__id_, __y.__id_) < 0;} friend _LIBCPP_INLINE_VISIBILITY bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT {return !(__y < __x);} @@ -260,7 +261,7 @@ private: _LIBCPP_INLINE_VISIBILITY - __thread_id(pthread_t __id) : __id_(__id) {} + __thread_id(__libcpp_os_support::__os_thread_id __id) : __id_(__id) {} friend __thread_id this_thread::get_id() _NOEXCEPT; friend class _LIBCPP_TYPE_VIS thread; @@ -274,7 +275,7 @@ _LIBCPP_INLINE_VISIBILITY size_t operator()(__thread_id __v) const { - return hash()(__v.__id_); + return hash<__libcpp_os_support::__os_thread_id>()(__v.__id_); } }; @@ -285,23 +286,24 @@ __thread_id get_id() _NOEXCEPT { - return pthread_self(); + return __libcpp_os_support::__os_thread_get_current_id(); } } // this_thread class _LIBCPP_TYPE_VIS thread { - pthread_t __t_; + typedef __libcpp_os_support::__os_thread __thread_type; + __thread_type __t_; thread(const thread&); thread& operator=(const thread&); public: typedef __thread_id id; - typedef pthread_t native_handle_type; + typedef __thread_type native_handle_type; _LIBCPP_INLINE_VISIBILITY - thread() _NOEXCEPT : __t_(0) {} + thread() _NOEXCEPT : __t_(__libcpp_os_support::__os_thread_init) {} #ifndef _LIBCPP_HAS_NO_VARIADICS template (__f)), __decay_copy(_VSTD::forward<_Args>(__args))...)); - int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); + int __ec = __libcpp_os_support::__os_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); if (__ec == 0) __p.release(); else @@ -405,7 +407,7 @@ typedef __thread_invoke_pair<_Fp> _InvokePair; typedef std::unique_ptr<_InvokePair> _PairPtr; _PairPtr __pp(new _InvokePair(__f)); - int __ec = pthread_create(&__t_, 0, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); + int __ec = __libcpp_os_support::__os_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); if (__ec == 0) __pp.release(); else @@ -480,7 +482,7 @@ } inline _LIBCPP_INLINE_VISIBILITY -void yield() _NOEXCEPT {sched_yield();} +void yield() _NOEXCEPT {__libcpp_os_support::__os_thread_yield();} } // this_thread Index: src/algorithm.cpp =================================================================== --- src/algorithm.cpp +++ src/algorithm.cpp @@ -48,14 +48,18 @@ template unsigned __sort5<__less&, long double*>(long double*, long double*, long double*, long double*, long double*, __less&); #ifndef _LIBCPP_HAS_NO_THREADS -static pthread_mutex_t __rs_mut = PTHREAD_MUTEX_INITIALIZER; +static __libcpp_os_support::__os_mutex __rs_mut = __OS_MUTEX_INITIALIZER; #endif unsigned __rs_default::__c_ = 0; __rs_default::__rs_default() { #ifndef _LIBCPP_HAS_NO_THREADS +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_mutex_lock(&__rs_mut); +#else + #error "Not implemented for the selected thread API." +#endif #endif __c_ = 1; } @@ -69,8 +73,12 @@ { #ifndef _LIBCPP_HAS_NO_THREADS if (--__c_ == 0) +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_mutex_unlock(&__rs_mut); #else + #error "Not implemented for the selected thread API." +#endif +#else --__c_; #endif } Index: src/condition_variable.cpp =================================================================== --- src/condition_variable.cpp +++ src/condition_variable.cpp @@ -18,21 +18,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD +using namespace __libcpp_os_support; + condition_variable::~condition_variable() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_cond_destroy(&__cv_); +#else + #error "Not implemented for the selected thread API." +#endif } void condition_variable::notify_one() _NOEXCEPT { +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_cond_signal(&__cv_); +#else + #error "Not implemented for the selected thread API." +#endif } void condition_variable::notify_all() _NOEXCEPT { +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_cond_broadcast(&__cv_); +#else + #error "Not implemented for the selected thread API." +#endif } void @@ -41,7 +55,11 @@ if (!lk.owns_lock()) __throw_system_error(EPERM, "condition_variable::wait: mutex not locked"); +#if defined(_LIBCPP_THREAD_API_PTHREAD) int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle()); +#else + #error "Not implemented for the selected thread API." +#endif if (ec) __throw_system_error(ec, "condition_variable wait failed"); } @@ -50,10 +68,10 @@ condition_variable::__do_timed_wait(unique_lock& lk, chrono::time_point tp) _NOEXCEPT { - using namespace chrono; if (!lk.owns_lock()) __throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked"); + using namespace chrono; nanoseconds d = tp.time_since_epoch(); if (d > nanoseconds(0x59682F000000E941)) d = nanoseconds(0x59682F000000E941); @@ -71,7 +89,11 @@ ts.tv_sec = ts_sec_max; ts.tv_nsec = giga::num - 1; } +#if defined(_LIBCPP_THREAD_API_PTHREAD) int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); +#else + #error "Not implemented for the selected thread API." +#endif if (ec != 0 && ec != ETIMEDOUT) __throw_system_error(ec, "condition_variable timed_wait failed"); } Index: src/memory.cpp =================================================================== --- src/memory.cpp +++ src/memory.cpp @@ -127,12 +127,12 @@ #if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS) static const std::size_t __sp_mut_count = 16; -static pthread_mutex_t mut_back_imp[__sp_mut_count] = +static __libcpp_os_support::__os_mutex mut_back_imp[__sp_mut_count] = { - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER + __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, + __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, + __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, + __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER, __OS_MUTEX_INITIALIZER }; static mutex* mut_back = reinterpret_cast(mut_back_imp); Index: src/mutex.cpp =================================================================== --- src/mutex.cpp +++ src/mutex.cpp @@ -21,15 +21,25 @@ const try_to_lock_t try_to_lock = {}; const adopt_lock_t adopt_lock = {}; +using namespace __libcpp_os_support; + mutex::~mutex() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_mutex_destroy(&__m_); +#else + #error "Not implemented for the selected thread API." +#endif } void mutex::lock() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) int ec = pthread_mutex_lock(&__m_); +#else + #error "Not implemented for the selected thread API." +#endif if (ec) __throw_system_error(ec, "mutex lock failed"); } @@ -37,13 +47,21 @@ bool mutex::try_lock() _NOEXCEPT { +#if defined(_LIBCPP_THREAD_API_PTHREAD) return pthread_mutex_trylock(&__m_) == 0; +#else + #error "Not implemented for the selected thread API." +#endif } void mutex::unlock() _NOEXCEPT { +#if defined(_LIBCPP_THREAD_API_PTHREAD) int ec = pthread_mutex_unlock(&__m_); +#else + #error "Not implemented for the selected thread API." +#endif (void)ec; assert(ec == 0); } @@ -52,6 +70,7 @@ recursive_mutex::recursive_mutex() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_mutexattr_t attr; int ec = pthread_mutexattr_init(&attr); if (ec) @@ -77,11 +96,18 @@ return; fail: __throw_system_error(ec, "recursive_mutex constructor failed"); +#else + #error "Not implemented for the selected thread API." +#endif } recursive_mutex::~recursive_mutex() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) int e = pthread_mutex_destroy(&__m_); +#else + #error "Not implemented for the selected thread API." +#endif (void)e; assert(e == 0); } @@ -89,7 +115,11 @@ void recursive_mutex::lock() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) int ec = pthread_mutex_lock(&__m_); +#else + #error "Not implemented for the selected thread API." +#endif if (ec) __throw_system_error(ec, "recursive_mutex lock failed"); } @@ -97,7 +127,11 @@ void recursive_mutex::unlock() _NOEXCEPT { +#if defined(_LIBCPP_THREAD_API_PTHREAD) int e = pthread_mutex_unlock(&__m_); +#else + #error "Not implemented for the selected thread API." +#endif (void)e; assert(e == 0); } @@ -105,7 +139,11 @@ bool recursive_mutex::try_lock() _NOEXCEPT { +#if defined(_LIBCPP_THREAD_API_PTHREAD) return pthread_mutex_trylock(&__m_) == 0; +#else + #error "Not implemented for the selected thread API." +#endif } // timed_mutex @@ -165,9 +203,9 @@ void recursive_timed_mutex::lock() { - pthread_t id = pthread_self(); + __os_thread_id id = __os_thread_get_current_id(); unique_lock lk(__m_); - if (pthread_equal(id, __id_)) + if (__os_thread_id_compare(id, __id_) == 0) { if (__count_ == numeric_limits::max()) __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); @@ -183,9 +221,9 @@ bool recursive_timed_mutex::try_lock() _NOEXCEPT { - pthread_t id = pthread_self(); + __os_thread_id id = __os_thread_get_current_id(); unique_lock lk(__m_, try_to_lock); - if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_))) + if (lk.owns_lock() && (__count_ == 0 || __os_thread_id_compare(id, __id_) == 0)) { if (__count_ == numeric_limits::max()) return false; @@ -210,22 +248,17 @@ #endif // !_LIBCPP_HAS_NO_THREADS +#if !defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_THREAD_API_PTHREAD) // If dispatch_once_f ever handles C++ exceptions, and if one can get to it // without illegal macros (unexpected macros not beginning with _UpperCase or // __lowercase), and if it stops spinning waiting threads, then call_once should // call into dispatch_once_f instead of here. Relevant radar this code needs to // keep in sync with: 7741191. - -#ifndef _LIBCPP_HAS_NO_THREADS static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; #endif -/// NOTE: Changes to flag are done via relaxed atomic stores -/// even though the accesses are protected by a mutex because threads -/// just entering 'call_once` concurrently read from flag. -void -__call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) +void __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) { #if defined(_LIBCPP_HAS_NO_THREADS) if (flag == 0) @@ -246,7 +279,8 @@ } #endif // _LIBCPP_NO_EXCEPTIONS } -#else // !_LIBCPP_HAS_NO_THREADS +#else // !LIBCPP_HAS_NO_THREADS +#if defined(_LIBCPP_THREAD_API_PTHREAD) pthread_mutex_lock(&mut); while (flag == 1) pthread_cond_wait(&cv, &mut); @@ -277,8 +311,10 @@ } else pthread_mutex_unlock(&mut); -#endif // !_LIBCPP_HAS_NO_THREADS - +#else // !_LIBCPP_THREAD_API_PTHREAD + #error "Not implemented for the selected thread API." +#endif // _LIBCPP_THREAD_API_PTHREAD +#endif // _LIBCPP_HAS_NO_THREADS } _LIBCPP_END_NAMESPACE_STD Index: src/thread.cpp =================================================================== --- src/thread.cpp +++ src/thread.cpp @@ -37,6 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD +using namespace __libcpp_os_support; + thread::~thread() { if (__t_ != 0) @@ -46,7 +48,11 @@ void thread::join() { +#if defined(_LIBCPP_THREAD_API_PTHREAD) int ec = pthread_join(__t_, 0); +#else + #error "Not implemented for the selected thread API." +#endif #ifndef _LIBCPP_NO_EXCEPTIONS if (ec) throw system_error(error_code(ec, system_category()), "thread::join failed"); @@ -62,7 +68,11 @@ int ec = EINVAL; if (__t_ != 0) { +#if defined(_LIBCPP_THREAD_API_PTHREAD) ec = pthread_detach(__t_); +#else + #error "Not implemented for the selected thread API." +#endif if (ec == 0) __t_ = 0; } @@ -109,8 +119,7 @@ namespace this_thread { -void -sleep_for(const chrono::nanoseconds& ns) +void sleep_for(const chrono::nanoseconds& ns) { using namespace chrono; if (ns > nanoseconds::zero()) @@ -135,8 +144,7 @@ } } -} // this_thread - +} __thread_specific_ptr<__thread_struct>& __thread_local_data() {