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