FreeRDP
TestSynchMutex.c
1 
2 #include <winpr/crt.h>
3 #include <winpr/synch.h>
4 #include <winpr/thread.h>
5 
6 static 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 
46 static 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 
101 static HANDLE thread1_mutex1 = NULL;
102 static HANDLE thread1_mutex2 = NULL;
103 static BOOL thread1_failed = TRUE;
104 
105 static 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 
156 static 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;
231 fail:
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 
241 int 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 }