From: Daniel Lehman dlehman25@gmail.com
--- dlls/msvcp140_atomic_wait/main.c | 12 ++++ .../msvcp140_atomic_wait.spec | 4 +- .../tests/msvcp140_atomic_wait.c | 57 +++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcp140_atomic_wait/main.c b/dlls/msvcp140_atomic_wait/main.c index 52ecae486eb..9c61b158b97 100644 --- a/dlls/msvcp140_atomic_wait/main.c +++ b/dlls/msvcp140_atomic_wait/main.c @@ -83,6 +83,18 @@ BOOL __stdcall __std_atomic_wait_direct(volatile void *addr, void *cmp, return WaitOnAddress(addr, cmp, size, timeout); }
+void __stdcall __std_execution_wait_on_uchar(void *addr, unsigned char val) +{ + TRACE("(%p %d)\n", addr, val); + WaitOnAddress(addr, &val, sizeof(val), INFINITE); +} + +void __stdcall __std_execution_wake_by_address_all(void *addr) +{ + TRACE("(%p)\n", addr); + WakeByAddressAll(addr); +} + typedef struct { SRWLOCK srwlock; diff --git a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec index 88ed59adad9..d335828d35c 100644 --- a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec +++ b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec @@ -15,8 +15,8 @@ @ stdcall __std_calloc_crt(long long) @ stdcall __std_close_threadpool_work(ptr) @ stdcall __std_create_threadpool_work(ptr ptr ptr) -@ stub __std_execution_wait_on_uchar -@ stub __std_execution_wake_by_address_all +@ stdcall __std_execution_wait_on_uchar(ptr long) +@ stdcall __std_execution_wake_by_address_all(ptr) @ stdcall __std_free_crt(ptr) @ stdcall __std_parallel_algorithms_hw_threads() @ stdcall __std_release_shared_mutex_for_instance(ptr) diff --git a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c index 882e07c48db..1e99145ac4b 100644 --- a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c +++ b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c @@ -37,6 +37,8 @@ static void (__stdcall *p___std_submit_threadpool_work)(PTP_WORK); static void (__stdcall *p___std_wait_for_threadpool_work_callbacks)(PTP_WORK, BOOL); static BOOL (__stdcall *p___std_atomic_wait_direct)(volatile void*, void*, size_t, DWORD); static void (__stdcall *p___std_atomic_notify_one_direct)(void*); +static void (__stdcall *p___std_execution_wait_on_uchar)(void *, unsigned char); +static void (__stdcall *p___std_execution_wake_by_address_all)(void *); static shared_mutex* (__stdcall *p___std_acquire_shared_mutex_for_instance)(void*); static void (__stdcall *p___std_release_shared_mutex_for_instance)(void*);
@@ -58,6 +60,8 @@ static HMODULE init(void) SET(p___std_wait_for_threadpool_work_callbacks, "__std_wait_for_threadpool_work_callbacks"); SET(p___std_atomic_wait_direct, "__std_atomic_wait_direct"); SET(p___std_atomic_notify_one_direct, "__std_atomic_notify_one_direct"); + SET(p___std_execution_wait_on_uchar, "__std_execution_wait_on_uchar"); + SET(p___std_execution_wake_by_address_all, "__std_execution_wake_by_address_all"); SET(p___std_acquire_shared_mutex_for_instance, "__std_acquire_shared_mutex_for_instance"); SET(p___std_release_shared_mutex_for_instance, "__std_release_shared_mutex_for_instance"); return msvcp; @@ -246,6 +250,58 @@ static void test___std_atomic_wait_direct(void) CloseHandle(thread); }
+static LONG count; +static unsigned WINAPI execution_wait_thread(void *arg) +{ + unsigned char *phase = arg; + + if(!InterlockedDecrement(&count)) { + *phase = 1; + p___std_execution_wake_by_address_all(phase); + }else { + while(!*phase) + p___std_execution_wait_on_uchar(phase, 0); + } + + while(*phase == 1) + p___std_execution_wait_on_uchar(phase, 1); + + InterlockedIncrement(&count); + return 0; +} + +static void test___std_execution(void) +{ + int i; + DWORD ret; + HANDLE threads[4]; + unsigned char phase; + + p___std_execution_wake_by_address_all(NULL); + if(0) p___std_execution_wait_on_uchar(NULL, 0); /* crash on windows */ + + count = ARRAY_SIZE(threads); + phase = 0; + for(i=0; i<ARRAY_SIZE(threads); i++) { + threads[i] = (HANDLE)_beginthreadex(NULL, 0, execution_wait_thread, &phase, 0, NULL); + ok(threads[i] != INVALID_HANDLE_VALUE, "_beginthreadex failed\n"); + } + + Sleep(0); + while(!phase) + p___std_execution_wait_on_uchar(&phase, 0); + ok(!count, "expected 0, got %ld\n", count); + + phase = 2; + p___std_execution_wake_by_address_all(&phase); + + ret = WaitForMultipleObjects(ARRAY_SIZE(threads), threads, TRUE, 1000); + ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret); + ok(count == ARRAY_SIZE(threads), "expected %Iu, got %lu\n", ARRAY_SIZE(threads), count); + for(i=0; i<ARRAY_SIZE(threads); i++) + CloseHandle(threads[i]); +} + static void test___std_acquire_shared_mutex_for_instance(void) { shared_mutex *ret1, *ret2; @@ -280,6 +336,7 @@ START_TEST(msvcp140_atomic_wait) test___std_parallel_algorithms_hw_threads(); test_threadpool_work(); test___std_atomic_wait_direct(); + test___std_execution(); test___std_acquire_shared_mutex_for_instance(); FreeLibrary(msvcp); }
This merge request was approved by Piotr Caban.