msvcp140_atomic_wait: Add __std_acquire_shared_mutex_for_instance implementation.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55184
This commit is contained in:
Piotr Caban 2023-09-19 15:28:24 +02:00 committed by Alexandre Julliard
parent 46b78c5d6d
commit 1155a1914b
3 changed files with 119 additions and 2 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}