[PATCH] msvcp120: implement _Cnd_* functions (try 3)

Piotr Caban piotr.caban at gmail.com
Thu Nov 12 08:29:58 CST 2015


Hi,

The implementation looks good for me. The tests are over complicated. 
I'm attaching a patch generated on top of yours that simplifies them. If 
you agree with this changes please just squash both commits and resend.

Thanks,
Piotr
-------------- next part --------------
>From 55ea6332d2df9088bb185d0c9023d1fbf88027a6 Mon Sep 17 00:00:00 2001
From: Piotr Caban <piotr at codeweavers.com>
Date: Thu, 12 Nov 2015 15:23:14 +0100
Subject: [PATCH] _Cnd_* tests cleanup
To: wine-patches <wine-patches at winehq.org>

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
---
 dlls/msvcp120/tests/msvcp120.c | 152 +++++++++++++----------------------------
 1 file changed, 47 insertions(+), 105 deletions(-)

diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c
index b05fba4..e69405f 100644
--- a/dlls/msvcp120/tests/msvcp120.c
+++ b/dlls/msvcp120/tests/msvcp120.c
@@ -1303,66 +1303,38 @@ static void test_thrd(void)
 #define NUM_THREADS 10
 struct cndmtx
 {
+    HANDLE initialized;
+    int started;
+    int thread_no;
+
     _Cnd_t cnd;
     _Mtx_t mtx;
-    int    go;
-    int    started;
+    BOOL timed_wait;
 };
 
-static int __cdecl cnd_broadcast_thread(void *arg)
+static int __cdecl cnd_wait_thread(void *arg)
 {
     struct cndmtx *cm = arg;
-    int done;
     int r;
 
-    done = 0;
     p__Mtx_lock(&cm->mtx);
-    while(!cm->go) {
-        if(!done) {
-            if(++cm->started == NUM_THREADS) {
-                r = p__Cnd_broadcast(&cm->cnd);
-                ok(!r, "failed to broadcast\n");
-            }
-            done = 1;
-        }
-        r = p__Cnd_wait(&cm->cnd, &cm->mtx);
-        ok(!r, "failed to wait\n");
-    }
-    p__Mtx_unlock(&cm->mtx);
-    return 0;
-}
 
-static int __cdecl cnd_signal_thread(void *arg)
-{
-    struct cndmtx *cm = arg;
-    int r;
+    if(InterlockedIncrement(&cm->started) == cm->thread_no)
+        SetEvent(cm->initialized);
 
-    p__Mtx_lock(&cm->mtx);
-    while(!cm->go) {
-        if(!cm->started) {
-            cm->started = 1;
-            r = p__Cnd_signal(&cm->cnd);
-            ok(!r, "failed to signal\n");
-        }
+    if(cm->timed_wait) {
+        xtime xt;
+
+        p_xtime_get(&xt, 1);
+        xt.sec += 2;
+        r = p__Cnd_timedwait(&cm->cnd, &cm->mtx, &xt);
+        ok(!r, "timed wait failed\n");
+    } else {
         r = p__Cnd_wait(&cm->cnd, &cm->mtx);
-        ok(!r, "failed to wait\n");
+        ok(!r, "wait failed\n");
     }
-    p__Mtx_unlock(&cm->mtx);
-    return 0;
-}
-
-static int __cdecl cnd_timedwait_thread(void *arg)
-{
-    struct cndmtx *cm = arg;
-    int r;
 
-    p__Mtx_lock(&cm->mtx);
-    cm->started = 1;
     p__Mtx_unlock(&cm->mtx);
-    r = p__Cnd_signal(&cm->cnd);
-    ok(!r, "failed signal\n");
-
-    /* exit without setting go */
     return 0;
 }
 
@@ -1392,111 +1364,81 @@ static void test_cnd(void)
     }
     p__Cnd_destroy(NULL);
 
-    /* test signal */
+    /* test _Cnd_signal/_Cnd_wait */
+    cm.initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
+    cm.started = 0;
+    cm.thread_no = 1;
     cm.cnd = cnd;
     cm.mtx = mtx;
-    cm.go = 0;
-    cm.started = 0;
-    p__Thrd_create(&threads[0], cnd_signal_thread, (void*)&cm);
+    cm.timed_wait = FALSE;
+    p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
 
+    WaitForSingleObject(cm.initialized, INFINITE);
     p__Mtx_lock(&mtx);
-    while(cm.started != 1) {
-        r = p__Cnd_wait(&cm.cnd, &cm.mtx);
-        ok(!r, "failed to wait\n");
-    }
     p__Mtx_unlock(&mtx);
 
-    p__Mtx_lock(&cm.mtx);
-    cm.go = 1;
-    p__Mtx_unlock(&cm.mtx);
     r = p__Cnd_signal(&cm.cnd);
     ok(!r, "failed to signal\n");
-
     p__Thrd_join(threads[0], NULL);
 
-    /* test time out on purpose */
-    p_xtime_get(&xt, 1);
-    xt.sec += 2;
-
+    /* test _Cnd_timedwait time out */
     p__Mtx_lock(&mtx);
     p_xtime_get(&before, 1);
+    xt = before;
+    xt.sec += 1;
     r = p__Cnd_timedwait(&cnd, &mtx, &xt);
     p_xtime_get(&after, 1);
     p__Mtx_unlock(&mtx);
 
     diff = p__Xtime_diff_to_millis2(&after, &before);
     ok(r == 2, "should have timed out\n");
-    ok(diff > 2000 - TIMEDELTA, "got %d\n", diff);
+    ok(diff > 1000 - TIMEDELTA, "got %d\n", diff);
 
-    /* test timed wait */
-    cm.go = 0;
+    /* test _Cnd_timedwait */
     cm.started = 0;
-    p__Thrd_create(&threads[0], cnd_timedwait_thread, (void*)&cm);
+    cm.timed_wait = TRUE;
+    p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
 
-    /* wait up to 5 seconds for thread to start (should pass) */
-    p_xtime_get(&xt, 1);
-    xt.sec += 5;
+    WaitForSingleObject(cm.initialized, INFINITE);
     p__Mtx_lock(&mtx);
-    while(!cm.started) {
-        r = p__Cnd_timedwait(&cnd, &mtx, &xt);
-        ok(!r, "failed timed wait\n");
-    }
     p__Mtx_unlock(&mtx);
 
-    /* wait for thread to set go (which it won't, so should time out) */
-    p_xtime_get(&xt, 1);
-    xt.sec += 1;
-    r = 0;
-    p__Mtx_lock(&mtx);
-    while(!r && !cm.go) {
-        r = p__Cnd_timedwait(&cnd, &mtx, &xt);
-        ok(r == 2, "timed wait did not timeout: %d\n", r);
-    }
-    p__Mtx_unlock(&mtx);
+    r = p__Cnd_signal(&cm.cnd);
+    ok(!r, "failed to signal\n");
     p__Thrd_join(threads[0], NULL);
 
-    /* test broadcast with _Cnd_broadcast */
-    cm.go  = 0;
+    /* test _Cnd_broadcast */
     cm.started = 0;
-    for(i = 0; i < NUM_THREADS; i++)
-        p__Thrd_create(&threads[i], cnd_broadcast_thread, (void*)&cm);
+    cm.thread_no = NUM_THREADS;
+    cm.timed_wait = FALSE;
 
-    p__Mtx_lock(&mtx);
-    while(cm.started != NUM_THREADS) {
-        r = p__Cnd_wait(&cm.cnd, &cm.mtx);
-        ok(!r, "failed to wait\n");
-    }
-    p__Mtx_unlock(&mtx);
+    for(i = 0; i < cm.thread_no; i++)
+        p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
 
+    WaitForSingleObject(cm.initialized, INFINITE);
     p__Mtx_lock(&mtx);
-    cm.go = 1;
     p__Mtx_unlock(&mtx);
+
     r = p__Cnd_broadcast(&cnd);
     ok(!r, "failed to broadcast\n");
-    for(i = 0; i < NUM_THREADS; i++)
+    for(i = 0; i < cm.thread_no; i++)
         p__Thrd_join(threads[i], NULL);
 
     /* test broadcast with _Cnd_destroy */
-    cm.go = 0;
     cm.started = 0;
-    for(i = 0; i < NUM_THREADS; i++)
-        p__Thrd_create(&threads[i], cnd_broadcast_thread, (void*)&cm);
+    for(i = 0; i < cm.thread_no; i++)
+        p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
 
+    WaitForSingleObject(cm.initialized, INFINITE);
     p__Mtx_lock(&mtx);
-    while(cm.started != NUM_THREADS) {
-        r = p__Cnd_wait(&cm.cnd, &cm.mtx);
-        ok(!r, "failed to wait\n");
-    }
     p__Mtx_unlock(&mtx);
 
-    p__Mtx_lock(&mtx);
-    cm.go = 1;
-    p__Mtx_unlock(&mtx);
     p__Cnd_destroy(&cnd);
-    for(i = 0; i < NUM_THREADS; i++)
+    for(i = 0; i < cm.thread_no; i++)
         p__Thrd_join(threads[i], NULL);
 
     p__Mtx_destroy(&mtx);
+    CloseHandle(cm.initialized);
 }
 
 START_TEST(msvcp120)
-- 
2.4.10



More information about the wine-devel mailing list