Index: include/__threading_support =================================================================== --- include/__threading_support +++ include/__threading_support @@ -194,7 +194,73 @@ pthread_setspecific(__key, __p); } -#else // !_LIBCPP_THREAD_API_PTHREAD +#elif defined(_LIBCPP_THREAD_API_EXTERNAL) + +// Mutex +#define _LIBCPP_MUTEX_INITIALIZER 0 +struct __libcpp_mutex_external; +typedef __libcpp_mutex_external* __libcpp_mutex_t; + +int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m); + +int __libcpp_mutex_lock(__libcpp_mutex_t* __m); + +int __libcpp_mutex_trylock(__libcpp_mutex_t* __m); + +int __libcpp_mutex_unlock(__libcpp_mutex_t* __m); + +int __libcpp_mutex_destroy(__libcpp_mutex_t* __m); + +// Condition variable +#define _LIBCPP_CONDVAR_INITIALIZER 0 +struct __libcpp_condvar_external; +typedef __libcpp_condvar_external* __libcpp_condvar_t; + +int __libcpp_condvar_signal(__libcpp_condvar_t* __cv); + +int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv); + +int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m); + +int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts); + +int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv); + +// Thread id +typedef unsigned long __libcpp_thread_id; + +// Returns non-zero if the thread ids are equal, otherwise 0 +int __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2); + +// Returns non-zero if t1 < t2, otherwise 0 +int __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2); + +// Thread +struct __libcpp_thread_external; +typedef __libcpp_thread_external* __libcpp_thread_t; + +int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__f)(void*), void* __arg); + +__libcpp_thread_id __libcpp_thread_get_current_id(); + +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t); + +int __libcpp_thread_join(__libcpp_thread_t* __t); + +int __libcpp_thread_detach(__libcpp_thread_t* __t); + +void __libcpp_thread_yield(); + +// Thread local storage +typedef unsigned long __libcpp_tl_key; + +int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit) (void*)); + +void* __libcpp_tl_get(__libcpp_tl_key __key); + +void __libcpp_tl_set(__libcpp_tl_key __key, void* __p); + +#else #error "No thread API selected." #endif Index: src/algorithm.cpp =================================================================== --- src/algorithm.cpp +++ src/algorithm.cpp @@ -48,14 +48,22 @@ template unsigned __sort5<__less&, long double*>(long double*, long double*, long double*, long double*, long double*, __less&); #ifndef _LIBCPP_HAS_NO_THREADS +# if defined(_LIBCPP_THREAD_API_EXTERNAL) +static mutex __rs_mut; +# define __LOCK_LOCK() __rs_mut.lock(); +# define __LOCK_UNLOCK() __rs_mut.unlock(); +# else static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; +# define __LOCK_LOCK() __libcpp_mutex_lock(&__rs_mut); +# define __LOCK_UNLOCK() __libcpp_mutex_unlock(&__rs_mut); +# endif #endif unsigned __rs_default::__c_ = 0; __rs_default::__rs_default() { #ifndef _LIBCPP_HAS_NO_THREADS - __libcpp_mutex_lock(&__rs_mut); + __LOCK_LOCK() #endif __c_ = 1; } @@ -69,7 +77,7 @@ { #ifndef _LIBCPP_HAS_NO_THREADS if (--__c_ == 0) - __libcpp_mutex_unlock(&__rs_mut); + __LOCK_UNLOCK() #else --__c_; #endif @@ -88,4 +96,9 @@ return __rs_default(); } +#ifndef _LIBCPP_HAS_NO_THREADS +# undef __LOCK_LOCK +# undef __LOCK_UNLOCK +#endif + _LIBCPP_END_NAMESPACE_STD Index: src/memory.cpp =================================================================== --- src/memory.cpp +++ src/memory.cpp @@ -127,6 +127,9 @@ #if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS) static const std::size_t __sp_mut_count = 16; +#if defined(_LIBCPP_THREAD_API_EXTERNAL) +static mutex mut_back_imp[__sp_mut_count]; +#else static __libcpp_mutex_t mut_back_imp[__sp_mut_count] = { _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, @@ -134,6 +137,7 @@ _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER }; +#endif static mutex* mut_back = reinterpret_cast(mut_back_imp); Index: src/mutex.cpp =================================================================== --- src/mutex.cpp +++ src/mutex.cpp @@ -195,8 +195,23 @@ // keep in sync with: 7741191. #ifndef _LIBCPP_HAS_NO_THREADS +# if defined(_LIBCPP_THREAD_API_EXTERNAL) +static mutex mut; +static condition_variable cv; +# define __LOCK_INIT() unique_lock lk(mut); +# define __LOCK_LOCK() lk.lock(); +# define __LOCK_UNLOCK() lk.unlock(); +# define __CV_WAIT_LOCK() cv.wait(lk); +# define __CV_NOTIFY_ALL() cv.notify_all(); +# else static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; +# define __LOCK_INIT() __libcpp_mutex_lock(&mut); +# define __LOCK_LOCK() __libcpp_mutex_lock(&mut); +# define __LOCK_UNLOCK() __libcpp_mutex_unlock(&mut); +# define __CV_WAIT_LOCK() __libcpp_condvar_wait(&cv, &mut); +# define __CV_NOTIFY_ALL() __libcpp_condvar_broadcast(&cv); +# endif #endif /// NOTE: Changes to flag are done via relaxed atomic stores @@ -225,9 +240,9 @@ #endif // _LIBCPP_NO_EXCEPTIONS } #else // !_LIBCPP_HAS_NO_THREADS - __libcpp_mutex_lock(&mut); + __LOCK_INIT() while (flag == 1) - __libcpp_condvar_wait(&cv, &mut); + __CV_WAIT_LOCK() if (flag == 0) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -235,28 +250,36 @@ { #endif // _LIBCPP_NO_EXCEPTIONS __libcpp_relaxed_store(&flag, 1ul); - __libcpp_mutex_unlock(&mut); + __LOCK_UNLOCK() func(arg); - __libcpp_mutex_lock(&mut); + __LOCK_LOCK() __libcpp_relaxed_store(&flag, ~0ul); - __libcpp_mutex_unlock(&mut); - __libcpp_condvar_broadcast(&cv); + __LOCK_UNLOCK() + __CV_NOTIFY_ALL() #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - __libcpp_mutex_lock(&mut); + __LOCK_LOCK() __libcpp_relaxed_store(&flag, 0ul); - __libcpp_mutex_unlock(&mut); - __libcpp_condvar_broadcast(&cv); + __LOCK_UNLOCK() + __CV_NOTIFY_ALL() throw; } #endif // _LIBCPP_NO_EXCEPTIONS } else - __libcpp_mutex_unlock(&mut); + __LOCK_UNLOCK() #endif // !_LIBCPP_HAS_NO_THREADS } +#ifndef _LIBCPP_HAS_NO_THREADS +# undef __LOCK_INIT +# undef __LOCK_LOCK +# undef __LOCK_UNLOCK +# undef __CV_WAIT_LOCK +# undef __CV_NOTIFY_ALL +#endif + _LIBCPP_END_NAMESPACE_STD