Sebastian Lackner : ntdll: Implement condition variable functions using keyed events.
Alexandre Julliard
julliard at winehq.org
Wed Jan 8 13:41:31 CST 2014
Module: wine
Branch: master
Commit: 5472b9f9ca1a393c0153e256da67798a3afe53c7
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5472b9f9ca1a393c0153e256da67798a3afe53c7
Author: Sebastian Lackner <sebastian at fds-team.de>
Date: Sun Jan 5 03:48:34 2014 +0100
ntdll: Implement condition variable functions using keyed events.
---
dlls/ntdll/ntdll.spec | 4 +++
dlls/ntdll/sync.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
include/winternl.h | 6 +++-
3 files changed, 102 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 6418671..2e507bb 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 b05bd19..c94d9c4 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 d93b37a..c840732 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*);
More information about the wine-cvs
mailing list