From 1155a1914b379f819e4a1be9e092e10bf27a7a2c Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 19 Sep 2023 15:28:24 +0200 Subject: [PATCH] msvcp140_atomic_wait: Add __std_acquire_shared_mutex_for_instance implementation. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55184 --- dlls/msvcp140_atomic_wait/main.c | 84 +++++++++++++++++++ .../msvcp140_atomic_wait.spec | 4 +- .../tests/msvcp140_atomic_wait.c | 33 ++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/dlls/msvcp140_atomic_wait/main.c b/dlls/msvcp140_atomic_wait/main.c index bee7164e09f..b7aa30200ff 100644 --- a/dlls/msvcp140_atomic_wait/main.c +++ b/dlls/msvcp140_atomic_wait/main.c @@ -20,6 +20,7 @@ #include "windef.h" #include "winbase.h" #include "wine/debug.h" +#include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(msvcp); @@ -81,3 +82,86 @@ BOOL __stdcall __std_atomic_wait_direct(volatile void *addr, void *cmp, TRACE("(%p %p %Id %ld)\n", addr, cmp, size, timeout); return WaitOnAddress(addr, cmp, size, timeout); } + +typedef struct +{ + SRWLOCK srwlock; +} shared_mutex; + +struct shared_mutex_elem +{ + struct list entry; + int ref; + void *ptr; + shared_mutex mutex; +}; + +static CRITICAL_SECTION shared_mutex_cs; +static CRITICAL_SECTION_DEBUG shared_mutex_cs_debug = +{ + 0, 0, &shared_mutex_cs, + { &shared_mutex_cs_debug.ProcessLocksList, &shared_mutex_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": shared_mutex_cs") } +}; +static CRITICAL_SECTION shared_mutex_cs = { &shared_mutex_cs_debug, -1, 0, 0, 0, 0 }; +static struct list shared_mutex_list = LIST_INIT(shared_mutex_list); + +/* shared_mutex_cs must be held by caller */ +static struct shared_mutex_elem* find_shared_mutex(void *ptr) +{ + struct shared_mutex_elem *sme; + + LIST_FOR_EACH_ENTRY(sme, &shared_mutex_list, struct shared_mutex_elem, entry) + { + if (sme->ptr == ptr) + return sme; + } + return NULL; +} + +shared_mutex* __stdcall __std_acquire_shared_mutex_for_instance(void *ptr) +{ + struct shared_mutex_elem *sme; + + TRACE("(%p)\n", ptr); + + EnterCriticalSection(&shared_mutex_cs); + sme = find_shared_mutex(ptr); + if (sme) + { + sme->ref++; + LeaveCriticalSection(&shared_mutex_cs); + return &sme->mutex; + } + + sme = malloc(sizeof(*sme)); + sme->ref = 1; + sme->ptr = ptr; + InitializeSRWLock(&sme->mutex.srwlock); + list_add_head(&shared_mutex_list, &sme->entry); + LeaveCriticalSection(&shared_mutex_cs); + return &sme->mutex; +} + +void __stdcall __std_release_shared_mutex_for_instance(void *ptr) +{ + struct shared_mutex_elem *sme; + + TRACE("(%p)\n", ptr); + + EnterCriticalSection(&shared_mutex_cs); + sme = find_shared_mutex(ptr); + if (!sme) + { + LeaveCriticalSection(&shared_mutex_cs); + return; + } + + sme->ref--; + if (!sme->ref) + { + list_remove(&sme->entry); + free(sme); + } + LeaveCriticalSection(&shared_mutex_cs); +} diff --git a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec index 04b5bf2c7f9..5d9dd5c1a74 100644 --- a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec +++ b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec @@ -1,4 +1,4 @@ -@ stub __std_acquire_shared_mutex_for_instance +@ stdcall __std_acquire_shared_mutex_for_instance(ptr) @ stub __std_atomic_compare_exchange_128 @ stub __std_atomic_get_mutex @ stub __std_atomic_has_cmpxchg16b @@ -19,7 +19,7 @@ @ stub __std_execution_wake_by_address_all @ stub __std_free_crt @ stdcall __std_parallel_algorithms_hw_threads() -@ stub __std_release_shared_mutex_for_instance +@ stdcall __std_release_shared_mutex_for_instance(ptr) @ stdcall __std_submit_threadpool_work(ptr) @ stub __std_tzdb_delete_current_zone @ stub __std_tzdb_delete_leap_seconds diff --git a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c index c10217cf34f..882e07c48db 100644 --- a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c +++ b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c @@ -23,6 +23,11 @@ #include "winbase.h" #include "wine/test.h" +typedef struct +{ + SRWLOCK srwlock; +} shared_mutex; + static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void); static void (__stdcall *p___std_bulk_submit_threadpool_work)(PTP_WORK, size_t); @@ -32,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 shared_mutex* (__stdcall *p___std_acquire_shared_mutex_for_instance)(void*); +static void (__stdcall *p___std_release_shared_mutex_for_instance)(void*); #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) @@ -51,6 +58,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_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; } @@ -237,6 +246,29 @@ static void test___std_atomic_wait_direct(void) CloseHandle(thread); } +static void test___std_acquire_shared_mutex_for_instance(void) +{ + shared_mutex *ret1, *ret2; + + ret1 = p___std_acquire_shared_mutex_for_instance(NULL); + ok(ret1 != NULL, "got %p\n", ret1); + ret2 = p___std_acquire_shared_mutex_for_instance(NULL); + ok(ret2 != NULL, "got %p\n", ret2); + ok(ret1 == ret2, "got different instances of shared mutex\n"); + + ret2 = p___std_acquire_shared_mutex_for_instance((void *)1); + ok(ret2 != NULL, "got %p\n", ret2); + ok(ret1 != ret2, "got the same instance of shared mutex\n"); + + p___std_release_shared_mutex_for_instance(NULL); + p___std_release_shared_mutex_for_instance((void *)1); + + AcquireSRWLockExclusive(&ret1->srwlock); + ReleaseSRWLockExclusive(&ret1->srwlock); + p___std_release_shared_mutex_for_instance(NULL); + p___std_release_shared_mutex_for_instance(NULL); +} + START_TEST(msvcp140_atomic_wait) { HMODULE msvcp; @@ -248,5 +280,6 @@ START_TEST(msvcp140_atomic_wait) test___std_parallel_algorithms_hw_threads(); test_threadpool_work(); test___std_atomic_wait_direct(); + test___std_acquire_shared_mutex_for_instance(); FreeLibrary(msvcp); }