1 /*
2 *
3 *
4 * --------------------------------------------------------------------------
5 *
6 * Pthreads-win32 - POSIX Threads Library for Win32
7 * Copyright(C) 1998 John E. Bossom
8 * Copyright(C) 1999,2005 Pthreads-win32 contributors
9 *
10 * Contact Email: rpj@callisto.canberra.edu.au
11 *
12 * The current list of contributors is contained
13 * in the file CONTRIBUTORS included with the source
14 * code distribution. The list can also be seen at the
15 * following World Wide Web location:
16 * http://sources.redhat.com/pthreads-win32/contributors.html
17 *
18 * This library is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU Lesser General Public
20 * License as published by the Free Software Foundation; either
21 * version 2 of the License, or (at your option) any later version.
22 *
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Lesser General Public License for more details.
27 *
28 * You should have received a copy of the GNU Lesser General Public
29 * License along with this library in the file COPYING.LIB;
30 * if not, write to the Free Software Foundation, Inc.,
31 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
32 *
33 */
34
35 #include "../include/pthread.h"
36 //#include "sched.h"
37 //#include "semaphore.h"
38 #include <windows.h>
39 #include <stdio.h>
40
41 #ifdef __GNUC__
42 #include <stdlib.h>
43 #endif
44
45 #include "benchtest.h"
46
47 int old_mutex_use = OLD_WIN32CS;
48
49 BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION) = NULL;
50 HINSTANCE ptw32_h_kernel32;
51
52 void
dummy_call(int * a)53 dummy_call(int * a)
54 {
55 }
56
57 void
interlocked_inc_with_conditionals(int * a)58 interlocked_inc_with_conditionals(int * a)
59 {
60 if (a != NULL)
61 if (InterlockedIncrement((long *) a) == -1)
62 {
63 *a = 0;
64 }
65 }
66
67 void
interlocked_dec_with_conditionals(int * a)68 interlocked_dec_with_conditionals(int * a)
69 {
70 if (a != NULL)
71 if (InterlockedDecrement((long *) a) == -1)
72 {
73 *a = 0;
74 }
75 }
76
77 int
old_mutex_init(old_mutex_t * mutex,const old_mutexattr_t * attr)78 old_mutex_init(old_mutex_t *mutex, const old_mutexattr_t *attr)
79 {
80 int result = 0;
81 old_mutex_t mx;
82
83 if (mutex == NULL)
84 {
85 return EINVAL;
86 }
87
88 mx = (old_mutex_t) calloc(1, sizeof(*mx));
89
90 if (mx == NULL)
91 {
92 result = ENOMEM;
93 goto FAIL0;
94 }
95
96 mx->mutex = 0;
97
98 if (attr != NULL
99 && *attr != NULL
100 && (*attr)->pshared == PTHREAD_PROCESS_SHARED
101 )
102 {
103 result = ENOSYS;
104 }
105 else
106 {
107 CRITICAL_SECTION cs;
108
109 /*
110 * Load KERNEL32 and try to get address of TryEnterCriticalSection
111 */
112 ptw32_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));
113 ptw32_try_enter_critical_section = (BOOL (WINAPI *)(LPCRITICAL_SECTION))
114
115 #if defined(NEED_UNICODE_CONSTS)
116 GetProcAddress(ptw32_h_kernel32,
117 (const TCHAR *)TEXT("TryEnterCriticalSection"));
118 #else
119 GetProcAddress(ptw32_h_kernel32,
120 (LPCSTR) "TryEnterCriticalSection");
121 #endif
122
123 if (ptw32_try_enter_critical_section != NULL)
124 {
125 InitializeCriticalSection(&cs);
126 if ((*ptw32_try_enter_critical_section)(&cs))
127 {
128 LeaveCriticalSection(&cs);
129 }
130 else
131 {
132 /*
133 * Not really supported (Win98?).
134 */
135 ptw32_try_enter_critical_section = NULL;
136 }
137 DeleteCriticalSection(&cs);
138 }
139
140 if (ptw32_try_enter_critical_section == NULL)
141 {
142 (void) FreeLibrary(ptw32_h_kernel32);
143 ptw32_h_kernel32 = 0;
144 }
145
146 if (old_mutex_use == OLD_WIN32CS)
147 {
148 InitializeCriticalSection(&mx->cs);
149 }
150 else if (old_mutex_use == OLD_WIN32MUTEX)
151 {
152 mx->mutex = CreateMutex (NULL,
153 FALSE,
154 NULL);
155
156 if (mx->mutex == 0)
157 {
158 result = EAGAIN;
159 }
160 }
161 else
162 {
163 result = EINVAL;
164 }
165 }
166
167 if (result != 0 && mx != NULL)
168 {
169 free(mx);
170 mx = NULL;
171 }
172
173 FAIL0:
174 *mutex = mx;
175
176 return(result);
177 }
178
179
180 int
old_mutex_lock(old_mutex_t * mutex)181 old_mutex_lock(old_mutex_t *mutex)
182 {
183 int result = 0;
184 old_mutex_t mx;
185
186 if (mutex == NULL || *mutex == NULL)
187 {
188 return EINVAL;
189 }
190
191 if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
192 {
193 /*
194 * Don't use initialisers when benchtesting.
195 */
196 result = EINVAL;
197 }
198
199 mx = *mutex;
200
201 if (result == 0)
202 {
203 if (mx->mutex == 0)
204 {
205 EnterCriticalSection(&mx->cs);
206 }
207 else
208 {
209 result = (WaitForSingleObject(mx->mutex, INFINITE)
210 == WAIT_OBJECT_0)
211 ? 0
212 : EINVAL;
213 }
214 }
215
216 return(result);
217 }
218
219 int
old_mutex_unlock(old_mutex_t * mutex)220 old_mutex_unlock(old_mutex_t *mutex)
221 {
222 int result = 0;
223 old_mutex_t mx;
224
225 if (mutex == NULL || *mutex == NULL)
226 {
227 return EINVAL;
228 }
229
230 mx = *mutex;
231
232 if (mx != (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
233 {
234 if (mx->mutex == 0)
235 {
236 LeaveCriticalSection(&mx->cs);
237 }
238 else
239 {
240 result = (ReleaseMutex (mx->mutex) ? 0 : EINVAL);
241 }
242 }
243 else
244 {
245 result = EINVAL;
246 }
247
248 return(result);
249 }
250
251
252 int
old_mutex_trylock(old_mutex_t * mutex)253 old_mutex_trylock(old_mutex_t *mutex)
254 {
255 int result = 0;
256 old_mutex_t mx;
257
258 if (mutex == NULL || *mutex == NULL)
259 {
260 return EINVAL;
261 }
262
263 if (*mutex == (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
264 {
265 /*
266 * Don't use initialisers when benchtesting.
267 */
268 result = EINVAL;
269 }
270
271 mx = *mutex;
272
273 if (result == 0)
274 {
275 if (mx->mutex == 0)
276 {
277 if (ptw32_try_enter_critical_section == NULL)
278 {
279 result = 0;
280 }
281 else if ((*ptw32_try_enter_critical_section)(&mx->cs) != TRUE)
282 {
283 result = EBUSY;
284 }
285 }
286 else
287 {
288 DWORD status;
289
290 status = WaitForSingleObject (mx->mutex, 0);
291
292 if (status != WAIT_OBJECT_0)
293 {
294 result = ((status == WAIT_TIMEOUT)
295 ? EBUSY
296 : EINVAL);
297 }
298 }
299 }
300
301 return(result);
302 }
303
304
305 int
old_mutex_destroy(old_mutex_t * mutex)306 old_mutex_destroy(old_mutex_t *mutex)
307 {
308 int result = 0;
309 old_mutex_t mx;
310
311 if (mutex == NULL
312 || *mutex == NULL)
313 {
314 return EINVAL;
315 }
316
317 if (*mutex != (old_mutex_t) PTW32_OBJECT_AUTO_INIT)
318 {
319 mx = *mutex;
320
321 if ((result = old_mutex_trylock(&mx)) == 0)
322 {
323 *mutex = NULL;
324
325 (void) old_mutex_unlock(&mx);
326
327 if (mx->mutex == 0)
328 {
329 DeleteCriticalSection(&mx->cs);
330 }
331 else
332 {
333 result = (CloseHandle (mx->mutex) ? 0 : EINVAL);
334 }
335
336 if (result == 0)
337 {
338 mx->mutex = 0;
339 free(mx);
340 }
341 else
342 {
343 *mutex = mx;
344 }
345 }
346 }
347 else
348 {
349 result = EINVAL;
350 }
351
352 if (ptw32_try_enter_critical_section != NULL)
353 {
354 (void) FreeLibrary(ptw32_h_kernel32);
355 ptw32_h_kernel32 = 0;
356 }
357
358 return(result);
359 }
360
361 /****************************************************************************************/
362