OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [gthr-win32.h] - Blame information for rev 294

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.