kernel32: Add condition variables prototypes and tests.

This commit is contained in:
Marcus Meissner 2012-09-03 13:54:46 +02:00 committed by Alexandre Julliard
parent 1a4a1e5323
commit 7a529328db
3 changed files with 130 additions and 0 deletions

View File

@ -42,6 +42,11 @@ static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVO
static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
static void test_signalandwait(void)
{
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
@ -1238,6 +1243,112 @@ static void test_initonce(void)
ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
}
static CONDITION_VARIABLE buffernotempty,buffernotfull;
static CRITICAL_SECTION buffercrit;
static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
static LONG bufferlen,totalproduced,totalconsumed;
static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
#define BUFFER_SIZE 10
static DWORD WINAPI condvar_producer(LPVOID x) {
while (1) {
Sleep(rand() % 10);
EnterCriticalSection(&buffercrit);
while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
condvar_producer_sleepcnt++;
if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, 2000))
condvar_sleeperr = TRUE;
}
if (condvar_stop) {
LeaveCriticalSection(&buffercrit);
break;
}
bufferlen++;
totalproduced++;
LeaveCriticalSection(&buffercrit);
pWakeConditionVariable(&buffernotempty);
}
return 0;
}
static DWORD WINAPI condvar_consumer(LPVOID x) {
DWORD *cnt = (DWORD*)x;
while (1) {
EnterCriticalSection(&buffercrit);
while ((bufferlen == 0) && !condvar_stop) {
condvar_consumer_sleepcnt++;
if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, 2000))
condvar_sleeperr = TRUE;
}
if (condvar_stop && (bufferlen == 0)) {
LeaveCriticalSection(&buffercrit);
break;
}
bufferlen--;
totalconsumed++;
(*cnt)++;
LeaveCriticalSection(&buffercrit);
pWakeConditionVariable(&buffernotfull);
Sleep(rand() % 10);
}
return 0;
}
static void test_condvars(void)
{
HANDLE hp1,hp2,hc1,hc2;
DWORD dummy;
DWORD cnt1,cnt2;
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;
}
/* Implement a producer / consumer scheme with non-full / non-empty triggers */
pInitializeConditionVariable(&buffernotfull);
pInitializeConditionVariable(&buffernotempty);
InitializeCriticalSection(&buffercrit);
bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = 0;
hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
/* Limit run to 0.5 seconds. */
Sleep(500);
/* tear down start */
condvar_stop = TRUE;
/* final wake up call */
pWakeAllConditionVariable (&buffernotfull);
pWakeAllConditionVariable (&buffernotempty);
WaitForSingleObject(hp1, 1000);
WaitForSingleObject(hp2, 1000);
WaitForSingleObject(hc1, 1000);
WaitForSingleObject(hc2, 1000);
ok(totalconsumed == totalproduced,
"consumed %d != produced %d\n", totalconsumed, totalproduced);
ok (!condvar_sleeperr, "error occured during SleepConditionVariableCS\n");
/* Checking cnt1 - cnt2 for non-0 would be not good, the case where
* one consumer does not get anything to do is possible. */
trace("produced %d, c1 %d, c2 %d\n", totalproduced, cnt1, cnt2);
/* The sleeps of the producer or consumer should not go above 100* produced count,
* otherwise the implementation does not sleep correctly. But yet again, this is
* not hard defined. */
trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
}
START_TEST(sync)
{
HMODULE hdll = GetModuleHandle("kernel32");
@ -1254,6 +1365,10 @@ START_TEST(sync)
pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
test_signalandwait();
test_mutex();
@ -1266,4 +1381,5 @@ START_TEST(sync)
test_WaitForSingleObject();
test_WaitForMultipleObjects();
test_initonce();
test_condvars();
}

View File

@ -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
@ -1880,6 +1884,7 @@ WINBASEAPI BOOL WINAPI HeapValidate(HANDLE,DWORD,LPCVOID);
WINBASEAPI BOOL WINAPI HeapWalk(HANDLE,LPPROCESS_HEAP_ENTRY);
WINBASEAPI BOOL WINAPI InitAtomTable(DWORD);
WINADVAPI BOOL WINAPI InitializeAcl(PACL,DWORD,DWORD);
WINBASEAPI VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE);
WINBASEAPI void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
WINBASEAPI BOOL WINAPI InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *,DWORD);
WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(CRITICAL_SECTION *,DWORD,DWORD);
@ -2172,6 +2177,7 @@ WINBASEAPI BOOL WINAPI SetupComm(HANDLE,DWORD,DWORD);
WINBASEAPI DWORD WINAPI SignalObjectAndWait(HANDLE,HANDLE,DWORD,BOOL);
WINBASEAPI DWORD WINAPI SizeofResource(HMODULE,HRSRC);
WINBASEAPI VOID WINAPI Sleep(DWORD);
WINBASEAPI BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
WINBASEAPI DWORD WINAPI SleepEx(DWORD,BOOL);
WINBASEAPI DWORD WINAPI SuspendThread(HANDLE);
WINBASEAPI void WINAPI SwitchToFiber(LPVOID);
@ -2224,6 +2230,8 @@ WINBASEAPI DWORD WINAPI WaitForSingleObjectEx(HANDLE,DWORD,BOOL);
WINBASEAPI BOOL WINAPI WaitNamedPipeA(LPCSTR,DWORD);
WINBASEAPI BOOL WINAPI WaitNamedPipeW(LPCWSTR,DWORD);
#define WaitNamedPipe WINELIB_NAME_AW(WaitNamedPipe)
WINBASEAPI VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE);
WINBASEAPI VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE);
WINBASEAPI UINT WINAPI WinExec(LPCSTR,UINT);
WINBASEAPI BOOL WINAPI Wow64DisableWow64FsRedirection(PVOID*);
WINBASEAPI BOOLEAN WINAPI Wow64EnableWow64FsRedirection(BOOLEAN);

View File

@ -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 );