diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 6418671804e..2e507bb5c65 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -672,6 +672,7 @@ @ stdcall RtlInitUnicodeStringEx(ptr wstr) # @ stub RtlInitializeAtomPackage @ stdcall RtlInitializeBitMap(ptr long long) +@ stdcall RtlInitializeConditionVariable(ptr) @ stub RtlInitializeContext @ stdcall RtlInitializeCriticalSection(ptr) @ stdcall RtlInitializeCriticalSectionAndSpinCount(ptr long) @@ -867,6 +868,7 @@ @ stub RtlSetUserFlagsHeap @ stub RtlSetUserValueHeap @ stdcall RtlSizeHeap(long long ptr) +@ stdcall RtlSleepConditionVariableCS(ptr ptr ptr) @ stub RtlSplay @ stub RtlStartRXact # @ stub RtlStatMemoryStream @@ -932,6 +934,8 @@ # @ stub RtlValidateUnicodeString @ stdcall RtlVerifyVersionInfo(ptr long int64) @ stdcall -arch=x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr) +@ stdcall RtlWakeAllConditionVariable(ptr) +@ stdcall RtlWakeConditionVariable(ptr) @ stub RtlWalkFrameChain @ stdcall RtlWalkHeap(long ptr) @ stdcall RtlWow64EnableFsRedirection(long) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index b05bd1988a6..c94d9c40fa0 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -63,6 +63,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); HANDLE keyed_event = NULL; +static inline int interlocked_dec_if_nonzero( int *dest ) +{ + int val, tmp; + for (val = *dest;; val = tmp) + { + if (!val || (tmp = interlocked_cmpxchg( dest, val - 1, val )) == val) + break; + } + return val; +} + /* creates a struct security_descriptor and contained information in one contiguous piece of memory */ NTSTATUS NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd, data_size_t *server_sd_len) @@ -1410,3 +1421,85 @@ void WINAPI RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) { FIXME( "%p stub\n", lock ); } + +/*********************************************************************** + * RtlInitializeConditionVariable (NTDLL.@) + * + * Initializes the condition variable with NULL. + * + * PARAMS + * variable [O] condition variable + * + * RETURNS + * Nothing. + */ +void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable ) +{ + variable->Ptr = NULL; +} + +/*********************************************************************** + * RtlWakeConditionVariable (NTDLL.@) + * + * Wakes up one thread waiting on the condition variable. + * + * PARAMS + * variable [I/O] condition variable to wake up. + * + * RETURNS + * Nothing. + * + * NOTES + * The calling thread does not have to own any lock in order to call + * this function. + */ +void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable ) +{ + if (interlocked_dec_if_nonzero( (int *)&variable->Ptr )) + NtReleaseKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL ); +} + +/*********************************************************************** + * RtlWakeAllConditionVariable (NTDLL.@) + * + * See WakeConditionVariable, wakes up all waiting threads. + */ +void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable ) +{ + int val = interlocked_xchg( (int *)&variable->Ptr, 0 ); + while (val-- > 0) + NtReleaseKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL ); +} + +/*********************************************************************** + * RtlSleepConditionVariableCS (NTDLL.@) + * + * Atomically releases the critical section and suspends the thread, + * waiting for a Wake(All)ConditionVariable event. Afterwards it enters + * the critical section again and returns. + * + * PARAMS + * variable [I/O] condition variable + * crit [I/O] critical section to leave temporarily + * timeout [I] timeout + * + * RETURNS + * see NtWaitForKeyedEvent for all possible return values. + */ +NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, RTL_CRITICAL_SECTION *crit, + const LARGE_INTEGER *timeout ) +{ + NTSTATUS status; + interlocked_xchg_add( (int *)&variable->Ptr, 1 ); + RtlLeaveCriticalSection( crit ); + + 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 ); + } + + RtlEnterCriticalSection( crit ); + return status; +} diff --git a/include/winternl.h b/include/winternl.h index d93b37aca0f..c84073242cf 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2418,10 +2418,11 @@ NTSYSAPI void WINAPI RtlInitAnsiString(PANSI_STRING,PCSZ); NTSYSAPI NTSTATUS WINAPI RtlInitAnsiStringEx(PANSI_STRING,PCSZ); NTSYSAPI void WINAPI RtlInitUnicodeString(PUNICODE_STRING,PCWSTR); NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING,PCWSTR); +NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP,PULONG,ULONG); +NTSYSAPI void WINAPI RtlInitializeConditionVariable(RTL_CONDITION_VARIABLE *); NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSection(RTL_CRITICAL_SECTION *); NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount(RTL_CRITICAL_SECTION *,ULONG); NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSectionEx(RTL_CRITICAL_SECTION *,ULONG,ULONG); -NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP,PULONG,ULONG); NTSYSAPI void WINAPI RtlInitializeHandleTable(ULONG,ULONG,RTL_HANDLE_TABLE *); NTSYSAPI void WINAPI RtlInitializeResource(LPRTL_RWLOCK); NTSYSAPI void WINAPI RtlInitializeSRWLock(RTL_SRWLOCK*); @@ -2501,6 +2502,7 @@ NTSYSAPI NTSTATUS WINAPI RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOL 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 RtlStringFromGUID(REFGUID,PUNICODE_STRING); NTSYSAPI LPDWORD WINAPI RtlSubAuthoritySid(PSID,DWORD); NTSYSAPI LPBYTE WINAPI RtlSubAuthorityCountSid(PSID); @@ -2544,6 +2546,8 @@ 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 void WINAPI RtlWakeAllConditionVariable(RTL_CONDITION_VARIABLE *); +NTSYSAPI void WINAPI RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *); NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE,PVOID); NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirection(BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx(ULONG,ULONG*);