[PATCH] ntdll: Wake one waiter in RtlWakeAddressSingle in futex path.
Daniel Lehman
dlehman25 at gmail.com
Mon Sep 9 22:39:50 CDT 2019
Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
dlls/ntdll/sync.c | 10 ++++-----
dlls/ntdll/tests/om.c | 48 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 35b89df52e..88fb979b2c 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -2416,7 +2416,7 @@ static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T
return STATUS_SUCCESS;
}
-static inline NTSTATUS fast_wake_addr( const void *addr )
+static inline NTSTATUS fast_wake_addr( const void *addr, int waiters )
{
int *futex;
@@ -2427,7 +2427,7 @@ static inline NTSTATUS fast_wake_addr( const void *addr )
interlocked_xchg_add( futex, 1 );
- futex_wake( futex, INT_MAX );
+ futex_wake( futex, waiters );
return STATUS_SUCCESS;
}
#else
@@ -2437,7 +2437,7 @@ static inline NTSTATUS fast_wait_addr( const void *addr, const void *cmp, SIZE_T
return STATUS_NOT_IMPLEMENTED;
}
-static inline NTSTATUS fast_wake_addr( const void *addr )
+static inline NTSTATUS fast_wake_addr( const void *addr, int waiters )
{
return STATUS_NOT_IMPLEMENTED;
}
@@ -2518,7 +2518,7 @@ NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size
*/
void WINAPI RtlWakeAddressAll( const void *addr )
{
- if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED)
+ if (fast_wake_addr( addr, INT_MAX ) != STATUS_NOT_IMPLEMENTED)
return;
RtlEnterCriticalSection( &addr_section );
@@ -2531,7 +2531,7 @@ void WINAPI RtlWakeAddressAll( const void *addr )
*/
void WINAPI RtlWakeAddressSingle( const void *addr )
{
- if (fast_wake_addr( addr ) != STATUS_NOT_IMPLEMENTED)
+ if (fast_wake_addr( addr, 1 ) != STATUS_NOT_IMPLEMENTED)
return;
RtlEnterCriticalSection( &addr_section );
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index c17b6ffa8d..8fbcc89718 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -2148,6 +2148,53 @@ static void test_wait_on_address(void)
ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
}
+static LONG wake_single_addr;
+DWORD WINAPI wake_single_thread(void *arg)
+{
+ LONG value;
+ NTSTATUS status;
+
+ value = 0;
+ status = pRtlWaitOnAddress(&wake_single_addr, &value, sizeof(value), NULL);
+ ok(status == STATUS_SUCCESS, "got %x\n", status);
+ return 0;
+}
+
+static void test_wake_single(void)
+{
+ HANDLE threads[16];
+ DWORD ret, nthreads;
+ int i;
+
+ if (!pRtlWaitOnAddress)
+ {
+ win_skip("RtlWaitOnAddress not supported, skipping test\n");
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(threads); i++)
+ threads[i] = CreateThread(NULL, 0, wake_single_thread, NULL, 0, NULL);
+
+ Sleep(1000); /* wait for threads to enter RtlWaitOnAddress */
+
+ wake_single_addr = 1;
+ nthreads = ARRAY_SIZE(threads);
+ while (nthreads)
+ {
+ pRtlWakeAddressSingle(&wake_single_addr);
+ ret = WaitForMultipleObjects(nthreads, threads, FALSE, 2000);
+ ok(ret < WAIT_OBJECT_0 + nthreads, "got %u\n", ret);
+ CloseHandle(threads[ret]);
+ memmove(&threads[ret], &threads[ret+1], (nthreads - ret - 1) * sizeof(threads[0]));
+ if (--nthreads)
+ {
+ /* make sure other threads are still waiting */
+ ret = WaitForMultipleObjects(nthreads, threads, FALSE, 0);
+ ok(ret == WAIT_TIMEOUT, "got %u\n", ret);
+ }
+ }
+}
+
START_TEST(om)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -2221,4 +2268,5 @@ START_TEST(om)
test_keyed_events();
test_null_device();
test_wait_on_address();
+ test_wake_single();
}
--
2.17.1
More information about the wine-devel
mailing list