Daniel Lehman : ntdll: Implement RtlWaitOnAddress functions.
Alexandre Julliard
julliard at winehq.org
Fri Oct 26 14:23:56 CDT 2018
Module: wine
Branch: master
Commit: 25acfbb40b5316a8c87989d4e61ce9edef2a04aa
URL: https://source.winehq.org/git/wine.git/?a=commit;h=25acfbb40b5316a8c87989d4e61ce9edef2a04aa
Author: Daniel Lehman <dlehman25 at gmail.com>
Date: Thu Oct 25 23:50:14 2018 -0700
ntdll: Implement RtlWaitOnAddress functions.
Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/ntdll.spec | 3 ++
dlls/ntdll/sync.c | 49 ++++++++++++++++++++++++++++++
dlls/ntdll/tests/om.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/winternl.h | 3 ++
4 files changed, 137 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 247f05f..818ae00 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -978,6 +978,9 @@
# @ stub RtlValidateUnicodeString
@ stdcall RtlVerifyVersionInfo(ptr long int64)
@ stdcall -arch=x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr)
+@ stdcall RtlWaitOnAddress(ptr ptr long ptr)
+@ stdcall RtlWakeAddressAll(ptr)
+@ stdcall RtlWakeAddressSingle(ptr)
@ stdcall RtlWakeAllConditionVariable(ptr)
@ stdcall RtlWakeConditionVariable(ptr)
@ stub RtlWalkFrameChain
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 4ae8e36..1bfaaab 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -61,6 +61,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
HANDLE keyed_event = NULL;
+static const LARGE_INTEGER zero_timeout;
+
static inline int interlocked_dec_if_nonzero( int *dest )
{
int val, tmp;
@@ -1955,3 +1957,50 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
RtlAcquireSRWLockExclusive( lock );
return status;
}
+
+/***********************************************************************
+ * RtlWaitOnAddress (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlWaitOnAddress( const void *addr, const void *cmp, SIZE_T size,
+ const LARGE_INTEGER *timeout )
+{
+ switch (size)
+ {
+ case 1:
+ if (*(const UCHAR *)addr != *(const UCHAR *)cmp)
+ return STATUS_SUCCESS;
+ break;
+ case 2:
+ if (*(const USHORT *)addr != *(const USHORT *)cmp)
+ return STATUS_SUCCESS;
+ break;
+ case 4:
+ if (*(const ULONG *)addr != *(const ULONG *)cmp)
+ return STATUS_SUCCESS;
+ break;
+ case 8:
+ if (*(const ULONG64 *)addr != *(const ULONG64 *)cmp)
+ return STATUS_SUCCESS;
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ return NtWaitForKeyedEvent( keyed_event, addr, 0, timeout );
+}
+
+/***********************************************************************
+ * RtlWakeAddressAll (NTDLL.@)
+ */
+void WINAPI RtlWakeAddressAll( const void *addr )
+{
+ while (NtReleaseKeyedEvent( keyed_event, addr, 0, &zero_timeout ) == STATUS_SUCCESS) {}
+}
+
+/***********************************************************************
+ * RtlWakeAddressSingle (NTDLL.@)
+ */
+void WINAPI RtlWakeAddressSingle( const void *addr )
+{
+ NtReleaseKeyedEvent( keyed_event, addr, 0, &zero_timeout );
+}
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index 5240854..4d879b0 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -70,6 +70,10 @@ static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, c
static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
static NTSTATUS (WINAPI *pNtOpenIoCompletion)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, void *, ULONG, FILE_INFORMATION_CLASS);
+static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
+static void (WINAPI *pRtlWakeAddressAll)( const void * );
+static void (WINAPI *pRtlWakeAddressSingle)( const void * );
#define KEYEDEVENT_WAIT 0x0001
#define KEYEDEVENT_WAKE 0x0002
@@ -2064,6 +2068,79 @@ static void test_mutant(void)
NtClose( mutant );
}
+static void test_wait_on_address(void)
+{
+ DWORD ticks;
+ SIZE_T size;
+ NTSTATUS status;
+ LARGE_INTEGER timeout;
+ LONG64 address, compare;
+
+ if (!pRtlWaitOnAddress)
+ {
+ win_skip("RtlWaitOnAddress not supported, skipping test\n");
+ return;
+ }
+
+ if (0) /* crash on Windows */
+ {
+ pRtlWaitOnAddress(&address, NULL, 8, NULL);
+ pRtlWaitOnAddress(NULL, &compare, 8, NULL);
+ pRtlWaitOnAddress(NULL, NULL, 8, NULL);
+ }
+
+ /* don't crash */
+ pRtlWakeAddressSingle(NULL);
+ pRtlWakeAddressAll(NULL);
+
+ /* invalid values */
+ address = 0;
+ compare = 0;
+ status = pRtlWaitOnAddress(&address, &compare, 5, NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "got %x\n", status);
+
+ /* values match */
+ address = 0;
+ compare = 0;
+ pNtQuerySystemTime(&timeout);
+ timeout.QuadPart += 100*10000;
+ ticks = GetTickCount();
+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
+ ticks = GetTickCount() - ticks;
+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+ ok(ticks >= 100 && ticks <= 1000, "got %u\n", ticks);
+ ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+ ok(compare == 0, "got %s\n", wine_dbgstr_longlong(compare));
+
+ /* different address size */
+ for (size = 1; size <= 4; size <<= 1)
+ {
+ compare = ~0;
+ compare <<= size * 8;
+
+ timeout.QuadPart = -100 * 10000;
+ ticks = GetTickCount();
+ status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
+ ticks = GetTickCount() - ticks;
+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+ ok(ticks >= 100 && ticks <= 1000, "got %u\n", ticks);
+
+ status = pRtlWaitOnAddress(&address, &compare, size << 1, &timeout);
+ ok(!status, "got 0x%08x\n", status);
+ }
+ address = 0;
+ compare = 1;
+ status = pRtlWaitOnAddress(&address, &compare, 8, NULL);
+ ok(!status, "got 0x%08x\n", status);
+
+ /* no waiters */
+ address = 0;
+ pRtlWakeAddressSingle(&address);
+ ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+ pRtlWakeAddressAll(&address);
+ ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+}
+
START_TEST(om)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -2117,6 +2194,10 @@ START_TEST(om)
pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
+ pNtQuerySystemTime = (void *)GetProcAddress(hntdll, "NtQuerySystemTime");
+ pRtlWaitOnAddress = (void *)GetProcAddress(hntdll, "RtlWaitOnAddress");
+ pRtlWakeAddressAll = (void *)GetProcAddress(hntdll, "RtlWakeAddressAll");
+ pRtlWakeAddressSingle = (void *)GetProcAddress(hntdll, "RtlWakeAddressSingle");
test_case_sensitive();
test_namespace_pipe();
@@ -2130,4 +2211,5 @@ START_TEST(om)
test_mutant();
test_keyed_events();
test_null_device();
+ test_wait_on_address();
}
diff --git a/include/winternl.h b/include/winternl.h
index 1cec3cf..9c88613 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -2865,6 +2865,9 @@ NTSYSAPI BOOLEAN WINAPI RtlValidAcl(PACL);
NTSYSAPI BOOLEAN WINAPI RtlValidSid(PSID);
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE,ULONG,LPCVOID);
NTSYSAPI NTSTATUS WINAPI RtlVerifyVersionInfo(const RTL_OSVERSIONINFOEXW*,DWORD,DWORDLONG);
+NTSYSAPI NTSTATUS WINAPI RtlWaitOnAddress(const void *,const void *,SIZE_T,const LARGE_INTEGER *);
+NTSYSAPI void WINAPI RtlWakeAddressAll(const void *);
+NTSYSAPI void WINAPI RtlWakeAddressSingle(const void *);
NTSYSAPI void WINAPI RtlWakeAllConditionVariable(RTL_CONDITION_VARIABLE *);
NTSYSAPI void WINAPI RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *);
NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE,PVOID);
More information about the wine-cvs
mailing list