[PATCH] kernel32: add basic conditional variables support (try 2)

Marcus Meissner marcus at jet.franken.de
Sun Aug 19 15:43:58 CDT 2012


Hi,

Started with patch from Austin, brought up to a point
where Adobe Lightroom 4.1 starts up.

The synchronisation is probably not 100% correct and
not sufficiently atomic.

resubmit: fixed timed waitloop now using 100ms steps not full
wait, removed superflous comment.

Ciao, Marcus
---
 dlls/kernel32/kernel32.spec |    4 +++
 dlls/kernel32/sync.c        |   64 +++++++++++++++++++++++++++++++++++++++++++
 include/winbase.h           |    4 +++
 include/winnt.h             |    6 ++++
 4 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 736fbde..da1d83d 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -743,6 +743,7 @@
 @ stdcall IdnToUnicode(long wstr long ptr long)
 @ stdcall InitAtomTable(long)
 @ stdcall InitializeSRWLock(ptr)
+@ stdcall InitializeConditionVariable(ptr)
 @ stdcall InitializeCriticalSection(ptr)
 @ stdcall InitializeCriticalSectionAndSpinCount(ptr long)
 @ stdcall InitializeCriticalSectionEx(ptr long long)
@@ -1184,6 +1185,7 @@
 @ stdcall SignalObjectAndWait(long long long long)
 @ stdcall SizeofResource(long long)
 @ stdcall Sleep(long)
+@ stdcall SleepConditionVariableCS(ptr ptr long)
 @ stdcall SleepEx(long long)
 @ stdcall SuspendThread(long)
 @ stdcall SwitchToFiber(ptr)
@@ -1253,6 +1255,8 @@
 @ stdcall WaitForSingleObjectEx(long long long)
 @ stdcall WaitNamedPipeA (str long)
 @ stdcall WaitNamedPipeW (wstr long)
+@ stdcall WakeAllConditionVariable (ptr)
+@ stdcall WakeConditionVariable (ptr)
 @ stdcall WerRegisterFile(wstr long long)
 @ stdcall WerRegisterMemoryBlock(ptr long)
 @ stdcall WerRegisterRuntimeExceptionModule(wstr ptr)
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
index f8c951b..787a72d 100644
--- a/dlls/kernel32/sync.c
+++ b/dlls/kernel32/sync.c
@@ -2299,3 +2299,67 @@ __ASM_STDCALL_FUNC(InterlockedDecrement, 4,
                   "ret $4")
 
 #endif  /* __i386__ */
+
+/**********************************************************************
+ *           InitializeConditionVariable     (KERNEL32.@)
+ */
+VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE variable)
+{
+    variable->Ptr = 0;
+    FIXME("(%p) semi-correct stub\n", variable);
+}
+
+/**********************************************************************
+ *           WakeConditionVariable     (KERNEL32.@)
+ */
+VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE variable)
+{
+    LONG ret;
+    FIXME("(%p) semi-correct stub\n", variable);
+    ret = InterlockedDecrement((PLONG)&variable->Ptr);
+    /* don't go below 0 */
+    if (!ret) InterlockedExchange((PLONG)&variable->Ptr, 0);
+}
+
+/**********************************************************************
+ *           WakeConditionVariable     (KERNEL32.@)
+ */
+VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE variable)
+{
+    FIXME("(%p) semi-correct stub\n", variable);
+    InterlockedExchange((PLONG)&variable->Ptr, 0);
+}
+
+/**********************************************************************
+ *           SleepConditionVariableCS     (KERNEL32.@)
+ */
+BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE variable,
+    LPCRITICAL_SECTION crit, DWORD milliseconds
+)
+{
+    static int cnt = 0;
+    LONG val;
+    BOOL ret;
+
+    if (cnt++ < 10)
+        FIXME("(%p, %p, %d): semi-correct stub.\n", variable, crit, milliseconds);
+    RtlLeaveCriticalSection(crit);
+    val = InterlockedIncrement((PLONG)&variable->Ptr);
+    if (milliseconds == INFINITE) {
+        while (val < *((PLONG)&variable->Ptr))
+            SleepEx(100,TRUE);
+    } else {
+        while ((milliseconds > 0) && (val < *((PLONG)&variable->Ptr))) {
+            DWORD ms = 100;
+
+            if (ms>milliseconds)
+                ms = milliseconds;
+            SleepEx(ms,TRUE);
+            milliseconds -= ms;
+        }
+    }
+    /* FIXME: make atomic? */
+    ret = val >= *((PLONG)&variable->Ptr);
+    RtlEnterCriticalSection(crit);
+    return ret;
+}
diff --git a/include/winbase.h b/include/winbase.h
index 2b384f6..4ed87bf 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -63,6 +63,10 @@ typedef PRTL_SRWLOCK PSRWLOCK;
 
 typedef WAITORTIMERCALLBACKFUNC WAITORTIMERCALLBACK;
 
+#define CONDITION_VARIABLE_INIT RTL_CONDITION_VARIABLE_INIT
+#define CONDITION_VARIABLE_LOCKMODE_SHARED RTL_CONDITION_VARIABLE_LOCKMODE_SHARED
+typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
+
 #define EXCEPTION_DEBUG_EVENT       1
 #define CREATE_THREAD_DEBUG_EVENT   2
 #define CREATE_PROCESS_DEBUG_EVENT  3
diff --git a/include/winnt.h b/include/winnt.h
index 5625e37..5106701 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -5082,6 +5082,12 @@ typedef struct _RTL_SRWLOCK {
 
 #define RTL_SRWLOCK_INIT {0}
 
+typedef struct _RTL_CONDITION_VARIABLE {
+    PVOID Ptr;
+} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
+#define RTL_CONDITION_VARIABLE_INIT {0}
+#define RTL_CONDITION_VARIABLE_LOCKMODE_SHARED  0x1
+
 typedef VOID (NTAPI * WAITORTIMERCALLBACKFUNC) (PVOID, BOOLEAN );
 typedef VOID (NTAPI * PFLS_CALLBACK_FUNCTION) ( PVOID );
 
-- 
1.7.3.4




More information about the wine-patches mailing list