Commit 17ca7ee8 authored by Marcus Meissner's avatar Marcus Meissner Committed by Alexandre Julliard

kernel32: Conditional variable tests.

parent 35fc9c12
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment