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: CriticalSectionFunctions/test3/test3.c |
8 | ** |
9 | ** Purpose: Create two threads to exercise TryEnterCriticalSection |
10 | ** and EnterCriticalSection. TryEnterCriticalSection acquires |
11 | ** and holds a CRITICAL_SECTION object. Another call to |
12 | ** TryEnterCriticalSection is made from a different thread, at |
13 | ** this time, to establish a call to TryEnterCriticalSection |
14 | ** will return immediatly and to establish |
15 | ** TryEnterCriticalSection returns the proper value when it |
16 | ** attempts to lock a CRITICAL_SECTION that is already owned |
17 | ** by another thread. The CRITICAL_SECTION object is then |
18 | ** released and held by a call to EnterCriticalSection. A new |
19 | ** thread is invoked and attempts to acquire the held |
20 | ** CRITICAL_SECTION with a call to TryEnterCriticalSection. |
21 | ** TryEnterCriticalSection returns immediatly and returns |
22 | ** with the value that states the CRITICAL_SECTION object is |
23 | ** held by another thread. This establishes |
24 | ** TryEnterCriticalSection behaves the same way with |
25 | ** CriticalSections locked by TryEnterCriticalSection and |
26 | ** EnterCriticalSection. |
27 | ** |
28 | ** |
29 | **===================================================================*/ |
30 | #include <palsuite.h> |
31 | |
32 | #define NUM_THREADS 2 |
33 | |
34 | HANDLE hThread[NUM_THREADS]; |
35 | HANDLE hEvent[NUM_THREADS]; |
36 | CRITICAL_SECTION CriticalSection; |
37 | BOOL bRet = FAIL; |
38 | |
39 | DWORD PALAPI Thread(LPVOID lpParam) |
40 | { |
41 | DWORD dwRet; |
42 | |
43 | if (0 == TryEnterCriticalSection(&CriticalSection)) |
44 | { |
45 | dwRet = WaitForMultipleObjects(NUM_THREADS, hEvent, TRUE, 10000); |
46 | if ((WAIT_OBJECT_0 > dwRet) || |
47 | ((WAIT_OBJECT_0 + NUM_THREADS - 1) < dwRet)) |
48 | { |
49 | #if 0 |
50 | if (0 == CloseHandle(hThread[1])) |
51 | { |
52 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
53 | "during clean up.\nGetLastError returned '%d'.\n" , |
54 | hThread[1], GetLastError()); |
55 | } |
56 | #endif |
57 | Trace("PALSUITE ERROR: WaitForMultipleObjects(%d, %p, %d, %d) call" |
58 | "returned an unexpected value, '%d'.\nGetLastError returned " |
59 | "%d.\n" , NUM_THREADS, hEvent, TRUE, 10000, dwRet, |
60 | GetLastError()); |
61 | } |
62 | else |
63 | { |
64 | bRet = PASS; |
65 | } |
66 | } |
67 | else |
68 | { |
69 | /* signal thread 0 */ |
70 | if (0 == SetEvent(hEvent[0])) |
71 | { |
72 | Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " |
73 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
74 | GetLastError()); |
75 | LeaveCriticalSection(&CriticalSection); |
76 | if (0 == CloseHandle(hThread[0])) |
77 | { |
78 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
79 | "during clean up\nGetLastError returned '%d'.\n" , |
80 | hThread[0], GetLastError()); |
81 | } |
82 | if (0 == CloseHandle(hEvent[0])) |
83 | { |
84 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
85 | "during clean up\nGetLastError returned '%d'.\n" , |
86 | hEvent[0], GetLastError()); |
87 | } |
88 | if (0 == CloseHandle(hEvent[1])) |
89 | { |
90 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
91 | "during clean up\nGetLastError returned '%d'.\n" , |
92 | hEvent[1], GetLastError()); |
93 | } |
94 | DeleteCriticalSection(&CriticalSection); |
95 | Fail("" ); |
96 | } |
97 | |
98 | /* wait to be signaled */ |
99 | dwRet = WaitForSingleObject(hEvent[1], 10000); |
100 | if (WAIT_OBJECT_0 != dwRet) |
101 | { |
102 | Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " |
103 | "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " |
104 | "('%d').\nGetLastError returned '%d'.\n" , |
105 | hEvent[0], 10000, WAIT_OBJECT_0, dwRet, GetLastError()); |
106 | if (0 == CloseHandle(hThread[0])) |
107 | { |
108 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
109 | "during clean up.\nGetLastError returned '%d'.\n" , |
110 | hThread[0], GetLastError()); |
111 | } |
112 | if (0 == CloseHandle(hEvent[0])) |
113 | { |
114 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
115 | "during clean up.\nGetLastError returned '%d'.\n" , |
116 | hEvent[0], GetLastError()); |
117 | } |
118 | if (0 == CloseHandle(hEvent[1])) |
119 | { |
120 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) " |
121 | "during clean up.\nGetLastError returned '%d.'\n" , |
122 | hEvent[1], GetLastError()); |
123 | } |
124 | DeleteCriticalSection(&CriticalSection); |
125 | Fail("" ); |
126 | } |
127 | LeaveCriticalSection(&CriticalSection); |
128 | } |
129 | return FAIL; |
130 | } |
131 | |
132 | int __cdecl main(int argc, char **argv) |
133 | { |
134 | HANDLE hThread[NUM_THREADS]; |
135 | DWORD dwThreadId[NUM_THREADS]; |
136 | DWORD dwRet; |
137 | |
138 | if ((PAL_Initialize(argc,argv)) != 0) |
139 | { |
140 | return(bRet); |
141 | } |
142 | |
143 | /* thread 0 event */ |
144 | hEvent[0] = CreateEvent(NULL, TRUE, FALSE, NULL); |
145 | |
146 | if (hEvent[0] == NULL) |
147 | { |
148 | Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " |
149 | "returned %d.\n" , GetLastError()); |
150 | } |
151 | |
152 | /* thread 1 event */ |
153 | hEvent[1] = CreateEvent(NULL, TRUE, FALSE, NULL); |
154 | |
155 | if (hEvent[1] == NULL) |
156 | { |
157 | Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " |
158 | "returned %d.\n" , GetLastError()); |
159 | if (0 == CloseHandle(hEvent[0])) |
160 | { |
161 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
162 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0]); |
163 | } |
164 | Fail("" ); |
165 | } |
166 | |
167 | InitializeCriticalSection ( &CriticalSection ); |
168 | |
169 | hThread[0] = CreateThread(NULL, |
170 | 0, |
171 | &Thread, |
172 | (LPVOID) NULL, |
173 | 0, |
174 | &dwThreadId[0]); |
175 | |
176 | if (hThread[0] == NULL) |
177 | { |
178 | Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " |
179 | "returned %d.\n" , GetLastError()); |
180 | if (0 == CloseHandle(hEvent[0])) |
181 | { |
182 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
183 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
184 | GetLastError()); |
185 | } |
186 | if (0 == CloseHandle(hEvent[1])) |
187 | { |
188 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
189 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[1], |
190 | GetLastError()); |
191 | } |
192 | DeleteCriticalSection(&CriticalSection); |
193 | Fail("" ); |
194 | } |
195 | |
196 | |
197 | /* wait for thread 0 to be signaled */ |
198 | dwRet = WaitForSingleObject(hEvent[0], 10000); |
199 | if (WAIT_OBJECT_0 != dwRet) |
200 | { |
201 | Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " |
202 | "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " |
203 | "('%d').\nGetLastError returned '%d'.\n" , hEvent[0], 10000, |
204 | WAIT_OBJECT_0, dwRet, GetLastError()); |
205 | if (0 == CloseHandle(hThread[0])) |
206 | { |
207 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
208 | "clean up.\nGetLastError returned '%d'.\n" , hThread[0], |
209 | GetLastError()); |
210 | } |
211 | if (0 == CloseHandle(hEvent[0])) |
212 | { |
213 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
214 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
215 | GetLastError()); |
216 | } |
217 | if (0 == CloseHandle(hEvent[1])) |
218 | { |
219 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
220 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[1], |
221 | GetLastError()); |
222 | } |
223 | Fail("" ); |
224 | } |
225 | |
226 | /* |
227 | * Attempting to enter CRITICAL_SECTION object owned by the |
228 | * created thread and locked with TryEnterCriticalSection |
229 | */ |
230 | if (0 == TryEnterCriticalSection(&CriticalSection)) |
231 | { |
232 | /* signal thread 1 */ |
233 | if (0 == SetEvent(hEvent[1])) |
234 | { |
235 | Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" |
236 | "GetLastError returned '%d'.\n" , hEvent[1], |
237 | GetLastError()); |
238 | goto done; |
239 | } |
240 | } |
241 | else |
242 | { |
243 | Trace("PALSUITE_ERROR: TryEnterCriticalSection was able to grab a" |
244 | " CRITICAL_SECTION object\nwhich was already owned.\n" ); |
245 | LeaveCriticalSection(&CriticalSection); |
246 | if (0 == CloseHandle(hThread[0])) |
247 | { |
248 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
249 | "clean up.\nGetLastError returned '%d'.\n" , hThread[0], |
250 | GetLastError()); |
251 | } |
252 | if (0 == CloseHandle(hEvent[0])) |
253 | { |
254 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
255 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
256 | GetLastError()); |
257 | } |
258 | if (0 == CloseHandle(hEvent[1])) |
259 | { |
260 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
261 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[1], |
262 | GetLastError()); |
263 | } |
264 | DeleteCriticalSection(&CriticalSection); |
265 | Fail("" ); |
266 | } |
267 | /* |
268 | * Enter the CRITICAL_SECTION and launch another thread to attempt |
269 | * to access the CRITICAL_SECTION with a call to TryEnterCriticalSection. |
270 | */ |
271 | EnterCriticalSection(&CriticalSection); |
272 | |
273 | hThread[1] = CreateThread(NULL, |
274 | 0, |
275 | &Thread, |
276 | (LPVOID) NULL, |
277 | 0, |
278 | &dwThreadId[1]); |
279 | |
280 | if (hThread[1] == NULL) |
281 | { |
282 | Trace("PALSUITE ERROR: CreateThread call #1 failed. GetLastError " |
283 | "returned %d.\n" , GetLastError()); |
284 | LeaveCriticalSection(&CriticalSection); |
285 | if (0 == CloseHandle(hThread[0])) |
286 | { |
287 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
288 | "clean up.\nGetLastError returned '%d'.\n" , hThread[0], |
289 | GetLastError()); |
290 | } |
291 | if (0 == CloseHandle(hEvent[0])) |
292 | { |
293 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
294 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
295 | GetLastError()); |
296 | } |
297 | if (0 == CloseHandle(hEvent[1])) |
298 | { |
299 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
300 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[1], |
301 | GetLastError()); |
302 | } |
303 | DeleteCriticalSection(&CriticalSection); |
304 | Fail("" ); |
305 | } |
306 | |
307 | dwRet = WaitForMultipleObjects(NUM_THREADS, hThread, TRUE, 10000); |
308 | if ((WAIT_OBJECT_0 > dwRet) || |
309 | ((WAIT_OBJECT_0 + NUM_THREADS - 1) < dwRet)) |
310 | { |
311 | Trace("PALSUITE ERROR: WaitForMultipleObjects(%d, %p, %d, %d) call " |
312 | "returned an unexpected value, '%d'.\nGetLastError returned " |
313 | "%d.\n" , NUM_THREADS, hThread, TRUE, 10000, dwRet, |
314 | GetLastError()); |
315 | LeaveCriticalSection(&CriticalSection); |
316 | if (0 == CloseHandle(hThread[0])) |
317 | { |
318 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
319 | "clean up.\nGetLastError returned '%d'.\n" , hThread[0], |
320 | GetLastError()); |
321 | } |
322 | if (0 == CloseHandle(hThread[1])) |
323 | { |
324 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
325 | "clean up.\nGetLastError returned '%d'.\n" , hThread[1], |
326 | GetLastError()); |
327 | } |
328 | if (0 == CloseHandle(hEvent[0])) |
329 | { |
330 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
331 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
332 | GetLastError()); |
333 | } |
334 | if (0 == CloseHandle(hEvent[1])) |
335 | { |
336 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
337 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[1], |
338 | GetLastError()); |
339 | } |
340 | DeleteCriticalSection(&CriticalSection); |
341 | Fail("" ); |
342 | } |
343 | |
344 | LeaveCriticalSection(&CriticalSection); |
345 | if (0 == CloseHandle(hThread[1])) |
346 | { |
347 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
348 | "clean up.\nGetLastError returned '%d'.\n" , hThread[1], |
349 | GetLastError()); |
350 | } |
351 | done: |
352 | if (0 == CloseHandle(hThread[0])) |
353 | { |
354 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
355 | "clean up.\nGetLastError returned '%d'.\n" , hThread[0], |
356 | GetLastError()); |
357 | } |
358 | if (0 == CloseHandle(hEvent[0])) |
359 | { |
360 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
361 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[0], |
362 | GetLastError()); |
363 | } |
364 | if (0 == CloseHandle(hEvent[1])) |
365 | { |
366 | Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during " |
367 | "clean up.\nGetLastError returned '%d'.\n" , hEvent[1], |
368 | GetLastError()); |
369 | } |
370 | DeleteCriticalSection(&CriticalSection); |
371 | |
372 | PAL_TerminateEx(bRet); |
373 | |
374 | return (bRet); |
375 | } |
376 | |
377 | |