1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*============================================================ |
6 | ** |
7 | ** Source: test6.c |
8 | ** |
9 | ** Purpose: Test for WaitForMultipleObjectsEx in multiple |
10 | ** scenarios |
11 | ** |
12 | ** |
13 | **=========================================================*/ |
14 | |
15 | #include <palsuite.h> |
16 | |
17 | #define MAX_COUNT 10000 |
18 | #define MAX_THREADS 256 |
19 | |
20 | BOOL g_bMutex = 0; |
21 | BOOL g_bEvent = 0; |
22 | BOOL g_bNamedEvent = 0; |
23 | BOOL g_bSemaphore = 0; |
24 | BOOL g_bProcess = 0; |
25 | BOOL g_bLocalWaitAll = 0; |
26 | BOOL g_bRemoteWaitAll = 0; |
27 | BOOL g_bRandom = 0; |
28 | |
29 | int iCount = 1; |
30 | int iThreads = 1; |
31 | HANDLE hThreads[MAX_THREADS]; |
32 | |
33 | #ifndef MIN |
34 | #define MIN(a,b) (((a)<(b)) ? (a) : (b)) |
35 | #endif |
36 | |
37 | DWORD PALAPI EventTestThread(PVOID pArg) |
38 | { |
39 | BOOL bRet; |
40 | DWORD dwRet; |
41 | HANDLE hEvent[2]; |
42 | HANDLE (*prgHandles)[] = (HANDLE (*)[])pArg; |
43 | |
44 | Trace("[EventTestThread] Starting\n" ); |
45 | |
46 | bRet = DuplicateHandle(GetCurrentProcess(), (*prgHandles)[0], GetCurrentProcess(), |
47 | &hEvent[0], 0, FALSE, DUPLICATE_SAME_ACCESS); |
48 | bRet &= DuplicateHandle(GetCurrentProcess(), (*prgHandles)[1], GetCurrentProcess(), |
49 | &hEvent[1], 0, FALSE, DUPLICATE_SAME_ACCESS); |
50 | if (FALSE == bRet) |
51 | { |
52 | Fail("[EventTestThread] Failed to duplicate handles\n" ); |
53 | } |
54 | |
55 | Sleep(1000); |
56 | bRet = SetEvent(hEvent[1]); |
57 | if (FALSE == bRet) |
58 | { |
59 | Fail("SetEvent failed\n" ); |
60 | Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n" , |
61 | GetLastError()); |
62 | } |
63 | |
64 | dwRet = WaitForSingleObject(hEvent[1], INFINITE); |
65 | if (WAIT_FAILED == dwRet) |
66 | { |
67 | Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
68 | GetLastError()); |
69 | } |
70 | |
71 | Sleep(1000); |
72 | bRet = SetEvent(hEvent[0]); |
73 | if (FALSE == bRet) |
74 | { |
75 | Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n" , |
76 | GetLastError()); |
77 | } |
78 | |
79 | Sleep(1000); |
80 | bRet = SetEvent(hEvent[1]); |
81 | if (FALSE == bRet) |
82 | { |
83 | Fail("[EventTestThread] SetEvent failed [GetLastError()=%u]\n" , |
84 | GetLastError()); |
85 | } |
86 | |
87 | CloseHandle(hEvent[0]); |
88 | CloseHandle(hEvent[1]); |
89 | |
90 | Trace("[EventTestThread] Done\n" ); |
91 | return 0; |
92 | } |
93 | |
94 | DWORD PALAPI MutexTestThread(PVOID pArg) |
95 | { |
96 | BOOL bRet; |
97 | DWORD dwRet; |
98 | HANDLE hMutex; |
99 | |
100 | Trace("[MutexTestThread] Starting\n" ); |
101 | |
102 | bRet = DuplicateHandle(GetCurrentProcess(), (HANDLE)pArg, GetCurrentProcess(), &hMutex, |
103 | 0, FALSE, DUPLICATE_SAME_ACCESS); |
104 | if (FALSE == bRet) |
105 | { |
106 | Fail("[EventTestThread] DuplicateHandle failed [GetLastError()=%u]\n" , |
107 | GetLastError()); |
108 | } |
109 | |
110 | dwRet = WaitForSingleObject(hMutex, INFINITE); |
111 | if (WAIT_FAILED == dwRet) |
112 | { |
113 | Fail("[EventTestThread] WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
114 | GetLastError()); |
115 | } |
116 | |
117 | Sleep(1000); |
118 | CloseHandle(hMutex); |
119 | |
120 | Trace("[MutexTestThread] Done\n" ); |
121 | |
122 | return 0; |
123 | } |
124 | |
125 | DWORD PALAPI TestThread(PVOID pArg) |
126 | { |
127 | BOOL bRet; |
128 | DWORD dwRet; |
129 | PROCESS_INFORMATION pi; |
130 | STARTUPINFO si; |
131 | HANDLE hNamedEvent; |
132 | HANDLE hEvent[2] = { 0, 0 }; |
133 | HANDLE hMutex = 0; |
134 | HANDLE hSemaphore = 0; |
135 | HANDLE hObjs[2]; |
136 | DWORD dwThreadNum; |
137 | DWORD dwSlaveThreadTid = 0; |
138 | HANDLE hThread; |
139 | int i, iCnt, iRet; |
140 | char szTestName[128]; |
141 | char szCmd[128]; |
142 | char szEventName[128] = { 0 }; |
143 | char szMutexName[128] = { 0 }; |
144 | char szSemName[128] = { 0 }; |
145 | WCHAR wszEventName[128] = { 0 }; |
146 | WCHAR wszMutexName[128] = { 0 }; |
147 | WCHAR wszSemName[128] = { 0 }; |
148 | BOOL bMutex = g_bMutex; |
149 | BOOL bEvent = g_bEvent; |
150 | BOOL bNamedEvent = g_bNamedEvent; |
151 | BOOL bSemaphore = g_bSemaphore; |
152 | BOOL bProcess = g_bProcess; |
153 | BOOL bLocalWaitAll = g_bLocalWaitAll; |
154 | BOOL bRemoteWaitAll = g_bRemoteWaitAll; |
155 | int iDesiredExitCode; |
156 | |
157 | dwThreadNum = (DWORD)pArg; |
158 | |
159 | sprintf_s (szTestName, 128, "Test6_%u" , dwThreadNum); |
160 | szTestName[127] = 0; |
161 | |
162 | sprintf_s(szEventName, 128, "%s_Event" , szTestName); |
163 | szEventName[127] = 0; |
164 | sprintf_s(szMutexName, 128, "%s_Mutex" , szTestName); |
165 | szMutexName[127] = 0; |
166 | sprintf_s(szSemName, 128, "%s_Semaphore" , szTestName); |
167 | szSemName[127] = 0; |
168 | |
169 | iRet = MultiByteToWideChar(CP_ACP, 0, szEventName, strlen(szEventName)+1, wszEventName, 128); |
170 | iRet &= MultiByteToWideChar(CP_ACP, 0, szMutexName, strlen(szMutexName)+1, wszMutexName, 128); |
171 | iRet &= MultiByteToWideChar(CP_ACP, 0, szSemName, strlen(szSemName)+1, wszSemName, 128); |
172 | |
173 | if (0 == iRet) |
174 | { |
175 | Fail("[TestThread] Failed to convert strings\n" ); |
176 | } |
177 | |
178 | Trace("[TestThread] TestName=%s Event: %S, Mutex: %S, Semaphore = %S\n" , |
179 | szTestName, wszEventName, wszMutexName, wszSemName); |
180 | |
181 | hEvent[0] = CreateEventA(NULL, FALSE, FALSE, NULL); |
182 | hEvent[1] = CreateEventA(NULL, FALSE, FALSE, NULL); |
183 | |
184 | hNamedEvent = CreateEventW(NULL, FALSE, FALSE, wszEventName); |
185 | hMutex = CreateMutexW(NULL, FALSE, wszMutexName); |
186 | hSemaphore = CreateSemaphoreW(NULL, 0, 256, wszSemName); |
187 | |
188 | if (NULL == hEvent[0] || NULL == hEvent[1] || NULL == hMutex || |
189 | NULL == hNamedEvent || NULL == hSemaphore) |
190 | { |
191 | Fail("[TestThread] Failed to create objects " |
192 | "[hNamedEvent=%p hMutex=%p hSemaphore=%p]\n" , |
193 | (VOID*)hNamedEvent, (VOID*)hMutex, (VOID*)hSemaphore); |
194 | } |
195 | |
196 | for (iCnt=0; iCnt<iCount; iCnt++) |
197 | { |
198 | if (g_bRandom) |
199 | { |
200 | int iRnd; |
201 | |
202 | bMutex = 0; |
203 | bEvent = 0; |
204 | bNamedEvent = 0; |
205 | bSemaphore = 0; |
206 | bProcess = 0; |
207 | bLocalWaitAll = 0; |
208 | bRemoteWaitAll = 0; |
209 | |
210 | iRnd = rand() % 7; |
211 | switch(iRnd) |
212 | { |
213 | case 0: |
214 | bMutex = 1; |
215 | break; |
216 | case 1: |
217 | bEvent = 1; |
218 | break; |
219 | case 2: |
220 | bNamedEvent = 1; |
221 | break; |
222 | case 3: |
223 | bSemaphore = 1; |
224 | break; |
225 | case 4: |
226 | bProcess = 1; |
227 | break; |
228 | case 5: |
229 | bLocalWaitAll = 1; |
230 | break; |
231 | case 6: |
232 | bRemoteWaitAll = 1; |
233 | break; |
234 | } |
235 | } |
236 | |
237 | if (bEvent) |
238 | { |
239 | Trace("======================================================================\n" ); |
240 | Trace("Local unnamed event test\n" ); |
241 | Trace("----------------------------------------\n" ); |
242 | hThread = CreateThread(NULL, 0, EventTestThread, (PVOID)hEvent, 0, &dwSlaveThreadTid); |
243 | if (NULL == hThread) |
244 | { |
245 | Fail("Failed to create thread\n" ); |
246 | } |
247 | |
248 | hObjs[0] = hEvent[0]; |
249 | dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE); |
250 | if (WAIT_FAILED == dwRet) |
251 | { |
252 | Fail("WaitForMultipleObjects failed\n" ); |
253 | } |
254 | |
255 | hObjs[0] = hThread; |
256 | dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE); |
257 | if (WAIT_FAILED == dwRet) |
258 | { |
259 | Fail("WaitForMultipleObjects failed\n" ); |
260 | } |
261 | |
262 | CloseHandle(hThread); |
263 | Trace("Local unnamed event test done \n" ); |
264 | Trace("======================================================================\n" ); |
265 | } |
266 | |
267 | if (bMutex) |
268 | { |
269 | Trace("======================================================================\n" ); |
270 | Trace("Mutex with remote thread awakening test\n" ); |
271 | Trace("----------------------------------------\n" ); |
272 | |
273 | hThread = CreateThread(NULL, 0, MutexTestThread, (PVOID)hMutex, 0, &dwSlaveThreadTid); |
274 | if (NULL == hThread) |
275 | { |
276 | Fail("Failed to create thread\n" ); |
277 | } |
278 | |
279 | Sleep(1000); |
280 | |
281 | hObjs[0] = hMutex; |
282 | |
283 | for (i=0;i<10;i++) |
284 | { |
285 | dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE); |
286 | if (WAIT_FAILED == dwRet) |
287 | { |
288 | Fail("WaitForMultipleObjects failed [dwRet=%x GetLastError()=%d\n" , |
289 | dwRet, GetLastError()); |
290 | } |
291 | } |
292 | |
293 | hObjs[0] = hThread; |
294 | dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE); |
295 | if (WAIT_FAILED == dwRet) |
296 | { |
297 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
298 | GetLastError()); |
299 | } |
300 | |
301 | for (i=0;i<10;i++) |
302 | { |
303 | bRet = ReleaseMutex(hMutex); |
304 | if (FALSE == bRet) |
305 | { |
306 | Fail("ReleaseMutex failed [GetLastError()=%u]\n" , |
307 | GetLastError()); |
308 | } |
309 | } |
310 | |
311 | CloseHandle(hThread); |
312 | Trace("Mutex with remote thread awakening test done\n" ); |
313 | Trace("======================================================================\n" ); |
314 | } |
315 | |
316 | if (bNamedEvent) |
317 | { |
318 | Trace("======================================================================\n" ); |
319 | Trace("Named event with remote thread awakening test\n" ); |
320 | Trace("----------------------------------------\n" ); |
321 | |
322 | ZeroMemory ( &si, sizeof(si) ); |
323 | si.cb = sizeof(si); |
324 | ZeroMemory ( &pi, sizeof(pi) ); |
325 | |
326 | sprintf_s (szCmd, 128, "child6 -event %s" , szTestName); |
327 | szCmd[127] = 0; |
328 | |
329 | bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); |
330 | if (FALSE == bRet) |
331 | { |
332 | Fail("CreateProcess failed [GetLastError()=%u]\n" , |
333 | GetLastError()); |
334 | } |
335 | |
336 | hObjs[0] = pi.hProcess; |
337 | hObjs[1] = hNamedEvent; |
338 | |
339 | dwRet = WaitForMultipleObjects(2, hObjs, FALSE, INFINITE); |
340 | if (1 != dwRet) |
341 | { |
342 | Fail("WaitForMultipleObjects failed [dwRet=%u GetLastError()=%u]\n" , |
343 | dwRet, GetLastError()); |
344 | } |
345 | |
346 | dwRet = WaitForSingleObject(pi.hProcess, INFINITE); |
347 | if (WAIT_FAILED == dwRet) |
348 | { |
349 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
350 | GetLastError()); |
351 | } |
352 | Trace("Named event with remote thread awakening test done\n" ); |
353 | Trace("======================================================================\n" ); |
354 | } |
355 | |
356 | if (bSemaphore) |
357 | { |
358 | Trace("======================================================================\n" ); |
359 | Trace("Semaphore with remote thread awakening test\n" ); |
360 | Trace("----------------------------------------\n" ); |
361 | |
362 | ZeroMemory ( &si, sizeof(si) ); |
363 | si.cb = sizeof(si); |
364 | ZeroMemory ( &pi, sizeof(pi) ); |
365 | |
366 | sprintf_s (szCmd, 128, "child6 -semaphore %s" , szTestName); |
367 | szCmd[127] = 0; |
368 | |
369 | bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, |
370 | 0, NULL, NULL, &si, &pi); |
371 | if (FALSE == bRet) |
372 | { |
373 | Fail("CreateProcessA failed [GetLastError()=%u]\n" , |
374 | GetLastError()); |
375 | } |
376 | |
377 | Trace("Setting event %s\n" , szEventName); |
378 | bRet = SetEvent(hNamedEvent); |
379 | if (FALSE == bRet) |
380 | { |
381 | Fail("[child] SetEvent failed [GetLastError()=%u]\n" , |
382 | GetLastError()); |
383 | } |
384 | |
385 | Trace("Going to wait on semaphore %s\n" , szSemName); |
386 | |
387 | |
388 | hObjs[0] = pi.hProcess; |
389 | hObjs[0] = hEvent[0]; |
390 | hObjs[1] = hSemaphore; |
391 | for (i=0;i<10;i++) |
392 | { |
393 | dwRet = WaitForMultipleObjects(2, hObjs, FALSE, INFINITE); |
394 | if (1 != dwRet) |
395 | { |
396 | Trace("WaitForMultipleObjects failed [tid=%u dwRet=%u GetLastError()=%u]\n" , |
397 | GetCurrentThreadId(), dwRet, GetLastError()); |
398 | DebugBreak(); |
399 | } |
400 | } |
401 | |
402 | dwRet = WaitForSingleObject(pi.hProcess, INFINITE); |
403 | if (WAIT_FAILED == dwRet) |
404 | { |
405 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
406 | GetLastError()); |
407 | } |
408 | Trace("Semaphore with remote thread awakening test done\n" ); |
409 | Trace("======================================================================\n" ); |
410 | } |
411 | |
412 | if (bProcess) |
413 | { |
414 | DWORD dwExitCode; |
415 | |
416 | Trace("======================================================================\n" ); |
417 | Trace("Process wait test\n" ); |
418 | Trace("----------------------------------------\n" ); |
419 | |
420 | iDesiredExitCode = rand() % 0xFF; |
421 | |
422 | ZeroMemory ( &si, sizeof(si) ); |
423 | si.cb = sizeof(si); |
424 | ZeroMemory ( &pi, sizeof(pi) ); |
425 | |
426 | sprintf_s (szCmd, 128, "child6 -mutex %s -exitcode %d" , szTestName, iDesiredExitCode); |
427 | szCmd[127] = 0; |
428 | |
429 | bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); |
430 | if (FALSE == bRet) |
431 | { |
432 | Fail("CreateProcess failed [GetLastError()=%u]\n" , |
433 | GetLastError()); |
434 | } |
435 | |
436 | Trace("Going to wait on event %s\n" , szEventName); |
437 | dwRet = WaitForSingleObject(hNamedEvent, INFINITE); |
438 | if (WAIT_FAILED == dwRet) |
439 | { |
440 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
441 | GetLastError()); |
442 | } |
443 | |
444 | hObjs[0] = hEvent[0]; // dummy, this is a local event |
445 | hObjs[1] = hMutex; |
446 | |
447 | dwRet = WaitForMultipleObjects(2, hObjs, FALSE, INFINITE); |
448 | if (WAIT_FAILED == dwRet) |
449 | { |
450 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
451 | GetLastError()); |
452 | } |
453 | if (1 == dwRet || (1 + WAIT_ABANDONED_0) == dwRet) |
454 | { |
455 | bRet = ReleaseMutex(hMutex); |
456 | if (FALSE == bRet) |
457 | { |
458 | Fail("ReleaseMutex failed [GetLastError()=%u]\n" , |
459 | GetLastError()); |
460 | } |
461 | } |
462 | |
463 | dwRet = WaitForSingleObject(pi.hProcess, INFINITE); |
464 | if (WAIT_FAILED == dwRet) |
465 | { |
466 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
467 | GetLastError()); |
468 | } |
469 | |
470 | if (!GetExitCodeProcess(pi.hProcess, &dwExitCode)) |
471 | { |
472 | Trace("GetExitCodeProcess call failed LastError:(%u)\n" , |
473 | GetLastError()); |
474 | dwExitCode = FAIL; |
475 | } |
476 | |
477 | if (iDesiredExitCode != dwExitCode) |
478 | { |
479 | Fail("Wrong return code: %u [%d]\n" , dwExitCode, iDesiredExitCode); |
480 | } |
481 | CloseHandle(pi.hProcess); |
482 | CloseHandle(pi.hThread); |
483 | Trace("Process wait test done\n" ); |
484 | Trace("======================================================================\n" ); |
485 | } |
486 | |
487 | if (bLocalWaitAll) |
488 | { |
489 | Trace("======================================================================\n" ); |
490 | Trace("WaitAll with local thread awakening test\n" ); |
491 | Trace("----------------------------------------\n" ); |
492 | |
493 | hThread = CreateThread(NULL, 0, EventTestThread, (PVOID)hEvent, 0, &dwSlaveThreadTid); |
494 | if (NULL == hThread) |
495 | { |
496 | Fail("CreateThread failed [GetLastError()=%u]\n" , |
497 | GetLastError()); |
498 | } |
499 | |
500 | dwRet = WaitForMultipleObjects(2, hEvent, TRUE, INFINITE); |
501 | if (WAIT_FAILED == dwRet) |
502 | { |
503 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
504 | GetLastError()); |
505 | } |
506 | |
507 | hObjs[0] = hThread; |
508 | dwRet = WaitForMultipleObjects(1, hObjs, FALSE, INFINITE); |
509 | if (WAIT_FAILED == dwRet) |
510 | { |
511 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
512 | GetLastError()); |
513 | } |
514 | |
515 | CloseHandle(hThread); |
516 | Trace("WaitAll with local thread awakening test done\n" ); |
517 | Trace("======================================================================\n" ); |
518 | } |
519 | |
520 | if (bRemoteWaitAll) |
521 | { |
522 | Trace("======================================================================\n" ); |
523 | Trace("WaitAll with remote thread awakening test\n" ); |
524 | Trace("----------------------------------------\n" ); |
525 | |
526 | ZeroMemory ( &si, sizeof(si) ); |
527 | si.cb = sizeof(si); |
528 | ZeroMemory ( &pi, sizeof(pi) ); |
529 | |
530 | sprintf_s (szCmd, 128, "child6 -mutex_and_named_event %s" , szTestName); |
531 | szCmd[127] = 0; |
532 | |
533 | bRet = CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, |
534 | 0, NULL, NULL, &si, &pi); |
535 | if (FALSE == bRet) |
536 | { |
537 | Fail("CreateProcess failed [GetLastError()=%u]\n" , |
538 | GetLastError()); |
539 | } |
540 | |
541 | Sleep(1000); |
542 | |
543 | hObjs[0] = hMutex; |
544 | hObjs[1] = hNamedEvent; |
545 | |
546 | dwRet = WaitForMultipleObjects(2, hObjs, TRUE, INFINITE); |
547 | if (WAIT_FAILED == dwRet) |
548 | { |
549 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
550 | GetLastError()); |
551 | } |
552 | |
553 | bRet = ReleaseMutex(hMutex); |
554 | if (FALSE == bRet) |
555 | { |
556 | Fail("ReleaseMutex failed [GetLastError()=%u]\n" , |
557 | GetLastError()); |
558 | } |
559 | |
560 | dwRet = WaitForSingleObject(pi.hProcess, INFINITE); |
561 | if (WAIT_FAILED == dwRet) |
562 | { |
563 | Fail("WaitForMultipleObjects failed [GetLastError()=%u]\n" , |
564 | GetLastError()); |
565 | } |
566 | |
567 | CloseHandle(pi.hProcess); |
568 | CloseHandle(pi.hThread); |
569 | Trace("WaitAll with remote thread awakening test done\n" ); |
570 | Trace("======================================================================\n" ); |
571 | } |
572 | } |
573 | |
574 | return 0; |
575 | } |
576 | |
577 | int __cdecl main(int argc, char **argv) |
578 | { |
579 | DWORD dwRet; |
580 | DWORD dwSlaveThreadTid = 0; |
581 | int i, iCnt; |
582 | |
583 | if(0 != (PAL_Initialize(argc, argv))) |
584 | { |
585 | return ( FAIL ); |
586 | } |
587 | |
588 | srand(time(NULL) * GetCurrentProcessId()); |
589 | |
590 | if (argc == 1) |
591 | { |
592 | g_bMutex = 1; |
593 | g_bEvent = 1; |
594 | g_bNamedEvent = 1; |
595 | g_bSemaphore = 1; |
596 | g_bProcess = 1; |
597 | g_bLocalWaitAll = 1; |
598 | g_bRemoteWaitAll = 1; |
599 | } |
600 | else |
601 | { |
602 | for (i=1;i<argc;i++) |
603 | { |
604 | if (0 == strcmp(argv[i], "-mutex" )) |
605 | { |
606 | g_bMutex = 1; |
607 | } |
608 | else if (0 == strcmp(argv[i], "-event" )) |
609 | { |
610 | g_bEvent = 1; |
611 | } |
612 | else if (0 == strcmp(argv[i], "-namedevent" )) |
613 | { |
614 | g_bNamedEvent = 1; |
615 | } |
616 | else if (0 == strcmp(argv[i], "-semaphore" )) |
617 | { |
618 | g_bSemaphore = 1; |
619 | } |
620 | else if (0 == strcmp(argv[i], "-process" )) |
621 | { |
622 | g_bProcess = 1; |
623 | } |
624 | else if (0 == strcmp(argv[i], "-localwaitall" )) |
625 | { |
626 | g_bLocalWaitAll = 1; |
627 | } |
628 | else if (0 == strcmp(argv[i], "-remotewaitall" )) |
629 | { |
630 | g_bRemoteWaitAll = 1; |
631 | } |
632 | else if (0 == strcmp(argv[i], "-all" )) |
633 | { |
634 | g_bMutex = 1; |
635 | g_bEvent = 1; |
636 | g_bNamedEvent = 1; |
637 | g_bSemaphore = 1; |
638 | g_bProcess = 1; |
639 | g_bLocalWaitAll = 1; |
640 | g_bRemoteWaitAll = 1; |
641 | } |
642 | else if (0 == strcmp(argv[i], "-random" )) |
643 | { |
644 | g_bRandom = 1; |
645 | } |
646 | else if ((0 == strcmp(argv[i], "-count" )) && (argc > i+1)) |
647 | { |
648 | i++; |
649 | iCnt = atoi(argv[i]); |
650 | if (iCnt > 0 && iCnt < MAX_COUNT) |
651 | { |
652 | iCount = iCnt; |
653 | } |
654 | } |
655 | else if ((0 == strcmp(argv[i], "-threads" )) && (argc > i+1)) |
656 | { |
657 | i++; |
658 | iCnt = atoi(argv[i]); |
659 | if (iCnt > 0 && iCnt <= MAX_THREADS) |
660 | { |
661 | iThreads = iCnt; |
662 | } |
663 | } |
664 | else |
665 | { |
666 | Trace("Unknown option %s ignored\n" , argv[i]); |
667 | } |
668 | } |
669 | } |
670 | |
671 | |
672 | iCnt = 0; |
673 | for (i=0;i<iThreads;i++) |
674 | { |
675 | hThreads[iCnt] = CreateThread(NULL, 0, TestThread, (VOID*)iCnt, 0, &dwSlaveThreadTid); |
676 | if (NULL == hThreads[iCnt]) |
677 | { |
678 | Trace("Failed to create thread\n" ); |
679 | } |
680 | else |
681 | { |
682 | iCnt++; |
683 | } |
684 | } |
685 | |
686 | if (0 == iCnt) |
687 | { |
688 | Fail("Can't create any thread\n" ); |
689 | } |
690 | |
691 | for (i=0; i<iCnt; i+=64) |
692 | { |
693 | dwRet = WaitForMultipleObjects(MIN(64, iCnt-i), &hThreads[i], TRUE, INFINITE); |
694 | if (WAIT_FAILED == dwRet) |
695 | { |
696 | Fail("WaitForMultipleObjects failed [dwRet=%u GetLastError()=%u iCnt=%d i=%d]\n" , |
697 | dwRet, GetLastError(), iCnt, i); |
698 | } |
699 | } |
700 | |
701 | |
702 | for (i=0; i<iCnt; i++) |
703 | { |
704 | CloseHandle(hThreads[i]); |
705 | } |
706 | |
707 | PAL_Terminate(); |
708 | return PASS; |
709 | } |
710 | |