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
34HANDLE hThread[NUM_THREADS];
35HANDLE hEvent[NUM_THREADS];
36CRITICAL_SECTION CriticalSection;
37BOOL bRet = FAIL;
38
39DWORD 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
132int __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 }
351done:
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