From: Daniel Lehman dlehman25@gmail.com
--- dlls/msvcp140/tests/msvcp140.c | 78 ++++++++++++++++++++++++++++++---- dlls/msvcp90/misc.c | 6 +++ 2 files changed, 75 insertions(+), 9 deletions(-)
diff --git a/dlls/msvcp140/tests/msvcp140.c b/dlls/msvcp140/tests/msvcp140.c index 0688239a1fc..b1ab13fe80b 100644 --- a/dlls/msvcp140/tests/msvcp140.c +++ b/dlls/msvcp140/tests/msvcp140.c @@ -179,7 +179,10 @@ typedef struct { DWORD count; } *_Mtx_t;
-typedef void *_Cnd_t; +typedef struct { + ULONG_PTR unknown; + CONDITION_VARIABLE cv; +} *_Cnd_t;
typedef struct { __time64_t sec; @@ -222,6 +225,8 @@ static int (__cdecl *p__Mtx_init)(_Mtx_t*, int); static void (__cdecl *p__Mtx_destroy)(_Mtx_t); static int (__cdecl *p__Mtx_lock)(_Mtx_t); static int (__cdecl *p__Mtx_unlock)(_Mtx_t); +static void (__cdecl *p__Mtx_clear_owner)(_Mtx_t); +static void (__cdecl *p__Mtx_reset_owner)(_Mtx_t); static int (__cdecl *p__Cnd_init)(_Cnd_t*); static void (__cdecl *p__Cnd_destroy)(_Cnd_t); static int (__cdecl *p__Cnd_wait)(_Cnd_t, _Mtx_t); @@ -358,6 +363,8 @@ static BOOL init(void) SET(p__Mtx_destroy, "_Mtx_destroy"); SET(p__Mtx_lock, "_Mtx_lock"); SET(p__Mtx_unlock, "_Mtx_unlock"); + SET(p__Mtx_clear_owner, "_Mtx_clear_owner"); + SET(p__Mtx_reset_owner, "_Mtx_reset_owner"); SET(p__Cnd_init, "_Cnd_init"); SET(p__Cnd_destroy, "_Cnd_destroy"); SET(p__Cnd_wait, "_Cnd_wait"); @@ -1504,6 +1511,7 @@ struct cndmtx _Cnd_t cnd; _Mtx_t mtx; BOOL timed_wait; + BOOL use_cnd_func; };
static int __cdecl cnd_wait_thread(void *arg) @@ -1516,16 +1524,23 @@ static int __cdecl cnd_wait_thread(void *arg) if(InterlockedIncrement(&cm->started) == cm->thread_no) SetEvent(cm->initialized);
- if(cm->timed_wait) { - xtime xt; + if(cm->use_cnd_func) { + if(cm->timed_wait) { + xtime xt; + p_xtime_get(&xt, 1); + xt.sec += 2;
- 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); + r = p__Cnd_timedwait(cm->cnd, cm->mtx, &xt); + } else { + r = p__Cnd_wait(cm->cnd, cm->mtx); + } ok(!r, "wait failed\n"); + } else { + p__Mtx_clear_owner(cm->mtx); + r = SleepConditionVariableSRW(&cm->cnd->cv, &cm->mtx->cs.win, + cm->timed_wait ? 2000 : INFINITE, 0); + ok(r, "wait failed\n"); + p__Mtx_reset_owner(cm->mtx); }
p__Mtx_unlock(cm->mtx); @@ -1556,12 +1571,27 @@ static void test_cnd(void) cm.cnd = cnd; cm.mtx = mtx; cm.timed_wait = FALSE; + cm.use_cnd_func = TRUE; + p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm); + + WaitForSingleObject(cm.initialized, INFINITE); + p__Mtx_lock(mtx); + p__Mtx_unlock(mtx); + + /* signal cnd function with kernel function */ + WakeConditionVariable(&cm.cnd->cv); + p__Thrd_join(threads[0], NULL); + + cm.started = 0; + cm.thread_no = 1; + cm.use_cnd_func = FALSE; p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
WaitForSingleObject(cm.initialized, INFINITE); p__Mtx_lock(mtx); p__Mtx_unlock(mtx);
+ /* signal kernel functions with cnd function */ r = p__Cnd_signal(cm.cnd); ok(!r, "failed to signal\n"); p__Thrd_join(threads[0], NULL); @@ -1584,20 +1614,49 @@ static void test_cnd(void) /* test _Cnd_timedwait */ cm.started = 0; cm.timed_wait = TRUE; + cm.use_cnd_func = TRUE; p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
WaitForSingleObject(cm.initialized, INFINITE); p__Mtx_lock(mtx); p__Mtx_unlock(mtx);
+ /* signal cnd function with kernel function */ + WakeConditionVariable(&cm.cnd->cv); + p__Thrd_join(threads[0], NULL); + + cm.started = 0; + cm.use_cnd_func = FALSE; + p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm); + + WaitForSingleObject(cm.initialized, INFINITE); + p__Mtx_lock(mtx); + p__Mtx_unlock(mtx); + + /* signal kernel functions with cnd function */ r = p__Cnd_signal(cm.cnd); ok(!r, "failed to signal\n"); p__Thrd_join(threads[0], NULL);
/* test _Cnd_broadcast */ cm.started = 0; + cm.timed_wait = FALSE; + cm.use_cnd_func = TRUE; cm.thread_no = NUM_THREADS; + 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); + p__Mtx_unlock(mtx); + + /* signal cnd function with kernel function */ + WakeAllConditionVariable(&cm.cnd->cv); + for(i = 0; i < cm.thread_no; i++) + p__Thrd_join(threads[i], NULL); + + cm.started = 0; + cm.use_cnd_func = FALSE; for(i = 0; i < cm.thread_no; i++) p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
@@ -1605,6 +1664,7 @@ static void test_cnd(void) p__Mtx_lock(mtx); p__Mtx_unlock(mtx);
+ /* signal kernel functions with cnd function */ r = p__Cnd_broadcast(cnd); ok(!r, "failed to broadcast\n"); for(i = 0; i < cm.thread_no; i++) diff --git a/dlls/msvcp90/misc.c b/dlls/msvcp90/misc.c index 088ecc9976c..80256c1f357 100644 --- a/dlls/msvcp90/misc.c +++ b/dlls/msvcp90/misc.c @@ -832,6 +832,9 @@ void __cdecl _Mtx_reset_owner(_Mtx_arg_t mtx)
typedef struct { +#if _MSVCP_VER >= 140 + ULONG_PTR unknown; +#endif cv cv; } *_Cnd_t;
@@ -847,6 +850,9 @@ typedef _Cnd_t *_Cnd_arg_t;
void __cdecl _Cnd_init_in_situ(_Cnd_t cnd) { +#if _MSVCP_VER >= 140 + cnd->unknown = 0; +#endif cv_init(&cnd->cv); }