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