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 | |
21 | HANDLE hToken[NUM_TOKENS]; |
22 | CRITICAL_SECTION CriticalSection; |
23 | |
24 | BOOL 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 | |
39 | BOOL 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 | |
60 | DWORD 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 | |
97 | int __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 | |