3#include <winpr/crypto.h>
4#include <winpr/synch.h>
5#include <winpr/thread.h>
6#include <winpr/interlocked.h>
7#include <winpr/sysinfo.h>
12static HANDLE gStartEvent =
nullptr;
13static LONG gErrorCount = 0;
15#define MAX_SLEEP_MS 22
26static UINT32 prand(UINT32 max)
31 if (winpr_RAND(&tmp,
sizeof(tmp)) < 0)
36 return tmp % (max - 1) + 1;
39static DWORD WINAPI test_synch_barrier_thread(LPVOID lpParam)
42 struct test_params* p = (
struct test_params*)lpParam;
44 InterlockedIncrement(&p->threadCount);
49 if (WaitForSingleObject(gStartEvent, INFINITE) != WAIT_OBJECT_0)
51 InterlockedIncrement(&gErrorCount);
57 for (DWORD i = 0; i < p->loops && gErrorCount == 0; i++)
60 Sleep(1 + prand(MAX_SLEEP_MS));
61 status = EnterSynchronizationBarrier(&gBarrier, p->flags);
65 InterlockedIncrement(&p->trueCount);
67 InterlockedIncrement(&p->falseCount);
75static BOOL TestSynchBarrierWithFlags(DWORD dwFlags, DWORD dwThreads, DWORD dwLoops)
80 struct test_params p = {
81 .threadCount = 0, .trueCount = 0, .falseCount = 0, .loops = dwLoops, .flags = dwFlags
83 DWORD expectedTrueCount = dwLoops;
84 DWORD expectedFalseCount = dwLoops * (dwThreads - 1);
86 printf(
"%s: >> Testing with flags 0x%08" PRIx32
". Using %" PRIu32
87 " threads performing %" PRIu32
" loops\n",
88 __func__, dwFlags, dwThreads, dwLoops);
90 HANDLE* threads = (HANDLE*)calloc(dwThreads,
sizeof(HANDLE));
93 printf(
"%s: error allocatin thread array memory\n", __func__);
97 if (dwThreads > INT32_MAX)
100 if (!InitializeSynchronizationBarrier(&gBarrier, (LONG)dwThreads, -1))
102 printf(
"%s: InitializeSynchronizationBarrier failed. GetLastError() = 0x%08x", __func__,
107 if (!(gStartEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
109 printf(
"%s: CreateEvent failed with error 0x%08x", __func__, GetLastError());
114 for (; i < dwThreads; i++)
116 threads[i] = CreateThread(
nullptr, 0, test_synch_barrier_thread, &p, 0,
nullptr);
119 printf(
"%s: CreateThread failed for thread #%" PRIu32
" with error 0x%08x\n", __func__,
121 InterlockedIncrement(&gErrorCount);
128 if (!SetEvent(gStartEvent))
130 printf(
"%s: SetEvent(gStartEvent) failed with error = 0x%08x)\n", __func__,
132 InterlockedIncrement(&gErrorCount);
137 if (WAIT_OBJECT_0 != (dwStatus = WaitForSingleObject(threads[i], INFINITE)))
139 printf(
"%s: WaitForSingleObject(thread[%" PRIu32
"] unexpectedly returned %" PRIu32
140 " (error = 0x%08x)\n",
141 __func__, i, dwStatus, GetLastError());
142 InterlockedIncrement(&gErrorCount);
145 if (!CloseHandle(threads[i]))
147 printf(
"%s: CloseHandle(thread[%" PRIu32
"]) failed with error = 0x%08x)\n",
148 __func__, i, GetLastError());
149 InterlockedIncrement(&gErrorCount);
154 if (!CloseHandle(gStartEvent))
156 printf(
"%s: CloseHandle(gStartEvent) failed with error = 0x%08x)\n", __func__,
158 InterlockedIncrement(&gErrorCount);
161 if (p.threadCount != (INT64)dwThreads)
162 InterlockedIncrement(&gErrorCount);
164 if (p.trueCount != (INT64)expectedTrueCount)
165 InterlockedIncrement(&gErrorCount);
167 if (p.falseCount != (INT64)expectedFalseCount)
168 InterlockedIncrement(&gErrorCount);
170 printf(
"%s: error count: %" PRId32
"\n", __func__, gErrorCount);
171 printf(
"%s: thread count: %" PRId32
" (expected %" PRIu32
")\n", __func__, p.threadCount,
173 printf(
"%s: true count: %" PRId32
" (expected %" PRIu32
")\n", __func__, p.trueCount,
175 printf(
"%s: false count: %" PRId32
" (expected %" PRIu32
")\n", __func__, p.falseCount,
180 free((
void*)threads);
181 DeleteSynchronizationBarrier(&gBarrier);
184 printf(
"%s: Error test failed with %" PRId32
" reported errors\n", __func__, gErrorCount);
191int TestSynchBarrier(
int argc,
char* argv[])
194 DWORD dwMaxThreads = 0;
195 DWORD dwMinThreads = 0;
196 DWORD dwNumLoops = 10;
201 GetNativeSystemInfo(&sysinfo);
202 printf(
"%s: Number of processors: %" PRIu32
"\n", __func__, sysinfo.dwNumberOfProcessors);
203 dwMinThreads = sysinfo.dwNumberOfProcessors;
204 dwMaxThreads = sysinfo.dwNumberOfProcessors * 4;
206 if (dwMaxThreads > 32)
210 if (InitializeSynchronizationBarrier(&gBarrier, 0, -1))
214 "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = 0\n",
219 if (InitializeSynchronizationBarrier(&gBarrier, -1, -1))
223 "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = -1\n",
228 if (InitializeSynchronizationBarrier(&gBarrier, 1, -2))
232 "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lSpinCount = -2\n",
239 if (!TestSynchBarrierWithFlags(0, dwMaxThreads, dwNumLoops))
243 "%s: TestSynchBarrierWithFlags(0) unecpectedly succeeded with lTotalThreads = -1\n",
248 if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY, dwMinThreads,
251 (void)fprintf(stderr,
252 "%s: TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY) "
253 "unecpectedly succeeded with lTotalThreads = -1\n",
258 if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY, dwMaxThreads,
261 (void)fprintf(stderr,
262 "%s: TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY) "
263 "unecpectedly succeeded with lTotalThreads = -1\n",
268 printf(
"%s: Test successfully completed\n", __func__);