ntdll: Implement RtlWaitOnAddress functions.
Signed-off-by: Daniel Lehman <dlehman25@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
61cdd8e352
commit
25acfbb40b
|
@ -978,6 +978,9 @@
|
||||||
# @ stub RtlValidateUnicodeString
|
# @ stub RtlValidateUnicodeString
|
||||||
@ stdcall RtlVerifyVersionInfo(ptr long int64)
|
@ stdcall RtlVerifyVersionInfo(ptr long int64)
|
||||||
@ stdcall -arch=x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr)
|
@ 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 RtlWakeAllConditionVariable(ptr)
|
||||||
@ stdcall RtlWakeConditionVariable(ptr)
|
@ stdcall RtlWakeConditionVariable(ptr)
|
||||||
@ stub RtlWalkFrameChain
|
@ stub RtlWalkFrameChain
|
||||||
|
|
|
@ -61,6 +61,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||||
|
|
||||||
HANDLE keyed_event = NULL;
|
HANDLE keyed_event = NULL;
|
||||||
|
|
||||||
|
static const LARGE_INTEGER zero_timeout;
|
||||||
|
|
||||||
static inline int interlocked_dec_if_nonzero( int *dest )
|
static inline int interlocked_dec_if_nonzero( int *dest )
|
||||||
{
|
{
|
||||||
int val, tmp;
|
int val, tmp;
|
||||||
|
@ -1955,3 +1957,50 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||||
RtlAcquireSRWLockExclusive( lock );
|
RtlAcquireSRWLockExclusive( lock );
|
||||||
return status;
|
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 );
|
||||||
|
}
|
||||||
|
|
|
@ -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 *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
|
||||||
static NTSTATUS (WINAPI *pNtOpenIoCompletion)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
|
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 *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_WAIT 0x0001
|
||||||
#define KEYEDEVENT_WAKE 0x0002
|
#define KEYEDEVENT_WAKE 0x0002
|
||||||
|
@ -2064,6 +2068,79 @@ static void test_mutant(void)
|
||||||
NtClose( mutant );
|
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)
|
START_TEST(om)
|
||||||
{
|
{
|
||||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||||
|
@ -2117,6 +2194,10 @@ START_TEST(om)
|
||||||
pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
|
pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
|
||||||
pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
|
pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
|
||||||
pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
|
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_case_sensitive();
|
||||||
test_namespace_pipe();
|
test_namespace_pipe();
|
||||||
|
@ -2130,4 +2211,5 @@ START_TEST(om)
|
||||||
test_mutant();
|
test_mutant();
|
||||||
test_keyed_events();
|
test_keyed_events();
|
||||||
test_null_device();
|
test_null_device();
|
||||||
|
test_wait_on_address();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2865,6 +2865,9 @@ NTSYSAPI BOOLEAN WINAPI RtlValidAcl(PACL);
|
||||||
NTSYSAPI BOOLEAN WINAPI RtlValidSid(PSID);
|
NTSYSAPI BOOLEAN WINAPI RtlValidSid(PSID);
|
||||||
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE,ULONG,LPCVOID);
|
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE,ULONG,LPCVOID);
|
||||||
NTSYSAPI NTSTATUS WINAPI RtlVerifyVersionInfo(const RTL_OSVERSIONINFOEXW*,DWORD,DWORDLONG);
|
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 RtlWakeAllConditionVariable(RTL_CONDITION_VARIABLE *);
|
||||||
NTSYSAPI void WINAPI RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *);
|
NTSYSAPI void WINAPI RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *);
|
||||||
NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE,PVOID);
|
NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE,PVOID);
|
||||||
|
|
Loading…
Reference in New Issue