TestSynchBarrier.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include <winpr/crt.h>
  2. #include <winpr/synch.h>
  3. #include <winpr/thread.h>
  4. #include <winpr/interlocked.h>
  5. #include <winpr/sysinfo.h>
  6. #include "../synch.h"
  7. static SYNCHRONIZATION_BARRIER gBarrier;
  8. static HANDLE gStartEvent = NULL;
  9. static LONG gErrorCount = 0;
  10. #define MAX_SLEEP_MS 32
  11. struct test_params
  12. {
  13. LONG threadCount;
  14. LONG trueCount;
  15. LONG falseCount;
  16. DWORD loops;
  17. DWORD flags;
  18. };
  19. static DWORD WINAPI test_synch_barrier_thread(LPVOID lpParam)
  20. {
  21. BOOL status = FALSE;
  22. struct test_params* p = (struct test_params*)lpParam;
  23. DWORD i;
  24. const ULONG currentNum = p->threadCount + 1;
  25. InterlockedIncrement(&p->threadCount);
  26. printf("Thread #%03u entered.\n", currentNum);
  27. /* wait for start event from main */
  28. if (WaitForSingleObject(gStartEvent, INFINITE) != WAIT_OBJECT_0)
  29. {
  30. InterlockedIncrement(&gErrorCount);
  31. goto out;
  32. }
  33. printf("Thread #%03u unblocked.\n", currentNum);
  34. for (i = 0; i < p->loops && gErrorCount == 0; i++)
  35. {
  36. /* simulate different execution times before the barrier */
  37. Sleep(rand() % MAX_SLEEP_MS);
  38. status = EnterSynchronizationBarrier(&gBarrier, p->flags);
  39. printf("Thread #%03u status: %s\n", currentNum, status ? "TRUE" : "FALSE");
  40. if (status)
  41. InterlockedIncrement(&p->trueCount);
  42. else
  43. InterlockedIncrement(&p->falseCount);
  44. }
  45. out:
  46. printf("Thread #%03u leaving.\n", currentNum);
  47. return 0;
  48. }
  49. static BOOL TestSynchBarrierWithFlags(DWORD dwFlags, DWORD dwThreads, DWORD dwLoops)
  50. {
  51. HANDLE* threads;
  52. struct test_params p;
  53. DWORD dwStatus, expectedTrueCount, expectedFalseCount;
  54. DWORD i;
  55. p.threadCount = 0;
  56. p.trueCount = 0;
  57. p.falseCount = 0;
  58. p.loops = dwLoops;
  59. p.flags = dwFlags;
  60. expectedTrueCount = dwLoops;
  61. expectedFalseCount = dwLoops * (dwThreads - 1);
  62. printf("%s: >> Testing with flags 0x%08" PRIx32 ". Using %" PRIu32
  63. " threads performing %" PRIu32 " loops\n",
  64. __FUNCTION__, dwFlags, dwThreads, dwLoops);
  65. if (!(threads = calloc(dwThreads, sizeof(HANDLE))))
  66. {
  67. printf("%s: error allocatin thread array memory\n", __FUNCTION__);
  68. return FALSE;
  69. }
  70. if (!InitializeSynchronizationBarrier(&gBarrier, dwThreads, -1))
  71. {
  72. printf("%s: InitializeSynchronizationBarrier failed. GetLastError() = 0x%08x", __FUNCTION__,
  73. GetLastError());
  74. free(threads);
  75. DeleteSynchronizationBarrier(&gBarrier);
  76. return FALSE;
  77. }
  78. if (!(gStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
  79. {
  80. printf("%s: CreateEvent failed with error 0x%08x", __FUNCTION__, GetLastError());
  81. free(threads);
  82. DeleteSynchronizationBarrier(&gBarrier);
  83. return FALSE;
  84. }
  85. for (i = 0; i < dwThreads; i++)
  86. {
  87. if (!(threads[i] = CreateThread(NULL, 0, test_synch_barrier_thread, &p, 0, NULL)))
  88. {
  89. printf("%s: CreateThread failed for thread #%" PRIu32 " with error 0x%08x\n",
  90. __FUNCTION__, i, GetLastError());
  91. InterlockedIncrement(&gErrorCount);
  92. break;
  93. }
  94. }
  95. if (i > 0)
  96. {
  97. if (!SetEvent(gStartEvent))
  98. {
  99. printf("%s: SetEvent(gStartEvent) failed with error = 0x%08x)\n", __FUNCTION__,
  100. GetLastError());
  101. InterlockedIncrement(&gErrorCount);
  102. }
  103. while (i--)
  104. {
  105. printf("%s: WaitForSingleObject(thread[%" PRIu32 "])...\n", __FUNCTION__, i);
  106. if (WAIT_OBJECT_0 != (dwStatus = WaitForSingleObject(threads[i], INFINITE)))
  107. {
  108. printf("%s: WaitForSingleObject(thread[%" PRIu32 "] unexpectedly returned %" PRIu32
  109. " (error = 0x%08x)\n",
  110. __FUNCTION__, i, dwStatus, GetLastError());
  111. InterlockedIncrement(&gErrorCount);
  112. }
  113. if (!CloseHandle(threads[i]))
  114. {
  115. printf("%s: CloseHandle(thread[%" PRIu32 "]) failed with error = 0x%08x)\n",
  116. __FUNCTION__, i, GetLastError());
  117. InterlockedIncrement(&gErrorCount);
  118. }
  119. }
  120. }
  121. free(threads);
  122. if (!CloseHandle(gStartEvent))
  123. {
  124. printf("%s: CloseHandle(gStartEvent) failed with error = 0x%08x)\n", __FUNCTION__,
  125. GetLastError());
  126. InterlockedIncrement(&gErrorCount);
  127. }
  128. DeleteSynchronizationBarrier(&gBarrier);
  129. if (p.threadCount != (INT64)dwThreads)
  130. InterlockedIncrement(&gErrorCount);
  131. if (p.trueCount != (INT64)expectedTrueCount)
  132. InterlockedIncrement(&gErrorCount);
  133. if (p.falseCount != (INT64)expectedFalseCount)
  134. InterlockedIncrement(&gErrorCount);
  135. printf("%s: error count: %" PRId32 "\n", __FUNCTION__, gErrorCount);
  136. printf("%s: thread count: %" PRId32 " (expected %" PRIu32 ")\n", __FUNCTION__, p.threadCount,
  137. dwThreads);
  138. printf("%s: true count: %" PRId32 " (expected %" PRIu32 ")\n", __FUNCTION__, p.trueCount,
  139. expectedTrueCount);
  140. printf("%s: false count: %" PRId32 " (expected %" PRIu32 ")\n", __FUNCTION__, p.falseCount,
  141. expectedFalseCount);
  142. if (gErrorCount > 0)
  143. {
  144. printf("%s: Error test failed with %" PRId32 " reported errors\n", __FUNCTION__,
  145. gErrorCount);
  146. return FALSE;
  147. }
  148. return TRUE;
  149. }
  150. int TestSynchBarrier(int argc, char* argv[])
  151. {
  152. SYSTEM_INFO sysinfo;
  153. DWORD dwMaxThreads;
  154. DWORD dwMinThreads;
  155. DWORD dwNumLoops = 200;
  156. GetNativeSystemInfo(&sysinfo);
  157. printf("%s: Number of processors: %" PRIu32 "\n", __FUNCTION__, sysinfo.dwNumberOfProcessors);
  158. dwMinThreads = sysinfo.dwNumberOfProcessors;
  159. dwMaxThreads = sysinfo.dwNumberOfProcessors * 4;
  160. if (dwMaxThreads > 32)
  161. dwMaxThreads = 32;
  162. /* Test invalid parameters */
  163. if (InitializeSynchronizationBarrier(&gBarrier, 0, -1))
  164. {
  165. printf(
  166. "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = 0\n",
  167. __FUNCTION__);
  168. return -1;
  169. }
  170. printf("%s: InitializeSynchronizationBarrier succeeded with lTotalThreads = 0\n",__FUNCTION__);
  171. if (InitializeSynchronizationBarrier(&gBarrier, -1, -1))
  172. {
  173. printf(
  174. "%s: InitializeSynchronizationBarrier unecpectedly succeeded with lTotalThreads = -1\n",
  175. __FUNCTION__);
  176. return -1;
  177. }
  178. printf("%s: InitializeSynchronizationBarrier succeeded with lTotalThreads = -1\n",__FUNCTION__);
  179. if (InitializeSynchronizationBarrier(&gBarrier, 1, -2))
  180. {
  181. printf("%s: InitializeSynchronizationBarrier unecpectedly succeeded with lSpinCount = -2\n",
  182. __FUNCTION__);
  183. return -1;
  184. }
  185. printf("%s: InitializeSynchronizationBarrier succeeded with lSpinCount = -2\n", __FUNCTION__);
  186. /* Functional tests */
  187. printf("%s: test TestSynchBarrierWithFlags\n", __FUNCTION__);
  188. if (!TestSynchBarrierWithFlags(0, dwMaxThreads, dwNumLoops))
  189. return -1;
  190. printf("%s: test TestSynchBarrierWithFlags with SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY\n", __FUNCTION__);
  191. if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY, dwMinThreads,
  192. dwNumLoops))
  193. return -1;
  194. printf("%s: test TestSynchBarrierWithFlags with SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY\n", __FUNCTION__);
  195. if (!TestSynchBarrierWithFlags(SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY, dwMaxThreads,
  196. dwNumLoops))
  197. return -1;
  198. printf("%s: Test successfully completed\n", __FUNCTION__);
  199. return 0;
  200. }