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