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/test6/test6.c
8**
9** Purpose: Attempt to leave a critical section which is owned by
10** another thread.
11**
12**
13**===================================================================*/
14#include <palsuite.h>
15
16/*
17 * Tokens 0 and 1 are events. Token 2 is the thread.
18 */
19#define NUM_TOKENS 3
20
21HANDLE hToken[NUM_TOKENS];
22CRITICAL_SECTION CriticalSection;
23
24BOOL CleanupHelper (HANDLE *hArray, DWORD dwIndex)
25{
26 BOOL bCHRet;
27
28 bCHRet = CloseHandle(hArray[dwIndex]);
29 if (!bCHRet)
30 {
31 Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
32 "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
33 GetLastError());
34 }
35
36 return (bCHRet);
37}
38
39BOOL Cleanup(HANDLE *hArray, DWORD dwIndex)
40{
41 BOOL bCRet;
42 BOOL bCHRet;
43
44 while (--dwIndex > 0)
45 {
46 bCHRet = CleanupHelper(&hArray[0], dwIndex);
47 }
48
49 bCRet = CloseHandle(hArray[0]);
50 if (!bCRet)
51 {
52 Trace("PALSUITE ERROR: Unable to execute CloseHandle(%p) during "
53 "clean up.\nGetLastError returned '%u'.\n", hArray[dwIndex],
54 GetLastError());
55 }
56
57 return (bCRet&&bCHRet);
58}
59
60DWORD PALAPI Thread(LPVOID lpParam)
61{
62 DWORD dwTRet;
63
64 EnterCriticalSection(&CriticalSection);
65
66 /* signal thread 0 */
67 if (0 == SetEvent(hToken[0]))
68 {
69 Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during "
70 "clean up.\nGetLastError returned '%u'.\n", hToken[0],
71 GetLastError());
72 LeaveCriticalSection(&CriticalSection);
73 Cleanup (&hToken[0], NUM_TOKENS);
74 DeleteCriticalSection(&CriticalSection);
75 Fail("");
76 }
77
78 /* wait to be signaled */
79 dwTRet = WaitForSingleObject(hToken[1], 10000);
80 if (WAIT_OBJECT_0 != dwTRet)
81 {
82 Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
83 "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
84 "('%d').\nGetLastError returned '%u'.\n",
85 hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError());
86 LeaveCriticalSection(&CriticalSection);
87 Cleanup (&hToken[0], NUM_TOKENS);
88 DeleteCriticalSection(&CriticalSection);
89 Fail("");
90 }
91
92 LeaveCriticalSection(&CriticalSection);
93
94 return 0;
95}
96
97int __cdecl main(int argc, char **argv)
98{
99 DWORD dwThreadId;
100 DWORD dwMRet;
101
102 if ((PAL_Initialize(argc,argv)) != 0)
103 {
104 return(FAIL);
105 }
106
107 /* thread 0 event */
108 hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
109
110 if (hToken[0] == NULL)
111 {
112 Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError "
113 "returned %u.\n", GetLastError());
114 }
115
116 /* thread 1 event */
117 hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
118
119 if (hToken[1] == NULL)
120 {
121 Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError "
122 "returned %u.\n", GetLastError());
123 Cleanup(&hToken[0], (NUM_TOKENS - 2));
124 Fail("");
125 }
126
127 InitializeCriticalSection(&CriticalSection);
128
129 hToken[2] = CreateThread(NULL,
130 0,
131 &Thread,
132 (LPVOID) NULL,
133 0,
134 &dwThreadId);
135
136 if (hToken[2] == NULL)
137 {
138 Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError "
139 "returned %u.\n", GetLastError());
140 Cleanup(&hToken[0], (NUM_TOKENS - 1));
141 DeleteCriticalSection(&CriticalSection);
142 Fail("");
143 }
144
145 /* wait for thread 0 to be signaled */
146 dwMRet = WaitForSingleObject(hToken[0], 10000);
147 if (WAIT_OBJECT_0 != dwMRet)
148 {
149 Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have "
150 "returned\nWAIT_OBJECT_0 ('%d'), instead it returned "
151 "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000,
152 WAIT_OBJECT_0, dwMRet, GetLastError());
153 Cleanup(&hToken[0], NUM_TOKENS);
154 Fail("");
155 }
156
157 /*
158 * Attempt to leave critical section which is owned by the other thread.
159 */
160 LeaveCriticalSection(&CriticalSection);
161
162 /* signal thread 1 */
163 if (0 == SetEvent(hToken[1]))
164 {
165 Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n"
166 "GetLastError returned '%u'.\n", hToken[1],
167 GetLastError());
168 Cleanup(&hToken[0], NUM_TOKENS);
169 Fail("");
170 }
171
172 dwMRet = WaitForSingleObject(hToken[2], 10000);
173 if (WAIT_OBJECT_0 != dwMRet)
174 {
175 Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call "
176 "returned an unexpected value '%d'.\nGetLastError returned "
177 "%u.\n", hToken[2], 10000, dwMRet, GetLastError());
178 Cleanup(&hToken[0], NUM_TOKENS);
179 Fail("");
180 }
181
182 if (!Cleanup(&hToken[0], NUM_TOKENS))
183 {
184 Fail("");
185 }
186
187 PAL_Terminate();
188
189 return(PASS);
190}
191