diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef __MVS__ # include <__support/ibm/nanosleep.h> @@ -149,6 +150,9 @@ // Semaphore typedef void* __libcpp_semaphore_t; +#if defined(_LIBCPP_HAS_THREAD_API_WIN32) +# define _LIBCPP_SEMAPHORE_MAX (::std::numeric_limits::max()) +#endif // Execute Once typedef void* __libcpp_exec_once_flag; diff --git a/libcxx/src/support/win32/thread_win32.cpp b/libcxx/src/support/win32/thread_win32.cpp --- a/libcxx/src/support/win32/thread_win32.cpp +++ b/libcxx/src/support/win32/thread_win32.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include <__threading_support> +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN #include #include #include @@ -37,6 +39,9 @@ static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), ""); static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), ""); +static_assert(sizeof(__libcpp_semaphore_t) == sizeof(HANDLE), ""); +static_assert(alignof(__libcpp_semaphore_t) == alignof(HANDLE), ""); + // Mutex int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { @@ -272,4 +277,37 @@ return 0; } +// Semaphores +bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) +{ + *(PHANDLE)__sem = CreateSemaphoreEx(nullptr, __init, _LIBCPP_SEMAPHORE_MAX, + nullptr, 0, SEMAPHORE_ALL_ACCESS); + return *__sem != nullptr; +} + +bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) +{ + CloseHandle(*(PHANDLE)__sem); + return true; +} + +bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) +{ + return ReleaseSemaphore(*(PHANDLE)__sem, 1, nullptr); +} + +bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) +{ + return WaitForSingleObjectEx(*(PHANDLE)__sem, INFINITE, false) == + WAIT_OBJECT_0; +} + +bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, + chrono::nanoseconds const& __ns) +{ + chrono::milliseconds __ms = std::chrono::ceil(__ns); + return WaitForSingleObjectEx(*(PHANDLE)__sem, __ms.count(), false) == + WAIT_OBJECT_0; +} + _LIBCPP_END_NAMESPACE_STD