Blame winpr/libwinpr/synch/test/TestSynchBarrier.c

Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
#include <winpr/synch.h>
Packit Service fa4841
#include <winpr/thread.h>
Packit Service fa4841
#include <winpr/interlocked.h>
Packit Service fa4841
#include <winpr/sysinfo.h>
Packit Service fa4841
Packit Service fa4841
#include "../synch.h"
Packit Service fa4841
Packit Service fa4841
static SYNCHRONIZATION_BARRIER gBarrier;
Packit Service fa4841
static HANDLE gStartEvent = NULL;
Packit Service bb5c11
static LONG gErrorCount  = 0;
Packit Service fa4841
Packit Service bb5c11
#define MAX_SLEEP_MS    32
Packit Service fa4841
Packit Service fa4841
struct test_params
Packit Service fa4841
{
Packit Service fa4841
	LONG threadCount;
Packit Service fa4841
	LONG trueCount;
Packit Service fa4841
	LONG falseCount;
Packit Service fa4841
	DWORD loops;
Packit Service fa4841
	DWORD flags;
Packit Service fa4841
};
Packit Service fa4841
Packit Service bb5c11
Packit Service fa4841
static DWORD WINAPI test_synch_barrier_thread(LPVOID lpParam)
Packit Service fa4841
{
Packit Service fa4841
	BOOL status = FALSE;
Packit Service fa4841
	struct test_params* p = (struct test_params*)lpParam;
Packit Service fa4841
	DWORD i;
Packit Service fa4841
Packit Service fa4841
	InterlockedIncrement(&p->threadCount);
Packit Service fa4841
Packit Service bb5c11
	//printf("Thread #%03u entered.\n", tnum);
Packit Service fa4841
Packit Service fa4841
	/* wait for start event from main */
Packit Service fa4841
	if (WaitForSingleObject(gStartEvent, INFINITE) != WAIT_OBJECT_0)
Packit Service fa4841
	{
Packit Service fa4841
		InterlockedIncrement(&gErrorCount);
Packit Service fa4841
		goto out;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service bb5c11
	//printf("Thread #%03u unblocked.\n", tnum);
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < p->loops && gErrorCount == 0; i++)
Packit Service fa4841
	{
Packit Service fa4841
		/* simulate different execution times before the barrier */
Packit Service fa4841
		Sleep(rand() % MAX_SLEEP_MS);
Packit Service fa4841
		status = EnterSynchronizationBarrier(&gBarrier, p->flags);
Packit Service fa4841
Packit Service bb5c11
		//printf("Thread #%03u status: %s\n", tnum, status ? "TRUE" : "FALSE");
Packit Service fa4841
		if (status)
Packit Service fa4841
			InterlockedIncrement(&p->trueCount);
Packit Service fa4841
		else
Packit Service fa4841
			InterlockedIncrement(&p->falseCount);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
out:
Packit Service bb5c11
	//printf("Thread #%03u leaving.\n", tnum);
Packit Service fa4841
	return 0;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
Packit Service fa4841
static BOOL TestSynchBarrierWithFlags(DWORD dwFlags, DWORD dwThreads, DWORD dwLoops)
Packit Service fa4841
{
Packit Service fa4841
	HANDLE* threads;
Packit Service fa4841
	struct test_params p;
Packit Service fa4841
	DWORD dwStatus, expectedTrueCount, expectedFalseCount;
Packit Service fa4841
	DWORD i;
Packit Service fa4841
	p.threadCount = 0;
Packit Service bb5c11
	p.trueCount   = 0;
Packit Service bb5c11
	p.falseCount  = 0;
Packit Service fa4841
	p.loops = dwLoops;
Packit Service fa4841
	p.flags = dwFlags;
Packit Service fa4841
	expectedTrueCount = dwLoops;
Packit Service fa4841
	expectedFalseCount = dwLoops * (dwThreads - 1);
Packit Service bb5c11
	printf("%s: >> Testing with flags 0x%08"PRIx32". Using %"PRIu32" threads performing %"PRIu32" loops\n",
Packit Service fa4841
	       __FUNCTION__, dwFlags, dwThreads, dwLoops);
Packit Service fa4841
Packit Service fa4841
	if (!(threads = calloc(dwThreads, sizeof(HANDLE))))
Packit Service fa4841
	{
Packit Service fa4841
		printf("%s: error allocatin thread array memory\n", __FUNCTION__);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!InitializeSynchronizationBarrier(&gBarrier, dwThreads, -1))
Packit Service fa4841
	{
Packit Service bb5c11
		printf("%s: InitializeSynchronizationBarrier failed. GetLastError() = 0x%08x",
Packit Service bb5c11
		       __FUNCTION__, GetLastError());
Packit Service fa4841
		free(threads);
Packit Service fa4841
		DeleteSynchronizationBarrier(&gBarrier);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!(gStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
Packit Service fa4841
	{
Packit Service bb5c11
		printf("%s: CreateEvent failed with error 0x%08x", __FUNCTION__,
Packit Service bb5c11
		       GetLastError());
Packit Service fa4841
		free(threads);
Packit Service fa4841
		DeleteSynchronizationBarrier(&gBarrier);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < dwThreads; i++)
Packit Service fa4841
	{
Packit Service bb5c11
		if (!(threads[i] = CreateThread(NULL, 0, test_synch_barrier_thread, &p, 0,
Packit Service bb5c11
						NULL)))
Packit Service fa4841
		{
Packit Service bb5c11
			printf("%s: CreateThread failed for thread #%"PRIu32" with error 0x%08x\n",
Packit Service fa4841
			       __FUNCTION__, i, GetLastError());
Packit Service fa4841
			InterlockedIncrement(&gErrorCount);
Packit Service fa4841
			break;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (i > 0)
Packit Service fa4841
	{
Packit Service fa4841
		if (!SetEvent(gStartEvent))
Packit Service fa4841
		{
Packit Service bb5c11
			printf("%s: SetEvent(gStartEvent) failed with error = 0x%08x)\n",
Packit Service bb5c11
			       __FUNCTION__, GetLastError());
Packit Service fa4841
			InterlockedIncrement(&gErrorCount);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		while (i--)
Packit Service fa4841
		{
Packit Service fa4841
			if (WAIT_OBJECT_0 != (dwStatus = WaitForSingleObject(threads[i], INFINITE)))
Packit Service fa4841
			{
Packit Service bb5c11
				printf("%s: WaitForSingleObject(thread[%"PRIu32"] unexpectedly returned %"PRIu32" (error = 0x%08x)\n",
Packit Service fa4841
				       __FUNCTION__, i, dwStatus, GetLastError());
Packit Service fa4841
				InterlockedIncrement(&gErrorCount);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			if (!CloseHandle(threads[i]))
Packit Service fa4841
			{
Packit Service bb5c11
				printf("%s: CloseHandle(thread[%"PRIu32"]) failed with error = 0x%08x)\n",
Packit Service fa4841
				       __FUNCTION__, i, GetLastError());
Packit Service fa4841
				InterlockedIncrement(&gErrorCount);
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	free(threads);
Packit Service fa4841
Packit Service fa4841
	if (!CloseHandle(gStartEvent))
Packit Service fa4841
	{
Packit Service bb5c11
		printf("%s: CloseHandle(gStartEvent) failed with error = 0x%08x)\n",
Packit Service bb5c11
		       __FUNCTION__, GetLastError());
Packit Service fa4841
		InterlockedIncrement(&gErrorCount);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	DeleteSynchronizationBarrier(&gBarrier);
Packit Service fa4841
Packit Service bb5c11
	if (p.threadCount != dwThreads)
Packit Service fa4841
		InterlockedIncrement(&gErrorCount);
Packit Service fa4841
Packit Service bb5c11
	if (p.trueCount != expectedTrueCount)
Packit Service fa4841
		InterlockedIncrement(&gErrorCount);
Packit Service fa4841
Packit Service bb5c11
	if (p.falseCount != expectedFalseCount)
Packit Service fa4841
		InterlockedIncrement(&gErrorCount);
Packit Service fa4841
Packit Service bb5c11
	printf("%s: error count:  %"PRId32"\n", __FUNCTION__, gErrorCount);
Packit Service bb5c11
	printf("%s: thread count: %"PRId32" (expected %"PRIu32")\n", __FUNCTION__, p.threadCount,
Packit Service fa4841
	       dwThreads);
Packit Service bb5c11
	printf("%s: true count:   %"PRId32" (expected %"PRIu32")\n", __FUNCTION__, p.trueCount,
Packit Service fa4841
	       expectedTrueCount);
Packit Service bb5c11
	printf("%s: false count:  %"PRId32" (expected %"PRIu32")\n", __FUNCTION__, p.falseCount,
Packit Service fa4841
	       expectedFalseCount);
Packit Service fa4841
Packit Service fa4841
	if (gErrorCount > 0)
Packit Service fa4841
	{
Packit Service bb5c11
		printf("%s: Error test failed with %"PRId32" reported errors\n", __FUNCTION__,
Packit Service fa4841
		       gErrorCount);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
Packit Service fa4841
int TestSynchBarrier(int argc, char* argv[])
Packit Service fa4841
{
Packit Service fa4841
	SYSTEM_INFO sysinfo;
Packit Service fa4841
	DWORD dwMaxThreads;
Packit Service fa4841
	DWORD dwMinThreads;
Packit Service fa4841
	DWORD dwNumLoops = 200;
Packit Service fa4841
	GetNativeSystemInfo(&sysinfo);
Packit Service bb5c11
	printf("%s: Number of processors: %"PRIu32"\n", __FUNCTION__,
Packit Service bb5c11
	       sysinfo.dwNumberOfProcessors);
Packit Service fa4841
	dwMinThreads = sysinfo.dwNumberOfProcessors;
Packit Service fa4841
	dwMaxThreads = sysinfo.dwNumberOfProcessors * 4;
Packit Service fa4841
Packit Service fa4841
	if (dwMaxThreads > 32)
Packit Service fa4841
		dwMaxThreads = 32;
Packit Service fa4841
Packit Service fa4841
	/* Test invalid parameters */
Packit Service fa4841
	if (InitializeSynchronizationBarrier(&gBarrier, 0, -1))
Packit Service fa4841
	{
Packit Service bb5c11
		printf("%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = 0\n",
Packit Service bb5c11
		       __FUNCTION__);
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (InitializeSynchronizationBarrier(&gBarrier, -1, -1))
Packit Service fa4841
	{
Packit Service bb5c11
		printf("%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = -1\n",
Packit Service bb5c11
		       __FUNCTION__);
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (InitializeSynchronizationBarrier(&gBarrier, 1, -2))
Packit Service fa4841
	{
Packit Service fa4841
		printf("%s: InitializeSynchronizationBarrier unecpectedly succeeded with lSpinCount = -2\n",
Packit Service fa4841
		       __FUNCTION__);
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* Functional tests */
Packit Service fa4841
Packit Service fa4841
	if (!TestSynchBarrierWithFlags(0, dwMaxThreads, dwNumLoops))
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service bb5c11
	if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY,
Packit Service bb5c11
				       dwMinThreads, dwNumLoops))
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service bb5c11
	if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY,
Packit Service bb5c11
				       dwMaxThreads, dwNumLoops))
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
	printf("%s: Test successfully completed\n", __FUNCTION__);
Packit Service fa4841
	return 0;
Packit Service fa4841
}