Marcus Meissner : kernel32: Conditional variable tests.

Alexandre Julliard julliard at winehq.org
Wed Jan 30 13:43:22 CST 2013


Module: wine
Branch: master
Commit: 17ca7ee82f63600b05324687aff7aa2a867d0ca2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=17ca7ee82f63600b05324687aff7aa2a867d0ca2

Author: Marcus Meissner <marcus at jet.franken.de>
Date:   Wed Jan 30 11:19:56 2013 +0100

kernel32: Conditional variable tests.

---

 dlls/kernel32/tests/sync.c |  154 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 145 insertions(+), 9 deletions(-)

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index 0ab82f0..3924dc0 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -1253,12 +1253,12 @@ static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
 #define BUFFER_SIZE 5
 
 static DWORD WINAPI condvar_producer(LPVOID x) {
-    DWORD sleepinterval = 50;
+    DWORD sleepinterval = 5;
 
     while (1) {
         Sleep(sleepinterval);
-        if (sleepinterval > 10)
-            sleepinterval -= 10;
+        if (sleepinterval > 1)
+            sleepinterval -= 1;
 
         EnterCriticalSection(&buffercrit);
         while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
@@ -1282,7 +1282,7 @@ static DWORD WINAPI condvar_producer(LPVOID x) {
 
 static DWORD WINAPI condvar_consumer(LPVOID x) {
     DWORD *cnt = (DWORD*)x;
-    DWORD sleepinterval = 10;
+    DWORD sleepinterval = 1;
 
     while (1) {
         EnterCriticalSection(&buffercrit);
@@ -1303,12 +1303,12 @@ static DWORD WINAPI condvar_consumer(LPVOID x) {
         LeaveCriticalSection(&buffercrit);
         pWakeConditionVariable(&buffernotfull);
         Sleep(sleepinterval);
-        if (sleepinterval < 50) sleepinterval += 10;
+        if (sleepinterval < 5) sleepinterval += 1;
     }
     return 0;
 }
 
-static void test_condvars(void)
+static void test_condvars_consumer_producer(void)
 {
     HANDLE hp1,hp2,hp3,hc1,hc2,hc3;
     DWORD dummy;
@@ -1328,8 +1328,10 @@ static void test_condvars(void)
      * pInitializeConditionVariable(&buffernotfull);
      */
     pInitializeConditionVariable(&buffernotempty);
-
     InitializeCriticalSection(&buffercrit);
+
+    /* Larger Test: consumer/producer example */
+
     bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0;
 
     hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
@@ -1349,7 +1351,9 @@ static void test_condvars(void)
     pWakeAllConditionVariable (&buffernotfull);
     pWakeAllConditionVariable (&buffernotempty);
 
-    ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
+    /* (mostly an implementation detail)
+     * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
+     */
 
     WaitForSingleObject(hp1, 1000);
     WaitForSingleObject(hp2, 1000);
@@ -1371,6 +1375,137 @@ static void test_condvars(void)
     trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
 }
 
+/* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
+static DWORD condvar_seq = 0;
+static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT;
+static CRITICAL_SECTION condvar_crit;
+
+/* Sequence of wake/sleep to check boundary conditions:
+ * 0: init
+ * 1: producer emits a WakeConditionVaribale without consumer waiting.
+ * 2: consumer sleeps without a wake expecting timeout
+ * 3: producer emits a WakeAllConditionVaribale without consumer waiting.
+ * 4: consumer sleeps without a wake expecting timeout
+ * 5: a wake is handed to a SleepConditionVariableCS
+ * 6: a wakeall is handed to a SleepConditionVariableCS
+ * 7: sleep after above should timeout
+ * 8: wake with crit section locked into the sleep timeout
+ * 9: end
+ */
+static DWORD WINAPI condvar_base_producer(LPVOID x) {
+    while (condvar_seq < 1) Sleep(1);
+
+    pWakeConditionVariable (&condvar_base);
+    condvar_seq = 2;
+
+    while (condvar_seq < 3) Sleep(1);
+    pWakeAllConditionVariable (&condvar_base);
+    condvar_seq = 4;
+
+    while (condvar_seq < 5) Sleep(1);
+    EnterCriticalSection (&condvar_crit);
+    pWakeConditionVariable (&condvar_base);
+    LeaveCriticalSection (&condvar_crit);
+    while (condvar_seq < 6) Sleep(1);
+    EnterCriticalSection (&condvar_crit);
+    pWakeAllConditionVariable (&condvar_base);
+    LeaveCriticalSection (&condvar_crit);
+
+    while (condvar_seq < 8) Sleep(1);
+    EnterCriticalSection (&condvar_crit);
+    pWakeConditionVariable (&condvar_base);
+    Sleep(50);
+    LeaveCriticalSection (&condvar_crit);
+
+    return 0;
+}
+
+static DWORD WINAPI condvar_base_consumer(LPVOID x) {
+    BOOL ret;
+
+    while (condvar_seq < 2) Sleep(1);
+
+    /* wake was emitted, but we were not sleeping */
+    EnterCriticalSection (&condvar_crit);
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
+    LeaveCriticalSection (&condvar_crit);
+    ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
+    ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
+
+    condvar_seq = 3;
+    while (condvar_seq < 4) Sleep(1);
+
+    /* wake all was emitted, but we were not sleeping */
+    EnterCriticalSection (&condvar_crit);
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
+    LeaveCriticalSection (&condvar_crit);
+    ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
+    ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
+
+    EnterCriticalSection (&condvar_crit);
+    condvar_seq = 5;
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
+    LeaveCriticalSection (&condvar_crit);
+    ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
+
+    EnterCriticalSection (&condvar_crit);
+    condvar_seq = 6;
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
+    LeaveCriticalSection (&condvar_crit);
+    ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n");
+    condvar_seq = 7;
+
+    EnterCriticalSection (&condvar_crit);
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
+    LeaveCriticalSection (&condvar_crit);
+    ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
+    ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
+
+    EnterCriticalSection (&condvar_crit);
+    condvar_seq = 8;
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20);
+    LeaveCriticalSection (&condvar_crit);
+    ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
+    condvar_seq = 9;
+
+    return 0;
+}
+
+static void test_condvars_base(void) {
+    HANDLE hp, hc;
+    DWORD dummy;
+    BOOL ret;
+
+
+    if (!pInitializeConditionVariable) {
+        /* function is not yet in XP, only in newer Windows */
+        /* and not yet implemented in Wine for some days/weeks */
+        todo_wine win_skip("no condition variable support.\n");
+        return;
+    }
+
+    InitializeCriticalSection (&condvar_crit);
+
+    EnterCriticalSection (&condvar_crit);
+    ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
+    LeaveCriticalSection (&condvar_crit);
+
+    ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
+    ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
+
+
+    hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy);
+    hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy);
+
+    condvar_seq = 1; /* go */
+
+    while (condvar_seq < 9)
+        Sleep (5);
+    WaitForSingleObject(hp, 100);
+    WaitForSingleObject(hc, 100);
+}
+
+
 START_TEST(sync)
 {
     HMODULE hdll = GetModuleHandle("kernel32");
@@ -1403,5 +1538,6 @@ START_TEST(sync)
     test_WaitForSingleObject();
     test_WaitForMultipleObjects();
     test_initonce();
-    test_condvars();
+    test_condvars_base();
+    test_condvars_consumer_producer();
 }




More information about the wine-cvs mailing list