Signed-off-by: Daniel Lehman dlehman25@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(); }
Hello Daniel,
On 9/9/19 10:39 PM, Daniel Lehman wrote:
Signed-off-by: Daniel Lehman dlehman25@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 );
Unfortunately, this can't work. We map multiple addresses to each futex, so this could result in waking up the wrong one, while the right one never wakes up.
Do you have an application that relies on this?
ἔρρωσο, Zeb
Unfortunately, this can't work. We map multiple addresses to each futex, so this could result in waking up the wrong one, while the right one never wakes up.
ah, i see - i missed that. ignore