1*76d0caaeSpatrick //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick
946035553Spatrick #include <__threading_support>
10*76d0caaeSpatrick #define NOMINMAX
11*76d0caaeSpatrick #define WIN32_LEAN_AND_MEAN
1246035553Spatrick #include <windows.h>
1346035553Spatrick #include <process.h>
1446035553Spatrick #include <fibersapi.h>
1546035553Spatrick
1646035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
1746035553Spatrick
1846035553Spatrick static_assert(sizeof(__libcpp_mutex_t) == sizeof(SRWLOCK), "");
1946035553Spatrick static_assert(alignof(__libcpp_mutex_t) == alignof(SRWLOCK), "");
2046035553Spatrick
2146035553Spatrick static_assert(sizeof(__libcpp_recursive_mutex_t) == sizeof(CRITICAL_SECTION),
2246035553Spatrick "");
2346035553Spatrick static_assert(alignof(__libcpp_recursive_mutex_t) == alignof(CRITICAL_SECTION),
2446035553Spatrick "");
2546035553Spatrick
2646035553Spatrick static_assert(sizeof(__libcpp_condvar_t) == sizeof(CONDITION_VARIABLE), "");
2746035553Spatrick static_assert(alignof(__libcpp_condvar_t) == alignof(CONDITION_VARIABLE), "");
2846035553Spatrick
2946035553Spatrick static_assert(sizeof(__libcpp_exec_once_flag) == sizeof(INIT_ONCE), "");
3046035553Spatrick static_assert(alignof(__libcpp_exec_once_flag) == alignof(INIT_ONCE), "");
3146035553Spatrick
3246035553Spatrick static_assert(sizeof(__libcpp_thread_id) == sizeof(DWORD), "");
3346035553Spatrick static_assert(alignof(__libcpp_thread_id) == alignof(DWORD), "");
3446035553Spatrick
3546035553Spatrick static_assert(sizeof(__libcpp_thread_t) == sizeof(HANDLE), "");
3646035553Spatrick static_assert(alignof(__libcpp_thread_t) == alignof(HANDLE), "");
3746035553Spatrick
3846035553Spatrick static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), "");
3946035553Spatrick static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), "");
4046035553Spatrick
4146035553Spatrick // Mutex
__libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t * __m)4246035553Spatrick int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
4346035553Spatrick {
4446035553Spatrick InitializeCriticalSection((LPCRITICAL_SECTION)__m);
4546035553Spatrick return 0;
4646035553Spatrick }
4746035553Spatrick
__libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t * __m)4846035553Spatrick int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
4946035553Spatrick {
5046035553Spatrick EnterCriticalSection((LPCRITICAL_SECTION)__m);
5146035553Spatrick return 0;
5246035553Spatrick }
5346035553Spatrick
__libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t * __m)5446035553Spatrick bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
5546035553Spatrick {
5646035553Spatrick return TryEnterCriticalSection((LPCRITICAL_SECTION)__m) != 0;
5746035553Spatrick }
5846035553Spatrick
__libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t * __m)5946035553Spatrick int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
6046035553Spatrick {
6146035553Spatrick LeaveCriticalSection((LPCRITICAL_SECTION)__m);
6246035553Spatrick return 0;
6346035553Spatrick }
6446035553Spatrick
__libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t * __m)6546035553Spatrick int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
6646035553Spatrick {
6746035553Spatrick DeleteCriticalSection((LPCRITICAL_SECTION)__m);
6846035553Spatrick return 0;
6946035553Spatrick }
7046035553Spatrick
__libcpp_mutex_lock(__libcpp_mutex_t * __m)7146035553Spatrick int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
7246035553Spatrick {
7346035553Spatrick AcquireSRWLockExclusive((PSRWLOCK)__m);
7446035553Spatrick return 0;
7546035553Spatrick }
7646035553Spatrick
__libcpp_mutex_trylock(__libcpp_mutex_t * __m)7746035553Spatrick bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
7846035553Spatrick {
7946035553Spatrick return TryAcquireSRWLockExclusive((PSRWLOCK)__m) != 0;
8046035553Spatrick }
8146035553Spatrick
__libcpp_mutex_unlock(__libcpp_mutex_t * __m)8246035553Spatrick int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
8346035553Spatrick {
8446035553Spatrick ReleaseSRWLockExclusive((PSRWLOCK)__m);
8546035553Spatrick return 0;
8646035553Spatrick }
8746035553Spatrick
__libcpp_mutex_destroy(__libcpp_mutex_t * __m)8846035553Spatrick int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
8946035553Spatrick {
9046035553Spatrick static_cast<void>(__m);
9146035553Spatrick return 0;
9246035553Spatrick }
9346035553Spatrick
9446035553Spatrick // Condition Variable
__libcpp_condvar_signal(__libcpp_condvar_t * __cv)9546035553Spatrick int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
9646035553Spatrick {
9746035553Spatrick WakeConditionVariable((PCONDITION_VARIABLE)__cv);
9846035553Spatrick return 0;
9946035553Spatrick }
10046035553Spatrick
__libcpp_condvar_broadcast(__libcpp_condvar_t * __cv)10146035553Spatrick int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
10246035553Spatrick {
10346035553Spatrick WakeAllConditionVariable((PCONDITION_VARIABLE)__cv);
10446035553Spatrick return 0;
10546035553Spatrick }
10646035553Spatrick
__libcpp_condvar_wait(__libcpp_condvar_t * __cv,__libcpp_mutex_t * __m)10746035553Spatrick int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
10846035553Spatrick {
10946035553Spatrick SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, INFINITE, 0);
11046035553Spatrick return 0;
11146035553Spatrick }
11246035553Spatrick
__libcpp_condvar_timedwait(__libcpp_condvar_t * __cv,__libcpp_mutex_t * __m,__libcpp_timespec_t * __ts)11346035553Spatrick int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
11446035553Spatrick __libcpp_timespec_t *__ts)
11546035553Spatrick {
11646035553Spatrick using namespace _VSTD::chrono;
11746035553Spatrick
11846035553Spatrick auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
11946035553Spatrick auto abstime =
12046035553Spatrick system_clock::time_point(duration_cast<system_clock::duration>(duration));
12146035553Spatrick auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
12246035553Spatrick
12346035553Spatrick if (!SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m,
12446035553Spatrick timeout_ms.count() > 0 ? timeout_ms.count()
12546035553Spatrick : 0,
12646035553Spatrick 0))
12746035553Spatrick {
12846035553Spatrick auto __ec = GetLastError();
12946035553Spatrick return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
13046035553Spatrick }
13146035553Spatrick return 0;
13246035553Spatrick }
13346035553Spatrick
__libcpp_condvar_destroy(__libcpp_condvar_t * __cv)13446035553Spatrick int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
13546035553Spatrick {
13646035553Spatrick static_cast<void>(__cv);
13746035553Spatrick return 0;
13846035553Spatrick }
13946035553Spatrick
14046035553Spatrick // Execute Once
14146035553Spatrick static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK
__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once,PVOID __parameter,PVOID * __context)14246035553Spatrick __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
14346035553Spatrick PVOID *__context)
14446035553Spatrick {
14546035553Spatrick static_cast<void>(__init_once);
14646035553Spatrick static_cast<void>(__context);
14746035553Spatrick
14846035553Spatrick void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
14946035553Spatrick init_routine();
15046035553Spatrick return TRUE;
15146035553Spatrick }
15246035553Spatrick
__libcpp_execute_once(__libcpp_exec_once_flag * __flag,void (* __init_routine)(void))15346035553Spatrick int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
15446035553Spatrick void (*__init_routine)(void))
15546035553Spatrick {
15646035553Spatrick if (!InitOnceExecuteOnce((PINIT_ONCE)__flag, __libcpp_init_once_execute_once_thunk,
15746035553Spatrick reinterpret_cast<void *>(__init_routine), NULL))
15846035553Spatrick return GetLastError();
15946035553Spatrick return 0;
16046035553Spatrick }
16146035553Spatrick
16246035553Spatrick // Thread ID
__libcpp_thread_id_equal(__libcpp_thread_id __lhs,__libcpp_thread_id __rhs)16346035553Spatrick bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
16446035553Spatrick __libcpp_thread_id __rhs)
16546035553Spatrick {
16646035553Spatrick return __lhs == __rhs;
16746035553Spatrick }
16846035553Spatrick
__libcpp_thread_id_less(__libcpp_thread_id __lhs,__libcpp_thread_id __rhs)16946035553Spatrick bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
17046035553Spatrick {
17146035553Spatrick return __lhs < __rhs;
17246035553Spatrick }
17346035553Spatrick
17446035553Spatrick // Thread
17546035553Spatrick struct __libcpp_beginthreadex_thunk_data
17646035553Spatrick {
17746035553Spatrick void *(*__func)(void *);
17846035553Spatrick void *__arg;
17946035553Spatrick };
18046035553Spatrick
18146035553Spatrick static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI
__libcpp_beginthreadex_thunk(void * __raw_data)18246035553Spatrick __libcpp_beginthreadex_thunk(void *__raw_data)
18346035553Spatrick {
18446035553Spatrick auto *__data =
18546035553Spatrick static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
18646035553Spatrick auto *__func = __data->__func;
18746035553Spatrick void *__arg = __data->__arg;
18846035553Spatrick delete __data;
18946035553Spatrick return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
19046035553Spatrick }
19146035553Spatrick
__libcpp_thread_isnull(const __libcpp_thread_t * __t)19246035553Spatrick bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
19346035553Spatrick return *__t == 0;
19446035553Spatrick }
19546035553Spatrick
__libcpp_thread_create(__libcpp_thread_t * __t,void * (* __func)(void *),void * __arg)19646035553Spatrick int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
19746035553Spatrick void *__arg)
19846035553Spatrick {
19946035553Spatrick auto *__data = new __libcpp_beginthreadex_thunk_data;
20046035553Spatrick __data->__func = __func;
20146035553Spatrick __data->__arg = __arg;
20246035553Spatrick
20346035553Spatrick *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
20446035553Spatrick __libcpp_beginthreadex_thunk,
20546035553Spatrick __data, 0, nullptr));
20646035553Spatrick
20746035553Spatrick if (*__t)
20846035553Spatrick return 0;
20946035553Spatrick return GetLastError();
21046035553Spatrick }
21146035553Spatrick
__libcpp_thread_get_current_id()21246035553Spatrick __libcpp_thread_id __libcpp_thread_get_current_id()
21346035553Spatrick {
21446035553Spatrick return GetCurrentThreadId();
21546035553Spatrick }
21646035553Spatrick
__libcpp_thread_get_id(const __libcpp_thread_t * __t)21746035553Spatrick __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
21846035553Spatrick {
21946035553Spatrick return GetThreadId(*__t);
22046035553Spatrick }
22146035553Spatrick
__libcpp_thread_join(__libcpp_thread_t * __t)22246035553Spatrick int __libcpp_thread_join(__libcpp_thread_t *__t)
22346035553Spatrick {
22446035553Spatrick if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
22546035553Spatrick return GetLastError();
22646035553Spatrick if (!CloseHandle(*__t))
22746035553Spatrick return GetLastError();
22846035553Spatrick return 0;
22946035553Spatrick }
23046035553Spatrick
__libcpp_thread_detach(__libcpp_thread_t * __t)23146035553Spatrick int __libcpp_thread_detach(__libcpp_thread_t *__t)
23246035553Spatrick {
23346035553Spatrick if (!CloseHandle(*__t))
23446035553Spatrick return GetLastError();
23546035553Spatrick return 0;
23646035553Spatrick }
23746035553Spatrick
__libcpp_thread_yield()23846035553Spatrick void __libcpp_thread_yield()
23946035553Spatrick {
24046035553Spatrick SwitchToThread();
24146035553Spatrick }
24246035553Spatrick
__libcpp_thread_sleep_for(const chrono::nanoseconds & __ns)24346035553Spatrick void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
24446035553Spatrick {
245*76d0caaeSpatrick // round-up to the nearest millisecond
246*76d0caaeSpatrick chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns);
24746035553Spatrick // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
24846035553Spatrick Sleep(__ms.count());
24946035553Spatrick }
25046035553Spatrick
25146035553Spatrick // Thread Local Storage
__libcpp_tls_create(__libcpp_tls_key * __key,void (_LIBCPP_TLS_DESTRUCTOR_CC * __at_exit)(void *))25246035553Spatrick int __libcpp_tls_create(__libcpp_tls_key* __key,
25346035553Spatrick void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
25446035553Spatrick {
25546035553Spatrick DWORD index = FlsAlloc(__at_exit);
25646035553Spatrick if (index == FLS_OUT_OF_INDEXES)
25746035553Spatrick return GetLastError();
25846035553Spatrick *__key = index;
25946035553Spatrick return 0;
26046035553Spatrick }
26146035553Spatrick
__libcpp_tls_get(__libcpp_tls_key __key)26246035553Spatrick void *__libcpp_tls_get(__libcpp_tls_key __key)
26346035553Spatrick {
26446035553Spatrick return FlsGetValue(__key);
26546035553Spatrick }
26646035553Spatrick
__libcpp_tls_set(__libcpp_tls_key __key,void * __p)26746035553Spatrick int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
26846035553Spatrick {
26946035553Spatrick if (!FlsSetValue(__key, __p))
27046035553Spatrick return GetLastError();
27146035553Spatrick return 0;
27246035553Spatrick }
27346035553Spatrick
27446035553Spatrick _LIBCPP_END_NAMESPACE_STD
275