From fad29fc5d997cfc13d75c0a5b5563c85188ba2f2 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 22 Jan 2014 01:05:15 +0100 Subject: [PATCH] ntdll: Implement RtlSleepConditionVariableSRW. --- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/sync.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/winternl.h | 1 + 3 files changed, 46 insertions(+) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 4140ff9f812..3c751eaedcc 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -869,6 +869,7 @@ @ stub RtlSetUserValueHeap @ stdcall RtlSizeHeap(long long ptr) @ stdcall RtlSleepConditionVariableCS(ptr ptr ptr) +@ stdcall RtlSleepConditionVariableSRW(ptr ptr ptr long) @ stub RtlSplay @ stub RtlStartRXact # @ stub RtlStatMemoryStream diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 6404ac59269..8ef16ccacc7 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1696,3 +1696,47 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R RtlEnterCriticalSection( crit ); return status; } + +/*********************************************************************** + * RtlSleepConditionVariableSRW (NTDLL.@) + * + * Atomically releases the SRWLock and suspends the thread, + * waiting for a Wake(All)ConditionVariable event. Afterwards it enters + * the SRWLock again with the same access rights and returns. + * + * PARAMS + * variable [I/O] condition variable + * lock [I/O] SRWLock to leave temporarily + * timeout [I] timeout + * flags [I] type of the current lock (exclusive / shared) + * + * RETURNS + * see NtWaitForKeyedEvent for all possible return values. + * + * NOTES + * the behaviour is undefined if the thread doesn't own the lock. + */ +NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, RTL_SRWLOCK *lock, + const LARGE_INTEGER *timeout, ULONG flags ) +{ + NTSTATUS status; + interlocked_xchg_add( (int *)&variable->Ptr, 1 ); + + if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) + RtlReleaseSRWLockShared( lock ); + else + RtlReleaseSRWLockExclusive( lock ); + + status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, timeout ); + if (status != STATUS_SUCCESS) + { + if (!interlocked_dec_if_nonzero( (int *)&variable->Ptr )) + status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL ); + } + + if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) + RtlAcquireSRWLockShared( lock ); + else + RtlAcquireSRWLockExclusive( lock ); + return status; +} diff --git a/include/winternl.h b/include/winternl.h index d3a02bfc9a7..22ee8e88057 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2503,6 +2503,7 @@ NTSYSAPI NTSTATUS WINAPI RtlSetThreadErrorMode(DWORD,LPDWORD); NTSYSAPI NTSTATUS WINAPI RtlSetTimeZoneInformation(const RTL_TIME_ZONE_INFORMATION*); NTSYSAPI SIZE_T WINAPI RtlSizeHeap(HANDLE,ULONG,const void*); NTSYSAPI NTSTATUS WINAPI RtlSleepConditionVariableCS(RTL_CONDITION_VARIABLE*,RTL_CRITICAL_SECTION*,const LARGE_INTEGER*); +NTSYSAPI NTSTATUS WINAPI RtlSleepConditionVariableSRW(RTL_CONDITION_VARIABLE*,RTL_SRWLOCK*,const LARGE_INTEGER*,ULONG); NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID,PUNICODE_STRING); NTSYSAPI LPDWORD WINAPI RtlSubAuthoritySid(PSID,DWORD); NTSYSAPI LPBYTE WINAPI RtlSubAuthorityCountSid(PSID); -- 2.11.4.GIT