FreeRDP
Loading...
Searching...
No Matches
TestSynchMultipleThreads.c
1
2#include <stdlib.h>
3
4#include <winpr/crt.h>
5#include <winpr/crypto.h>
6#include <winpr/synch.h>
7#include <winpr/thread.h>
8
9#define THREADS 8
10
11static UINT32 prand(UINT32 max)
12{
13 UINT32 tmp = 0;
14 if (max <= 1)
15 return 1;
16 winpr_RAND(&tmp, sizeof(tmp));
17 return tmp % (max - 1) + 1;
18}
19
20static DWORD WINAPI test_thread(LPVOID arg)
21{
22 UINT32 timeout = 50 + prand(100);
23 WINPR_UNUSED(arg);
24 Sleep(timeout);
25 ExitThread(0);
26 return 0;
27}
28
29static int start_threads(size_t count, HANDLE* threads)
30{
31 for (size_t i = 0; i < count; i++)
32 {
33 threads[i] = CreateThread(NULL, 0, test_thread, NULL, CREATE_SUSPENDED, NULL);
34
35 if (!threads[i])
36 {
37 (void)fprintf(stderr, "%s: CreateThread [%" PRIuz "] failure\n", __func__, i);
38 return -1;
39 }
40 }
41
42 for (size_t i = 0; i < count; i++)
43 ResumeThread(threads[i]);
44 return 0;
45}
46
47static int close_threads(DWORD count, HANDLE* threads)
48{
49 int rc = 0;
50
51 for (DWORD i = 0; i < count; i++)
52 {
53 if (!threads[i])
54 continue;
55
56 if (!CloseHandle(threads[i]))
57 {
58 (void)fprintf(stderr, "%s: CloseHandle [%" PRIu32 "] failure\n", __func__, i);
59 rc = -1;
60 }
61 threads[i] = NULL;
62 }
63
64 return rc;
65}
66
67static BOOL TestWaitForAll(void)
68{
69 BOOL rc = FALSE;
70 HANDLE threads[THREADS] = { 0 };
71 /* WaitForAll, timeout */
72 if (start_threads(ARRAYSIZE(threads), threads))
73 {
74 (void)fprintf(stderr, "%s: start_threads failed\n", __func__);
75 goto fail;
76 }
77
78 const DWORD ret = WaitForMultipleObjects(ARRAYSIZE(threads), threads, TRUE, 10);
79 if (ret != WAIT_TIMEOUT)
80 {
81 (void)fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, timeout 10 failed, ret=%d\n",
82 __func__, ret);
83 goto fail;
84 }
85
86 if (WaitForMultipleObjects(ARRAYSIZE(threads), threads, TRUE, INFINITE) != WAIT_OBJECT_0)
87 {
88 (void)fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, INFINITE failed\n", __func__);
89 goto fail;
90 }
91
92 rc = TRUE;
93fail:
94 if (close_threads(ARRAYSIZE(threads), threads))
95 {
96 (void)fprintf(stderr, "%s: close_threads failed\n", __func__);
97 return FALSE;
98 }
99
100 return rc;
101}
102
103static BOOL TestWaitOne(void)
104{
105 BOOL rc = FALSE;
106 HANDLE threads[THREADS] = { 0 };
107 /* WaitForAll, timeout */
108 if (start_threads(ARRAYSIZE(threads), threads))
109 {
110 (void)fprintf(stderr, "%s: start_threads failed\n", __func__);
111 goto fail;
112 }
113
114 const DWORD ret = WaitForMultipleObjects(ARRAYSIZE(threads), threads, FALSE, INFINITE);
115 if (ret > (WAIT_OBJECT_0 + ARRAYSIZE(threads)))
116 {
117 (void)fprintf(stderr, "%s: WaitForMultipleObjects INFINITE failed\n", __func__);
118 goto fail;
119 }
120
121 if (WaitForMultipleObjects(ARRAYSIZE(threads), threads, TRUE, INFINITE) != WAIT_OBJECT_0)
122 {
123 (void)fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, INFINITE failed\n", __func__);
124 goto fail;
125 }
126
127 rc = TRUE;
128fail:
129 if (close_threads(ARRAYSIZE(threads), threads))
130 {
131 (void)fprintf(stderr, "%s: close_threads failed\n", __func__);
132 return FALSE;
133 }
134
135 return rc;
136}
137
138static BOOL TestWaitOneTimeout(void)
139{
140 BOOL rc = FALSE;
141 HANDLE threads[THREADS] = { 0 };
142 /* WaitForAll, timeout */
143 if (start_threads(ARRAYSIZE(threads), threads))
144 {
145 (void)fprintf(stderr, "%s: start_threads failed\n", __func__);
146 goto fail;
147 }
148
149 const DWORD ret = WaitForMultipleObjects(ARRAYSIZE(threads), threads, FALSE, 1);
150 if (ret != WAIT_TIMEOUT)
151 {
152 (void)fprintf(stderr, "%s: WaitForMultipleObjects timeout 50 failed, ret=%d\n", __func__,
153 ret);
154 goto fail;
155 }
156
157 if (WaitForMultipleObjects(ARRAYSIZE(threads), threads, TRUE, INFINITE) != WAIT_OBJECT_0)
158 {
159 (void)fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, INFINITE failed\n", __func__);
160 goto fail;
161 }
162 rc = TRUE;
163fail:
164 if (close_threads(ARRAYSIZE(threads), threads))
165 {
166 (void)fprintf(stderr, "%s: close_threads failed\n", __func__);
167 return FALSE;
168 }
169
170 return rc;
171}
172
173static BOOL TestWaitOneTimeoutMultijoin(void)
174{
175 BOOL rc = FALSE;
176 HANDLE threads[THREADS] = { 0 };
177 /* WaitForAll, timeout */
178 if (start_threads(ARRAYSIZE(threads), threads))
179 {
180 (void)fprintf(stderr, "%s: start_threads failed\n", __func__);
181 goto fail;
182 }
183
184 for (size_t i = 0; i < ARRAYSIZE(threads); i++)
185 {
186 const DWORD ret = WaitForMultipleObjects(ARRAYSIZE(threads), threads, FALSE, 0);
187 if (ret != WAIT_TIMEOUT)
188 {
189 (void)fprintf(stderr, "%s: WaitForMultipleObjects timeout 0 failed, ret=%d\n", __func__,
190 ret);
191 goto fail;
192 }
193 }
194
195 if (WaitForMultipleObjects(ARRAYSIZE(threads), threads, TRUE, INFINITE) != WAIT_OBJECT_0)
196 {
197 (void)fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, INFINITE failed\n", __func__);
198 goto fail;
199 }
200
201 rc = TRUE;
202fail:
203 if (close_threads(ARRAYSIZE(threads), threads))
204 {
205 (void)fprintf(stderr, "%s: close_threads failed\n", __func__);
206 return FALSE;
207 }
208
209 return rc;
210}
211
212static BOOL TestDetach(void)
213{
214 BOOL rc = FALSE;
215 HANDLE threads[THREADS] = { 0 };
216 /* WaitForAll, timeout */
217 if (start_threads(ARRAYSIZE(threads), threads))
218 {
219 (void)fprintf(stderr, "%s: start_threads failed\n", __func__);
220 goto fail;
221 }
222
223 rc = TRUE;
224fail:
225 if (close_threads(ARRAYSIZE(threads), threads))
226 {
227 (void)fprintf(stderr, "%s: close_threads failed\n", __func__);
228 return FALSE;
229 }
230
231 return rc;
232}
233
234int TestSynchMultipleThreads(int argc, char* argv[])
235{
236 WINPR_UNUSED(argc);
237 WINPR_UNUSED(argv);
238
239 if (!TestWaitForAll())
240 return -1;
241
242 if (!TestWaitOne())
243 return -2;
244
245 if (!TestWaitOneTimeout())
246 return -3;
247
248 if (!TestWaitOneTimeoutMultijoin())
249 return -4;
250
251 if (!TestDetach())
252 return -5;
253
254 return 0;
255}