Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -882,6 +882,8 @@ defined(__CloudABI__) || \ defined(__sun__) # define _LIBCPP_HAS_THREAD_API_PTHREAD +# elif defined(_WIN32) +# define _LIBCPP_HAS_THREAD_API_WIN32 # else # error "No thread API" # endif // _LIBCPP_HAS_THREAD_API Index: include/__threading_support =================================================================== --- include/__threading_support +++ include/__threading_support @@ -30,6 +30,237 @@ #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \ __libcpp_has_include(<__external_threading>) #include <__external_threading> +#elif defined(_WIN32) && defined(_LIBCPP_HAS_THREAD_API_WIN32) +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRA_LEAN +#include +#include +#include + +// Mutex +typedef CRITICAL_SECTION __libcpp_mutex_t; +#define _LIBCPP_MUTEX_INITIALIZER \ + { (PRTL_CRITICAL_SECTION_DEBUG) - 1, -1, 0, 0, 0, 0 } + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_mutex_lock(__libcpp_mutex_t *__m); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_mutex_destroy(__libcpp_mutex_t *__m); + +// Condition Variable +typedef CONDITION_VARIABLE __libcpp_condvar_t; +#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_condvar_signal(__libcpp_condvar_t *__cv); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, + timespec *__tm); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv); + +// Thread ID +typedef DWORD __libcpp_thread_id; + +inline _LIBCPP_INLINE_VISIBILITY +bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, + __libcpp_thread_id __rhs); + +inline _LIBCPP_INLINE_VISIBILITY +bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, + __libcpp_thread_id __rhs); + +// Thread +typedef HANDLE __libcpp_thread_t; + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), + void *__arg); + +inline _LIBCPP_INLINE_VISIBILITY +__libcpp_thread_id __libcpp_thread_get_current_id(); + +inline _LIBCPP_INLINE_VISIBILITY +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *_t); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_thread_join(__libcpp_thread_t *__t); + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_thread_detach(__libcpp_thread_t *__t); + +inline _LIBCPP_INLINE_VISIBILITY +void __libcpp_thread_yield(); + +// Thread Local Storage +typedef DWORD __libcpp_tls_key; + +inline _LIBCPP_INLINE_VISIBILITY +int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)); + +inline _LIBCPP_INLINE_VISIBILITY +void *__libcpp_tls_get(__libcpp_tls_key __key); + +inline _LIBCPP_INLINE_VISIBILITY +void __libcpp_tls_set(__libcpp_tls_key __key, void *__p); + + +// Mutex +int __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m) +{ + InitializeCriticalSection(__m); + return 0; +} + +int __libcpp_mutex_lock(__libcpp_mutex_t *__m) +{ + EnterCriticalSection(__m); + return 0; +} + +int __libcpp_mutex_trylock(__libcpp_mutex_t *__m) +{ + return TryEnterCriticalSection(__m); +} + +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) +{ + LeaveCriticalSection(__m); + return 0; +} + +int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) +{ + DeleteCriticalSection(__m); + return 0; +} + +// Condition Variable +int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) +{ + WakeConditionVariable(__cv); + return 0; +} + +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) +{ + WakeAllConditionVariable(__cv); + return 0; +} + +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) +{ + SleepConditionVariableCS(__cv, __m, INFINITE); + return 0; +} + +int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, + timespec *__ts) +{ + using namespace _VSTD::chrono; + auto timeout = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); + // TODO(compnerd) handle timeouts < 10ms + // TODO(compnerd) handle spurious timeout + if (!SleepConditionVariableCS(__cv, __m, + duration_cast(timeout).count())) + return GetLastError(); + return 0; +} + +int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) +{ + static_cast(__cv); + return 0; +} + +// Thread ID +bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, + __libcpp_thread_id __rhs) +{ + return __lhs == __rhs; +} + +bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) +{ + return __lhs < __rhs; +} + +// Thread +int __libcpp_thread_create(__libcpp_thread_t *__t, + unsigned int (* WINAPI __func)(void *), void *__arg) +{ + *__t = + reinterpret_cast(_beginthreadex(NULL, 0, __func, __arg, 0, NULL)); + if (*__t) + return 0; + return GetLastError(); +} + +__libcpp_thread_id __libcpp_thread_get_current_id() +{ + return GetCurrentThreadId(); +} + +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) +{ + return GetThreadId(*__t); +} + +int __libcpp_thread_join(__libcpp_thread_t *__t) +{ + if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) + return GetLastError(); + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +int __libcpp_thread_detach(__libcpp_thread_t *__t) +{ + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +void __libcpp_thread_yield() +{ + SwitchToThread(); +} + +// Thread Local Storage +int __libcpp_tls_create(__libcpp_tls_key *__key, void (* WINAPI __at_exit)(void *)) +{ + *__key = FlsAlloc(__at_exit); + if (*__key == FLS_OUT_OF_INDEXES) + return GetLastError(); + return 0; +} + +void *__libcpp_tls_get(__libcpp_tls_key __key) +{ + return FlsGetValue(__key); +} + +void __libcpp_tls_set(__libcpp_tls_key __key, void *__p) +{ + FlsSetValue(__key, __p); +} + #else #include #include Index: src/algorithm.cpp =================================================================== --- src/algorithm.cpp +++ src/algorithm.cpp @@ -48,7 +48,10 @@ template unsigned __sort5<__less&, long double*>(long double*, long double*, long double*, long double*, long double*, __less&); #ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; +#if !defined(_WIN32) +_LIBCPP_SAFE_STATIC +#endif +static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; #endif unsigned __rs_default::__c_ = 0; Index: src/memory.cpp =================================================================== --- src/memory.cpp +++ src/memory.cpp @@ -155,7 +155,10 @@ #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) _LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16; -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] = +#if !defined(_WIN32) +_LIBCPP_SAFE_STATIC +#endif +static __libcpp_mutex_t mut_back[__sp_mut_count] = { _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, Index: src/mutex.cpp =================================================================== --- src/mutex.cpp +++ src/mutex.cpp @@ -195,7 +195,10 @@ // keep in sync with: 7741191. #ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; +#if !defined(_WIN32) +_LIBCPP_SAFE_STATIC +#endif +static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; _LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; #endif