Commit 1155a191 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcp140_atomic_wait: Add __std_acquire_shared_mutex_for_instance implementation.

parent 46b78c5d
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(msvcp); WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
...@@ -81,3 +82,86 @@ BOOL __stdcall __std_atomic_wait_direct(volatile void *addr, void *cmp, ...@@ -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); TRACE("(%p %p %Id %ld)\n", addr, cmp, size, timeout);
return WaitOnAddress(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);
}
@ stub __std_acquire_shared_mutex_for_instance @ stdcall __std_acquire_shared_mutex_for_instance(ptr)
@ stub __std_atomic_compare_exchange_128 @ stub __std_atomic_compare_exchange_128
@ stub __std_atomic_get_mutex @ stub __std_atomic_get_mutex
@ stub __std_atomic_has_cmpxchg16b @ stub __std_atomic_has_cmpxchg16b
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
@ stub __std_execution_wake_by_address_all @ stub __std_execution_wake_by_address_all
@ stub __std_free_crt @ stub __std_free_crt
@ stdcall __std_parallel_algorithms_hw_threads() @ 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) @ stdcall __std_submit_threadpool_work(ptr)
@ stub __std_tzdb_delete_current_zone @ stub __std_tzdb_delete_current_zone
@ stub __std_tzdb_delete_leap_seconds @ stub __std_tzdb_delete_leap_seconds
......
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
#include "winbase.h" #include "winbase.h"
#include "wine/test.h" #include "wine/test.h"
typedef struct
{
SRWLOCK srwlock;
} shared_mutex;
static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void); static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void);
static void (__stdcall *p___std_bulk_submit_threadpool_work)(PTP_WORK, size_t); 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); ...@@ -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 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 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_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 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) #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) ...@@ -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_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_wait_direct, "__std_atomic_wait_direct");
SET(p___std_atomic_notify_one_direct, "__std_atomic_notify_one_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; return msvcp;
} }
...@@ -237,6 +246,29 @@ static void test___std_atomic_wait_direct(void) ...@@ -237,6 +246,29 @@ static void test___std_atomic_wait_direct(void)
CloseHandle(thread); 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) START_TEST(msvcp140_atomic_wait)
{ {
HMODULE msvcp; HMODULE msvcp;
...@@ -248,5 +280,6 @@ START_TEST(msvcp140_atomic_wait) ...@@ -248,5 +280,6 @@ START_TEST(msvcp140_atomic_wait)
test___std_parallel_algorithms_hw_threads(); test___std_parallel_algorithms_hw_threads();
test_threadpool_work(); test_threadpool_work();
test___std_atomic_wait_direct(); test___std_atomic_wait_direct();
test___std_acquire_shared_mutex_for_instance();
FreeLibrary(msvcp); FreeLibrary(msvcp);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment