FreeRDP
Loading...
Searching...
No Matches
TestSynchMutex.c
1
2#include <winpr/crt.h>
3#include <winpr/synch.h>
4#include <winpr/thread.h>
5
6static BOOL test_mutex_basic(void)
7{
8 HANDLE mutex = NULL;
9 DWORD rc = 0;
10
11 if (!(mutex = CreateMutex(NULL, FALSE, NULL)))
12 {
13 printf("%s: CreateMutex failed\n", __func__);
14 return FALSE;
15 }
16
17 rc = WaitForSingleObject(mutex, INFINITE);
18
19 if (rc != WAIT_OBJECT_0)
20 {
21 printf("%s: WaitForSingleObject on mutex failed with %" PRIu32 "\n", __func__, rc);
22 return FALSE;
23 }
24
25 if (!ReleaseMutex(mutex))
26 {
27 printf("%s: ReleaseMutex failed\n", __func__);
28 return FALSE;
29 }
30
31 if (ReleaseMutex(mutex))
32 {
33 printf("%s: ReleaseMutex unexpectedly succeeded on released mutex\n", __func__);
34 return FALSE;
35 }
36
37 if (!CloseHandle(mutex))
38 {
39 printf("%s: CloseHandle on mutex failed\n", __func__);
40 return FALSE;
41 }
42
43 return TRUE;
44}
45
46static BOOL test_mutex_recursive(void)
47{
48 HANDLE mutex = NULL;
49 DWORD rc = 0;
50 DWORD cnt = 50;
51
52 if (!(mutex = CreateMutex(NULL, TRUE, NULL)))
53 {
54 printf("%s: CreateMutex failed\n", __func__);
55 return FALSE;
56 }
57
58 for (UINT32 i = 0; i < cnt; i++)
59 {
60 rc = WaitForSingleObject(mutex, INFINITE);
61
62 if (rc != WAIT_OBJECT_0)
63 {
64 printf("%s: WaitForSingleObject #%" PRIu32 " on mutex failed with %" PRIu32 "\n",
65 __func__, i, rc);
66 return FALSE;
67 }
68 }
69
70 for (UINT32 i = 0; i < cnt; i++)
71 {
72 if (!ReleaseMutex(mutex))
73 {
74 printf("%s: ReleaseMutex #%" PRIu32 " failed\n", __func__, i);
75 return FALSE;
76 }
77 }
78
79 if (!ReleaseMutex(mutex))
80 {
81 /* Note: The mutex was initially owned ! */
82 printf("%s: Final ReleaseMutex failed\n", __func__);
83 return FALSE;
84 }
85
86 if (ReleaseMutex(mutex))
87 {
88 printf("%s: ReleaseMutex unexpectedly succeeded on released mutex\n", __func__);
89 return FALSE;
90 }
91
92 if (!CloseHandle(mutex))
93 {
94 printf("%s: CloseHandle on mutex failed\n", __func__);
95 return FALSE;
96 }
97
98 return TRUE;
99}
100
101static HANDLE thread1_mutex1 = NULL;
102static HANDLE thread1_mutex2 = NULL;
103static BOOL thread1_failed = TRUE;
104
105static DWORD WINAPI test_mutex_thread1(LPVOID lpParam)
106{
107 HANDLE hStartEvent = (HANDLE)lpParam;
108 DWORD rc = 0;
109
110 if (WaitForSingleObject(hStartEvent, INFINITE) != WAIT_OBJECT_0)
111 {
112 (void)fprintf(stderr, "%s: failed to wait for start event\n", __func__);
113 return 0;
114 }
115
124 rc = WaitForSingleObject(thread1_mutex1, 10);
125
126 if (rc != WAIT_TIMEOUT)
127 {
128 (void)fprintf(stderr,
129 "%s: WaitForSingleObject on thread1_mutex1 unexpectedly returned %" PRIu32
130 " instead of WAIT_TIMEOUT (%u)\n",
131 __func__, rc, WAIT_TIMEOUT);
132 return 0;
133 }
134
135 rc = WaitForSingleObject(thread1_mutex2, 10);
136
137 if (rc != WAIT_OBJECT_0)
138 {
139 (void)fprintf(stderr,
140 "%s: WaitForSingleObject on thread1_mutex2 unexpectedly returned %" PRIu32
141 " instead of WAIT_OBJECT_0\n",
142 __func__, rc);
143 return 0;
144 }
145
146 if (!ReleaseMutex(thread1_mutex2))
147 {
148 (void)fprintf(stderr, "%s: ReleaseMutex failed on thread1_mutex2\n", __func__);
149 return 0;
150 }
151
152 thread1_failed = FALSE;
153 return 0;
154}
155
156static BOOL test_mutex_threading(void)
157{
158 HANDLE hThread = NULL;
159 HANDLE hStartEvent = NULL;
160
161 if (!(thread1_mutex1 = CreateMutex(NULL, TRUE, NULL)))
162 {
163 printf("%s: CreateMutex thread1_mutex1 failed\n", __func__);
164 goto fail;
165 }
166
167 if (!(thread1_mutex2 = CreateMutex(NULL, FALSE, NULL)))
168 {
169 printf("%s: CreateMutex thread1_mutex2 failed\n", __func__);
170 goto fail;
171 }
172
173 if (!(hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
174 {
175 (void)fprintf(stderr, "%s: error creating start event\n", __func__);
176 goto fail;
177 }
178
179 thread1_failed = TRUE;
180
181 if (!(hThread = CreateThread(NULL, 0, test_mutex_thread1, (LPVOID)hStartEvent, 0, NULL)))
182 {
183 (void)fprintf(stderr, "%s: error creating test_mutex_thread_1\n", __func__);
184 goto fail;
185 }
186
187 Sleep(100);
188
189 if (!thread1_failed)
190 {
191 (void)fprintf(stderr, "%s: thread1 premature success\n", __func__);
192 goto fail;
193 }
194
195 (void)SetEvent(hStartEvent);
196
197 if (WaitForSingleObject(hThread, 2000) != WAIT_OBJECT_0)
198 {
199 (void)fprintf(stderr, "%s: thread1 premature success\n", __func__);
200 goto fail;
201 }
202
203 if (thread1_failed)
204 {
205 (void)fprintf(stderr, "%s: thread1 has not reported success\n", __func__);
206 goto fail;
207 }
208
214 if (!ReleaseMutex(thread1_mutex1))
215 {
216 printf("%s: ReleaseMutex unexpectedly failed on thread1_mutex1\n", __func__);
217 goto fail;
218 }
219
220 if (ReleaseMutex(thread1_mutex2))
221 {
222 printf("%s: ReleaseMutex unexpectedly succeeded on thread1_mutex2\n", __func__);
223 goto fail;
224 }
225
226 (void)CloseHandle(hThread);
227 (void)CloseHandle(hStartEvent);
228 (void)CloseHandle(thread1_mutex1);
229 (void)CloseHandle(thread1_mutex2);
230 return TRUE;
231fail:
232 (void)ReleaseMutex(thread1_mutex1);
233 (void)ReleaseMutex(thread1_mutex2);
234 (void)CloseHandle(thread1_mutex1);
235 (void)CloseHandle(thread1_mutex2);
236 (void)CloseHandle(hStartEvent);
237 (void)CloseHandle(hThread);
238 return FALSE;
239}
240
241int TestSynchMutex(int argc, char* argv[])
242{
243 int rc = 0;
244 WINPR_UNUSED(argc);
245 WINPR_UNUSED(argv);
246
247 if (!test_mutex_basic())
248 rc += 1;
249
250 if (!test_mutex_recursive())
251 rc += 2;
252
253 if (!test_mutex_threading())
254 rc += 4;
255
256 printf("TestSynchMutex result %d\n", rc);
257 return rc;
258}