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>
12 static HANDLE gStartEvent = NULL;
13 static LONG gErrorCount = 0;
15 #define MAX_SLEEP_MS 22
26 static UINT32 prand(UINT32 max)
31 winpr_RAND(&tmp,
sizeof(tmp));
32 return tmp % (max - 1) + 1;
35 static DWORD WINAPI test_synch_barrier_thread(LPVOID lpParam)
38 struct test_params* p = (
struct test_params*)lpParam;
40 InterlockedIncrement(&p->threadCount);
45 if (WaitForSingleObject(gStartEvent, INFINITE) != WAIT_OBJECT_0)
47 InterlockedIncrement(&gErrorCount);
53 for (DWORD i = 0; i < p->loops && gErrorCount == 0; i++)
56 Sleep(1 + prand(MAX_SLEEP_MS));
57 status = EnterSynchronizationBarrier(&gBarrier, p->flags);
61 InterlockedIncrement(&p->trueCount);
63 InterlockedIncrement(&p->falseCount);
71 static BOOL TestSynchBarrierWithFlags(DWORD dwFlags, DWORD dwThreads, DWORD dwLoops)
76 struct test_params p = {
77 .threadCount = 0, .trueCount = 0, .falseCount = 0, .loops = dwLoops, .flags = dwFlags
79 DWORD expectedTrueCount = dwLoops;
80 DWORD expectedFalseCount = dwLoops * (dwThreads - 1);
82 printf(
"%s: >> Testing with flags 0x%08" PRIx32
". Using %" PRIu32
83 " threads performing %" PRIu32
" loops\n",
84 __func__, dwFlags, dwThreads, dwLoops);
86 HANDLE* threads = (HANDLE*)calloc(dwThreads,
sizeof(HANDLE));
89 printf(
"%s: error allocatin thread array memory\n", __func__);
93 if (dwThreads > INT32_MAX)
96 if (!InitializeSynchronizationBarrier(&gBarrier, (LONG)dwThreads, -1))
98 printf(
"%s: InitializeSynchronizationBarrier failed. GetLastError() = 0x%08x", __func__,
103 if (!(gStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
105 printf(
"%s: CreateEvent failed with error 0x%08x", __func__, GetLastError());
110 for (; i < dwThreads; i++)
112 threads[i] = CreateThread(NULL, 0, test_synch_barrier_thread, &p, 0, NULL);
115 printf(
"%s: CreateThread failed for thread #%" PRIu32
" with error 0x%08x\n", __func__,
117 InterlockedIncrement(&gErrorCount);
124 if (!SetEvent(gStartEvent))
126 printf(
"%s: SetEvent(gStartEvent) failed with error = 0x%08x)\n", __func__,
128 InterlockedIncrement(&gErrorCount);
133 if (WAIT_OBJECT_0 != (dwStatus = WaitForSingleObject(threads[i], INFINITE)))
135 printf(
"%s: WaitForSingleObject(thread[%" PRIu32
"] unexpectedly returned %" PRIu32
136 " (error = 0x%08x)\n",
137 __func__, i, dwStatus, GetLastError());
138 InterlockedIncrement(&gErrorCount);
141 if (!CloseHandle(threads[i]))
143 printf(
"%s: CloseHandle(thread[%" PRIu32
"]) failed with error = 0x%08x)\n",
144 __func__, i, GetLastError());
145 InterlockedIncrement(&gErrorCount);
150 if (!CloseHandle(gStartEvent))
152 printf(
"%s: CloseHandle(gStartEvent) failed with error = 0x%08x)\n", __func__,
154 InterlockedIncrement(&gErrorCount);
157 if (p.threadCount != (INT64)dwThreads)
158 InterlockedIncrement(&gErrorCount);
160 if (p.trueCount != (INT64)expectedTrueCount)
161 InterlockedIncrement(&gErrorCount);
163 if (p.falseCount != (INT64)expectedFalseCount)
164 InterlockedIncrement(&gErrorCount);
166 printf(
"%s: error count: %" PRId32
"\n", __func__, gErrorCount);
167 printf(
"%s: thread count: %" PRId32
" (expected %" PRIu32
")\n", __func__, p.threadCount,
169 printf(
"%s: true count: %" PRId32
" (expected %" PRIu32
")\n", __func__, p.trueCount,
171 printf(
"%s: false count: %" PRId32
" (expected %" PRIu32
")\n", __func__, p.falseCount,
176 free((
void*)threads);
177 DeleteSynchronizationBarrier(&gBarrier);
180 printf(
"%s: Error test failed with %" PRId32
" reported errors\n", __func__, gErrorCount);
187 int TestSynchBarrier(
int argc,
char* argv[])
190 DWORD dwMaxThreads = 0;
191 DWORD dwMinThreads = 0;
192 DWORD dwNumLoops = 10;
197 GetNativeSystemInfo(&sysinfo);
198 printf(
"%s: Number of processors: %" PRIu32
"\n", __func__, sysinfo.dwNumberOfProcessors);
199 dwMinThreads = sysinfo.dwNumberOfProcessors;
200 dwMaxThreads = sysinfo.dwNumberOfProcessors * 4;
202 if (dwMaxThreads > 32)
206 if (InitializeSynchronizationBarrier(&gBarrier, 0, -1))
210 "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = 0\n",
215 if (InitializeSynchronizationBarrier(&gBarrier, -1, -1))
219 "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = -1\n",
224 if (InitializeSynchronizationBarrier(&gBarrier, 1, -2))
228 "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lSpinCount = -2\n",
235 if (!TestSynchBarrierWithFlags(0, dwMaxThreads, dwNumLoops))
239 "%s: TestSynchBarrierWithFlags(0) unecpectedly succeeded with lTotalThreads = -1\n",
244 if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY, dwMinThreads,
247 (void)fprintf(stderr,
248 "%s: TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY) "
249 "unecpectedly succeeded with lTotalThreads = -1\n",
254 if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY, dwMaxThreads,
257 (void)fprintf(stderr,
258 "%s: TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY) "
259 "unecpectedly succeeded with lTotalThreads = -1\n",
264 printf(
"%s: Test successfully completed\n", __func__);