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

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