gthr-win32.h revision 1.3 1 1.1 mrg /* Threads compatibility routines for libgcc2 and libobjc. */
2 1.1 mrg /* Compile this one with gcc. */
3 1.1 mrg
4 1.3 mrg /* Copyright (C) 1999-2015 Free Software Foundation, Inc.
5 1.1 mrg Contributed by Mumit Khan <khan (at) xraylith.wisc.edu>.
6 1.1 mrg
7 1.1 mrg This file is part of GCC.
8 1.1 mrg
9 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
10 1.1 mrg the terms of the GNU General Public License as published by the Free
11 1.1 mrg Software Foundation; either version 3, or (at your option) any later
12 1.1 mrg version.
13 1.1 mrg
14 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 1.1 mrg for more details.
18 1.1 mrg
19 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
20 1.1 mrg permissions described in the GCC Runtime Library Exception, version
21 1.1 mrg 3.1, as published by the Free Software Foundation.
22 1.1 mrg
23 1.1 mrg You should have received a copy of the GNU General Public License and
24 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
25 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 1.1 mrg <http://www.gnu.org/licenses/>. */
27 1.1 mrg
28 1.1 mrg #ifndef GCC_GTHR_WIN32_H
29 1.1 mrg #define GCC_GTHR_WIN32_H
30 1.1 mrg
31 1.1 mrg /* Make sure CONST_CAST2 (origin in system.h) is declared. */
32 1.1 mrg #ifndef CONST_CAST2
33 1.1 mrg #define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
34 1.1 mrg #endif
35 1.1 mrg
36 1.1 mrg /* Windows32 threads specific definitions. The windows32 threading model
37 1.1 mrg does not map well into pthread-inspired gcc's threading model, and so
38 1.1 mrg there are caveats one needs to be aware of.
39 1.1 mrg
40 1.1 mrg 1. The destructor supplied to __gthread_key_create is ignored for
41 1.1 mrg generic x86-win32 ports. This will certainly cause memory leaks
42 1.1 mrg due to unreclaimed eh contexts (sizeof (eh_context) is at least
43 1.1 mrg 24 bytes for x86 currently).
44 1.1 mrg
45 1.1 mrg This memory leak may be significant for long-running applications
46 1.1 mrg that make heavy use of C++ EH.
47 1.1 mrg
48 1.1 mrg However, Mingw runtime (version 0.3 or newer) provides a mechanism
49 1.1 mrg to emulate pthreads key dtors; the runtime provides a special DLL,
50 1.1 mrg linked in if -mthreads option is specified, that runs the dtors in
51 1.1 mrg the reverse order of registration when each thread exits. If
52 1.1 mrg -mthreads option is not given, a stub is linked in instead of the
53 1.1 mrg DLL, which results in memory leak. Other x86-win32 ports can use
54 1.1 mrg the same technique of course to avoid the leak.
55 1.1 mrg
56 1.1 mrg 2. The error codes returned are non-POSIX like, and cast into ints.
57 1.1 mrg This may cause incorrect error return due to truncation values on
58 1.1 mrg hw where sizeof (DWORD) > sizeof (int).
59 1.1 mrg
60 1.1 mrg 3. We are currently using a special mutex instead of the Critical
61 1.1 mrg Sections, since Win9x does not support TryEnterCriticalSection
62 1.1 mrg (while NT does).
63 1.1 mrg
64 1.1 mrg The basic framework should work well enough. In the long term, GCC
65 1.1 mrg needs to use Structured Exception Handling on Windows32. */
66 1.1 mrg
67 1.1 mrg #define __GTHREADS 1
68 1.1 mrg
69 1.1 mrg #include <errno.h>
70 1.1 mrg #ifdef __MINGW32__
71 1.1 mrg #include <_mingw.h>
72 1.1 mrg #endif
73 1.1 mrg
74 1.1 mrg #ifndef __UNUSED_PARAM
75 1.1 mrg #define __UNUSED_PARAM(x) x
76 1.1 mrg #endif
77 1.1 mrg
78 1.1 mrg #ifdef _LIBOBJC
79 1.1 mrg
80 1.1 mrg /* This is necessary to prevent windef.h (included from windows.h) from
81 1.1 mrg defining its own BOOL as a typedef. */
82 1.1 mrg #ifndef __OBJC__
83 1.1 mrg #define __OBJC__
84 1.1 mrg #endif
85 1.1 mrg #include <windows.h>
86 1.1 mrg /* Now undef the windows BOOL. */
87 1.1 mrg #undef BOOL
88 1.1 mrg
89 1.1 mrg /* Key structure for maintaining thread specific storage */
90 1.1 mrg static DWORD __gthread_objc_data_tls = (DWORD) -1;
91 1.1 mrg
92 1.1 mrg /* Backend initialization functions */
93 1.1 mrg
94 1.1 mrg /* Initialize the threads subsystem. */
95 1.1 mrg int
96 1.1 mrg __gthread_objc_init_thread_system (void)
97 1.1 mrg {
98 1.1 mrg /* Initialize the thread storage key. */
99 1.1 mrg if ((__gthread_objc_data_tls = TlsAlloc ()) != (DWORD) -1)
100 1.1 mrg return 0;
101 1.1 mrg else
102 1.1 mrg return -1;
103 1.1 mrg }
104 1.1 mrg
105 1.1 mrg /* Close the threads subsystem. */
106 1.1 mrg int
107 1.1 mrg __gthread_objc_close_thread_system (void)
108 1.1 mrg {
109 1.1 mrg if (__gthread_objc_data_tls != (DWORD) -1)
110 1.1 mrg TlsFree (__gthread_objc_data_tls);
111 1.1 mrg return 0;
112 1.1 mrg }
113 1.1 mrg
114 1.1 mrg /* Backend thread functions */
115 1.1 mrg
116 1.1 mrg /* Create a new thread of execution. */
117 1.1 mrg objc_thread_t
118 1.1 mrg __gthread_objc_thread_detach (void (*func)(void *arg), void *arg)
119 1.1 mrg {
120 1.1 mrg DWORD thread_id = 0;
121 1.1 mrg HANDLE win32_handle;
122 1.1 mrg
123 1.1 mrg if (!(win32_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) func,
124 1.1 mrg arg, 0, &thread_id)))
125 1.1 mrg thread_id = 0;
126 1.1 mrg
127 1.1 mrg return (objc_thread_t) (INT_PTR) thread_id;
128 1.1 mrg }
129 1.1 mrg
130 1.1 mrg /* Set the current thread's priority. */
131 1.1 mrg int
132 1.1 mrg __gthread_objc_thread_set_priority (int priority)
133 1.1 mrg {
134 1.1 mrg int sys_priority = 0;
135 1.1 mrg
136 1.1 mrg switch (priority)
137 1.1 mrg {
138 1.1 mrg case OBJC_THREAD_INTERACTIVE_PRIORITY:
139 1.1 mrg sys_priority = THREAD_PRIORITY_NORMAL;
140 1.1 mrg break;
141 1.1 mrg default:
142 1.1 mrg case OBJC_THREAD_BACKGROUND_PRIORITY:
143 1.1 mrg sys_priority = THREAD_PRIORITY_BELOW_NORMAL;
144 1.1 mrg break;
145 1.1 mrg case OBJC_THREAD_LOW_PRIORITY:
146 1.1 mrg sys_priority = THREAD_PRIORITY_LOWEST;
147 1.1 mrg break;
148 1.1 mrg }
149 1.1 mrg
150 1.1 mrg /* Change priority */
151 1.1 mrg if (SetThreadPriority (GetCurrentThread (), sys_priority))
152 1.1 mrg return 0;
153 1.1 mrg else
154 1.1 mrg return -1;
155 1.1 mrg }
156 1.1 mrg
157 1.1 mrg /* Return the current thread's priority. */
158 1.1 mrg int
159 1.1 mrg __gthread_objc_thread_get_priority (void)
160 1.1 mrg {
161 1.1 mrg int sys_priority;
162 1.1 mrg
163 1.1 mrg sys_priority = GetThreadPriority (GetCurrentThread ());
164 1.1 mrg
165 1.1 mrg switch (sys_priority)
166 1.1 mrg {
167 1.1 mrg case THREAD_PRIORITY_HIGHEST:
168 1.1 mrg case THREAD_PRIORITY_TIME_CRITICAL:
169 1.1 mrg case THREAD_PRIORITY_ABOVE_NORMAL:
170 1.1 mrg case THREAD_PRIORITY_NORMAL:
171 1.1 mrg return OBJC_THREAD_INTERACTIVE_PRIORITY;
172 1.1 mrg
173 1.1 mrg default:
174 1.1 mrg case THREAD_PRIORITY_BELOW_NORMAL:
175 1.1 mrg return OBJC_THREAD_BACKGROUND_PRIORITY;
176 1.1 mrg
177 1.1 mrg case THREAD_PRIORITY_IDLE:
178 1.1 mrg case THREAD_PRIORITY_LOWEST:
179 1.1 mrg return OBJC_THREAD_LOW_PRIORITY;
180 1.1 mrg }
181 1.1 mrg
182 1.1 mrg /* Couldn't get priority. */
183 1.1 mrg return -1;
184 1.1 mrg }
185 1.1 mrg
186 1.1 mrg /* Yield our process time to another thread. */
187 1.1 mrg void
188 1.1 mrg __gthread_objc_thread_yield (void)
189 1.1 mrg {
190 1.1 mrg Sleep (0);
191 1.1 mrg }
192 1.1 mrg
193 1.1 mrg /* Terminate the current thread. */
194 1.1 mrg int
195 1.1 mrg __gthread_objc_thread_exit (void)
196 1.1 mrg {
197 1.1 mrg /* exit the thread */
198 1.1 mrg ExitThread (__objc_thread_exit_status);
199 1.1 mrg
200 1.1 mrg /* Failed if we reached here */
201 1.1 mrg return -1;
202 1.1 mrg }
203 1.1 mrg
204 1.1 mrg /* Returns an integer value which uniquely describes a thread. */
205 1.1 mrg objc_thread_t
206 1.1 mrg __gthread_objc_thread_id (void)
207 1.1 mrg {
208 1.1 mrg return (objc_thread_t) (INT_PTR) GetCurrentThreadId ();
209 1.1 mrg }
210 1.1 mrg
211 1.1 mrg /* Sets the thread's local storage pointer. */
212 1.1 mrg int
213 1.1 mrg __gthread_objc_thread_set_data (void *value)
214 1.1 mrg {
215 1.1 mrg if (TlsSetValue (__gthread_objc_data_tls, value))
216 1.1 mrg return 0;
217 1.1 mrg else
218 1.1 mrg return -1;
219 1.1 mrg }
220 1.1 mrg
221 1.1 mrg /* Returns the thread's local storage pointer. */
222 1.1 mrg void *
223 1.1 mrg __gthread_objc_thread_get_data (void)
224 1.1 mrg {
225 1.1 mrg DWORD lasterror;
226 1.1 mrg void *ptr;
227 1.1 mrg
228 1.1 mrg lasterror = GetLastError ();
229 1.1 mrg
230 1.1 mrg ptr = TlsGetValue (__gthread_objc_data_tls); /* Return thread data. */
231 1.1 mrg
232 1.1 mrg SetLastError (lasterror);
233 1.1 mrg
234 1.1 mrg return ptr;
235 1.1 mrg }
236 1.1 mrg
237 1.1 mrg /* Backend mutex functions */
238 1.1 mrg
239 1.1 mrg /* Allocate a mutex. */
240 1.1 mrg int
241 1.1 mrg __gthread_objc_mutex_allocate (objc_mutex_t mutex)
242 1.1 mrg {
243 1.1 mrg if ((mutex->backend = (void *) CreateMutex (NULL, 0, NULL)) == NULL)
244 1.1 mrg return -1;
245 1.1 mrg else
246 1.1 mrg return 0;
247 1.1 mrg }
248 1.1 mrg
249 1.1 mrg /* Deallocate a mutex. */
250 1.1 mrg int
251 1.1 mrg __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
252 1.1 mrg {
253 1.1 mrg CloseHandle ((HANDLE) (mutex->backend));
254 1.1 mrg return 0;
255 1.1 mrg }
256 1.1 mrg
257 1.1 mrg /* Grab a lock on a mutex. */
258 1.1 mrg int
259 1.1 mrg __gthread_objc_mutex_lock (objc_mutex_t mutex)
260 1.1 mrg {
261 1.1 mrg int status;
262 1.1 mrg
263 1.1 mrg status = WaitForSingleObject ((HANDLE) (mutex->backend), INFINITE);
264 1.1 mrg if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
265 1.1 mrg return -1;
266 1.1 mrg else
267 1.1 mrg return 0;
268 1.1 mrg }
269 1.1 mrg
270 1.1 mrg /* Try to grab a lock on a mutex. */
271 1.1 mrg int
272 1.1 mrg __gthread_objc_mutex_trylock (objc_mutex_t mutex)
273 1.1 mrg {
274 1.1 mrg int status;
275 1.1 mrg
276 1.1 mrg status = WaitForSingleObject ((HANDLE) (mutex->backend), 0);
277 1.1 mrg if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
278 1.1 mrg return -1;
279 1.1 mrg else
280 1.1 mrg return 0;
281 1.1 mrg }
282 1.1 mrg
283 1.1 mrg /* Unlock the mutex */
284 1.1 mrg int
285 1.1 mrg __gthread_objc_mutex_unlock (objc_mutex_t mutex)
286 1.1 mrg {
287 1.1 mrg if (ReleaseMutex ((HANDLE) (mutex->backend)) == 0)
288 1.1 mrg return -1;
289 1.1 mrg else
290 1.1 mrg return 0;
291 1.1 mrg }
292 1.1 mrg
293 1.1 mrg /* Backend condition mutex functions */
294 1.1 mrg
295 1.1 mrg /* Allocate a condition. */
296 1.1 mrg int
297 1.1 mrg __gthread_objc_condition_allocate (objc_condition_t __UNUSED_PARAM(condition))
298 1.1 mrg {
299 1.1 mrg /* Unimplemented. */
300 1.1 mrg return -1;
301 1.1 mrg }
302 1.1 mrg
303 1.1 mrg /* Deallocate a condition. */
304 1.1 mrg int
305 1.1 mrg __gthread_objc_condition_deallocate (objc_condition_t __UNUSED_PARAM(condition))
306 1.1 mrg {
307 1.1 mrg /* Unimplemented. */
308 1.1 mrg return -1;
309 1.1 mrg }
310 1.1 mrg
311 1.1 mrg /* Wait on the condition */
312 1.1 mrg int
313 1.1 mrg __gthread_objc_condition_wait (objc_condition_t __UNUSED_PARAM(condition),
314 1.1 mrg objc_mutex_t __UNUSED_PARAM(mutex))
315 1.1 mrg {
316 1.1 mrg /* Unimplemented. */
317 1.1 mrg return -1;
318 1.1 mrg }
319 1.1 mrg
320 1.1 mrg /* Wake up all threads waiting on this condition. */
321 1.1 mrg int
322 1.1 mrg __gthread_objc_condition_broadcast (objc_condition_t __UNUSED_PARAM(condition))
323 1.1 mrg {
324 1.1 mrg /* Unimplemented. */
325 1.1 mrg return -1;
326 1.1 mrg }
327 1.1 mrg
328 1.1 mrg /* Wake up one thread waiting on this condition. */
329 1.1 mrg int
330 1.1 mrg __gthread_objc_condition_signal (objc_condition_t __UNUSED_PARAM(condition))
331 1.1 mrg {
332 1.1 mrg /* Unimplemented. */
333 1.1 mrg return -1;
334 1.1 mrg }
335 1.1 mrg
336 1.1 mrg #else /* _LIBOBJC */
337 1.1 mrg
338 1.1 mrg #ifdef __cplusplus
339 1.1 mrg extern "C" {
340 1.1 mrg #endif
341 1.1 mrg
342 1.1 mrg typedef unsigned long __gthread_key_t;
343 1.1 mrg
344 1.1 mrg typedef struct {
345 1.1 mrg int done;
346 1.1 mrg long started;
347 1.1 mrg } __gthread_once_t;
348 1.1 mrg
349 1.1 mrg typedef struct {
350 1.1 mrg long counter;
351 1.1 mrg void *sema;
352 1.1 mrg } __gthread_mutex_t;
353 1.1 mrg
354 1.1 mrg typedef struct {
355 1.1 mrg long counter;
356 1.1 mrg long depth;
357 1.1 mrg unsigned long owner;
358 1.1 mrg void *sema;
359 1.1 mrg } __gthread_recursive_mutex_t;
360 1.1 mrg
361 1.1 mrg #define __GTHREAD_ONCE_INIT {0, -1}
362 1.1 mrg #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
363 1.1 mrg #define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0}
364 1.1 mrg #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
365 1.1 mrg __gthread_recursive_mutex_init_function
366 1.1 mrg #define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0}
367 1.1 mrg
368 1.1 mrg #if defined (_WIN32) && !defined(__CYGWIN__)
369 1.1 mrg #define MINGW32_SUPPORTS_MT_EH 1
370 1.1 mrg /* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero
371 1.1 mrg if -mthreads option was specified, or 0 otherwise. This is to get around
372 1.1 mrg the lack of weak symbols in PE-COFF. */
373 1.1 mrg extern int _CRT_MT;
374 1.1 mrg extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
375 1.1 mrg #endif /* _WIN32 && !__CYGWIN__ */
376 1.1 mrg
377 1.1 mrg /* The Windows95 kernel does not export InterlockedCompareExchange.
378 1.1 mrg This provides a substitute. When building apps that reference
379 1.1 mrg gthread_mutex_try_lock, the __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
380 1.1 mrg macro must be defined if Windows95 is a target. Currently
381 1.1 mrg gthread_mutex_try_lock is not referenced by libgcc or libstdc++. */
382 1.1 mrg #ifdef __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
383 1.1 mrg static inline long
384 1.1 mrg __gthr_i486_lock_cmp_xchg(long *__dest, long __xchg, long __comperand)
385 1.1 mrg {
386 1.1 mrg long result;
387 1.1 mrg __asm__ __volatile__ ("\n\
388 1.1 mrg lock\n\
389 1.1 mrg cmpxchg{l} {%4, %1|%1, %4}\n"
390 1.1 mrg : "=a" (result), "=m" (*__dest)
391 1.1 mrg : "0" (__comperand), "m" (*__dest), "r" (__xchg)
392 1.1 mrg : "cc");
393 1.1 mrg return result;
394 1.1 mrg }
395 1.1 mrg #define __GTHR_W32_InterlockedCompareExchange __gthr_i486_lock_cmp_xchg
396 1.1 mrg #else /* __GTHREAD_I486_INLINE_LOCK_PRIMITIVES */
397 1.1 mrg #define __GTHR_W32_InterlockedCompareExchange InterlockedCompareExchange
398 1.1 mrg #endif /* __GTHREAD_I486_INLINE_LOCK_PRIMITIVES */
399 1.1 mrg
400 1.1 mrg static inline int
401 1.1 mrg __gthread_active_p (void)
402 1.1 mrg {
403 1.1 mrg #ifdef MINGW32_SUPPORTS_MT_EH
404 1.1 mrg return _CRT_MT;
405 1.1 mrg #else
406 1.1 mrg return 1;
407 1.1 mrg #endif
408 1.1 mrg }
409 1.1 mrg
410 1.1 mrg #if __GTHREAD_HIDE_WIN32API
411 1.1 mrg
412 1.1 mrg /* The implementations are in config/i386/gthr-win32.c in libgcc.a.
413 1.1 mrg Only stubs are exposed to avoid polluting the C++ namespace with
414 1.1 mrg windows api definitions. */
415 1.1 mrg
416 1.1 mrg extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
417 1.1 mrg extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
418 1.1 mrg extern int __gthr_win32_key_delete (__gthread_key_t);
419 1.1 mrg extern void * __gthr_win32_getspecific (__gthread_key_t);
420 1.1 mrg extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
421 1.1 mrg extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
422 1.1 mrg extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
423 1.1 mrg extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
424 1.1 mrg extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
425 1.1 mrg extern void
426 1.1 mrg __gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *);
427 1.1 mrg extern int __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *);
428 1.1 mrg extern int
429 1.1 mrg __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
430 1.1 mrg extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *);
431 1.1 mrg extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *);
432 1.1 mrg extern int
433 1.1 mrg __gthr_win32_recursive_mutex_destroy (__gthread_recursive_mutex_t *);
434 1.1 mrg
435 1.1 mrg static inline int
436 1.1 mrg __gthread_once (__gthread_once_t *__once, void (*__func) (void))
437 1.1 mrg {
438 1.1 mrg if (__gthread_active_p ())
439 1.1 mrg return __gthr_win32_once (__once, __func);
440 1.1 mrg else
441 1.1 mrg return -1;
442 1.1 mrg }
443 1.1 mrg
444 1.1 mrg static inline int
445 1.1 mrg __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
446 1.1 mrg {
447 1.1 mrg return __gthr_win32_key_create (__key, __dtor);
448 1.1 mrg }
449 1.1 mrg
450 1.1 mrg static inline int
451 1.1 mrg __gthread_key_delete (__gthread_key_t __key)
452 1.1 mrg {
453 1.1 mrg return __gthr_win32_key_delete (__key);
454 1.1 mrg }
455 1.1 mrg
456 1.1 mrg static inline void *
457 1.1 mrg __gthread_getspecific (__gthread_key_t __key)
458 1.1 mrg {
459 1.1 mrg return __gthr_win32_getspecific (__key);
460 1.1 mrg }
461 1.1 mrg
462 1.1 mrg static inline int
463 1.1 mrg __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
464 1.1 mrg {
465 1.1 mrg return __gthr_win32_setspecific (__key, __ptr);
466 1.1 mrg }
467 1.1 mrg
468 1.1 mrg static inline void
469 1.1 mrg __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
470 1.1 mrg {
471 1.1 mrg __gthr_win32_mutex_init_function (__mutex);
472 1.1 mrg }
473 1.1 mrg
474 1.1 mrg static inline void
475 1.1 mrg __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
476 1.1 mrg {
477 1.1 mrg __gthr_win32_mutex_destroy (__mutex);
478 1.1 mrg }
479 1.1 mrg
480 1.1 mrg static inline int
481 1.1 mrg __gthread_mutex_lock (__gthread_mutex_t *__mutex)
482 1.1 mrg {
483 1.1 mrg if (__gthread_active_p ())
484 1.1 mrg return __gthr_win32_mutex_lock (__mutex);
485 1.1 mrg else
486 1.1 mrg return 0;
487 1.1 mrg }
488 1.1 mrg
489 1.1 mrg static inline int
490 1.1 mrg __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
491 1.1 mrg {
492 1.1 mrg if (__gthread_active_p ())
493 1.1 mrg return __gthr_win32_mutex_trylock (__mutex);
494 1.1 mrg else
495 1.1 mrg return 0;
496 1.1 mrg }
497 1.1 mrg
498 1.1 mrg static inline int
499 1.1 mrg __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
500 1.1 mrg {
501 1.1 mrg if (__gthread_active_p ())
502 1.1 mrg return __gthr_win32_mutex_unlock (__mutex);
503 1.1 mrg else
504 1.1 mrg return 0;
505 1.1 mrg }
506 1.1 mrg
507 1.1 mrg static inline void
508 1.1 mrg __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
509 1.1 mrg {
510 1.1 mrg __gthr_win32_recursive_mutex_init_function (__mutex);
511 1.1 mrg }
512 1.1 mrg
513 1.1 mrg static inline int
514 1.1 mrg __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
515 1.1 mrg {
516 1.1 mrg if (__gthread_active_p ())
517 1.1 mrg return __gthr_win32_recursive_mutex_lock (__mutex);
518 1.1 mrg else
519 1.1 mrg return 0;
520 1.1 mrg }
521 1.1 mrg
522 1.1 mrg static inline int
523 1.1 mrg __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
524 1.1 mrg {
525 1.1 mrg if (__gthread_active_p ())
526 1.1 mrg return __gthr_win32_recursive_mutex_trylock (__mutex);
527 1.1 mrg else
528 1.1 mrg return 0;
529 1.1 mrg }
530 1.1 mrg
531 1.1 mrg static inline int
532 1.1 mrg __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
533 1.1 mrg {
534 1.1 mrg if (__gthread_active_p ())
535 1.1 mrg return __gthr_win32_recursive_mutex_unlock (__mutex);
536 1.1 mrg else
537 1.1 mrg return 0;
538 1.1 mrg }
539 1.1 mrg
540 1.1 mrg static inline int
541 1.1 mrg __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
542 1.1 mrg {
543 1.1 mrg return __gthr_win32_recursive_mutex_destroy (__mutex);
544 1.1 mrg }
545 1.1 mrg
546 1.1 mrg #else /* ! __GTHREAD_HIDE_WIN32API */
547 1.1 mrg
548 1.1 mrg #include <windows.h>
549 1.1 mrg #include <errno.h>
550 1.1 mrg
551 1.1 mrg static inline int
552 1.1 mrg __gthread_once (__gthread_once_t *__once, void (*__func) (void))
553 1.1 mrg {
554 1.1 mrg if (! __gthread_active_p ())
555 1.1 mrg return -1;
556 1.1 mrg else if (__once == NULL || __func == NULL)
557 1.1 mrg return EINVAL;
558 1.1 mrg
559 1.1 mrg if (! __once->done)
560 1.1 mrg {
561 1.1 mrg if (InterlockedIncrement (&(__once->started)) == 0)
562 1.1 mrg {
563 1.1 mrg (*__func) ();
564 1.1 mrg __once->done = TRUE;
565 1.1 mrg }
566 1.1 mrg else
567 1.1 mrg {
568 1.1 mrg /* Another thread is currently executing the code, so wait for it
569 1.1 mrg to finish; yield the CPU in the meantime. If performance
570 1.1 mrg does become an issue, the solution is to use an Event that
571 1.1 mrg we wait on here (and set above), but that implies a place to
572 1.1 mrg create the event before this routine is called. */
573 1.1 mrg while (! __once->done)
574 1.1 mrg Sleep (0);
575 1.1 mrg }
576 1.1 mrg }
577 1.1 mrg
578 1.1 mrg return 0;
579 1.1 mrg }
580 1.1 mrg
581 1.1 mrg /* Windows32 thread local keys don't support destructors; this leads to
582 1.1 mrg leaks, especially in threaded applications making extensive use of
583 1.1 mrg C++ EH. Mingw uses a thread-support DLL to work-around this problem. */
584 1.1 mrg static inline int
585 1.1 mrg __gthread_key_create (__gthread_key_t *__key,
586 1.3 mrg void (*__dtor) (void *) __attribute__((__unused__)))
587 1.1 mrg {
588 1.1 mrg int __status = 0;
589 1.1 mrg DWORD __tls_index = TlsAlloc ();
590 1.1 mrg if (__tls_index != 0xFFFFFFFF)
591 1.1 mrg {
592 1.1 mrg *__key = __tls_index;
593 1.1 mrg #ifdef MINGW32_SUPPORTS_MT_EH
594 1.1 mrg /* Mingw runtime will run the dtors in reverse order for each thread
595 1.1 mrg when the thread exits. */
596 1.1 mrg __status = __mingwthr_key_dtor (*__key, __dtor);
597 1.1 mrg #endif
598 1.1 mrg }
599 1.1 mrg else
600 1.1 mrg __status = (int) GetLastError ();
601 1.1 mrg return __status;
602 1.1 mrg }
603 1.1 mrg
604 1.1 mrg static inline int
605 1.1 mrg __gthread_key_delete (__gthread_key_t __key)
606 1.1 mrg {
607 1.1 mrg return (TlsFree (__key) != 0) ? 0 : (int) GetLastError ();
608 1.1 mrg }
609 1.1 mrg
610 1.1 mrg static inline void *
611 1.1 mrg __gthread_getspecific (__gthread_key_t __key)
612 1.1 mrg {
613 1.1 mrg DWORD __lasterror;
614 1.1 mrg void *__ptr;
615 1.1 mrg
616 1.1 mrg __lasterror = GetLastError ();
617 1.1 mrg
618 1.1 mrg __ptr = TlsGetValue (__key);
619 1.1 mrg
620 1.1 mrg SetLastError (__lasterror);
621 1.1 mrg
622 1.1 mrg return __ptr;
623 1.1 mrg }
624 1.1 mrg
625 1.1 mrg static inline int
626 1.1 mrg __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
627 1.1 mrg {
628 1.1 mrg if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)) != 0)
629 1.1 mrg return 0;
630 1.1 mrg else
631 1.1 mrg return GetLastError ();
632 1.1 mrg }
633 1.1 mrg
634 1.1 mrg static inline void
635 1.1 mrg __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
636 1.1 mrg {
637 1.1 mrg __mutex->counter = -1;
638 1.3 mrg __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
639 1.1 mrg }
640 1.1 mrg
641 1.1 mrg static inline void
642 1.1 mrg __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
643 1.1 mrg {
644 1.1 mrg CloseHandle ((HANDLE) __mutex->sema);
645 1.1 mrg }
646 1.1 mrg
647 1.1 mrg static inline int
648 1.1 mrg __gthread_mutex_lock (__gthread_mutex_t *__mutex)
649 1.1 mrg {
650 1.1 mrg int __status = 0;
651 1.1 mrg
652 1.1 mrg if (__gthread_active_p ())
653 1.1 mrg {
654 1.1 mrg if (InterlockedIncrement (&__mutex->counter) == 0 ||
655 1.1 mrg WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
656 1.1 mrg __status = 0;
657 1.1 mrg else
658 1.1 mrg {
659 1.1 mrg /* WaitForSingleObject returns WAIT_FAILED, and we can only do
660 1.1 mrg some best-effort cleanup here. */
661 1.1 mrg InterlockedDecrement (&__mutex->counter);
662 1.1 mrg __status = 1;
663 1.1 mrg }
664 1.1 mrg }
665 1.1 mrg return __status;
666 1.1 mrg }
667 1.1 mrg
668 1.1 mrg static inline int
669 1.1 mrg __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
670 1.1 mrg {
671 1.1 mrg int __status = 0;
672 1.1 mrg
673 1.1 mrg if (__gthread_active_p ())
674 1.1 mrg {
675 1.1 mrg if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
676 1.1 mrg __status = 0;
677 1.1 mrg else
678 1.1 mrg __status = 1;
679 1.1 mrg }
680 1.1 mrg return __status;
681 1.1 mrg }
682 1.1 mrg
683 1.1 mrg static inline int
684 1.1 mrg __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
685 1.1 mrg {
686 1.1 mrg if (__gthread_active_p ())
687 1.1 mrg {
688 1.1 mrg if (InterlockedDecrement (&__mutex->counter) >= 0)
689 1.1 mrg return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
690 1.1 mrg }
691 1.1 mrg return 0;
692 1.1 mrg }
693 1.1 mrg
694 1.1 mrg static inline void
695 1.1 mrg __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
696 1.1 mrg {
697 1.1 mrg __mutex->counter = -1;
698 1.1 mrg __mutex->depth = 0;
699 1.1 mrg __mutex->owner = 0;
700 1.3 mrg __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
701 1.1 mrg }
702 1.1 mrg
703 1.1 mrg static inline int
704 1.1 mrg __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
705 1.1 mrg {
706 1.1 mrg if (__gthread_active_p ())
707 1.1 mrg {
708 1.1 mrg DWORD __me = GetCurrentThreadId();
709 1.1 mrg if (InterlockedIncrement (&__mutex->counter) == 0)
710 1.1 mrg {
711 1.1 mrg __mutex->depth = 1;
712 1.1 mrg __mutex->owner = __me;
713 1.1 mrg }
714 1.1 mrg else if (__mutex->owner == __me)
715 1.1 mrg {
716 1.1 mrg InterlockedDecrement (&__mutex->counter);
717 1.1 mrg ++(__mutex->depth);
718 1.1 mrg }
719 1.1 mrg else if (WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
720 1.1 mrg {
721 1.1 mrg __mutex->depth = 1;
722 1.1 mrg __mutex->owner = __me;
723 1.1 mrg }
724 1.1 mrg else
725 1.1 mrg {
726 1.1 mrg /* WaitForSingleObject returns WAIT_FAILED, and we can only do
727 1.1 mrg some best-effort cleanup here. */
728 1.1 mrg InterlockedDecrement (&__mutex->counter);
729 1.1 mrg return 1;
730 1.1 mrg }
731 1.1 mrg }
732 1.1 mrg return 0;
733 1.1 mrg }
734 1.1 mrg
735 1.1 mrg static inline int
736 1.1 mrg __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
737 1.1 mrg {
738 1.1 mrg if (__gthread_active_p ())
739 1.1 mrg {
740 1.1 mrg DWORD __me = GetCurrentThreadId();
741 1.1 mrg if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
742 1.1 mrg {
743 1.1 mrg __mutex->depth = 1;
744 1.1 mrg __mutex->owner = __me;
745 1.1 mrg }
746 1.1 mrg else if (__mutex->owner == __me)
747 1.1 mrg ++(__mutex->depth);
748 1.1 mrg else
749 1.1 mrg return 1;
750 1.1 mrg }
751 1.1 mrg return 0;
752 1.1 mrg }
753 1.1 mrg
754 1.1 mrg static inline int
755 1.1 mrg __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
756 1.1 mrg {
757 1.1 mrg if (__gthread_active_p ())
758 1.1 mrg {
759 1.1 mrg --(__mutex->depth);
760 1.1 mrg if (__mutex->depth == 0)
761 1.1 mrg {
762 1.1 mrg __mutex->owner = 0;
763 1.1 mrg
764 1.1 mrg if (InterlockedDecrement (&__mutex->counter) >= 0)
765 1.1 mrg return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
766 1.1 mrg }
767 1.1 mrg }
768 1.1 mrg return 0;
769 1.1 mrg }
770 1.1 mrg
771 1.1 mrg static inline int
772 1.1 mrg __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
773 1.1 mrg {
774 1.1 mrg CloseHandle ((HANDLE) __mutex->sema);
775 1.1 mrg return 0;
776 1.1 mrg }
777 1.1 mrg
778 1.1 mrg #endif /* __GTHREAD_HIDE_WIN32API */
779 1.1 mrg
780 1.1 mrg #ifdef __cplusplus
781 1.1 mrg }
782 1.1 mrg #endif
783 1.1 mrg
784 1.1 mrg #endif /* _LIBOBJC */
785 1.1 mrg
786 1.1 mrg #endif /* ! GCC_GTHR_WIN32_H */
787