Home | History | Annotate | Line # | Download | only in i386
      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.10  mrg /* Copyright (C) 1999-2022 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.10  mrg /* __GTHR_W32_InterlockedCompareExchange is left over from win95,
    378  1.10  mrg    which did not support InterlockedCompareExchange. */
    379   1.1  mrg #define __GTHR_W32_InterlockedCompareExchange InterlockedCompareExchange
    380   1.1  mrg 
    381   1.1  mrg static inline int
    382   1.1  mrg __gthread_active_p (void)
    383   1.1  mrg {
    384   1.1  mrg #ifdef MINGW32_SUPPORTS_MT_EH
    385   1.1  mrg   return _CRT_MT;
    386   1.1  mrg #else
    387   1.1  mrg   return 1;
    388   1.1  mrg #endif
    389   1.1  mrg }
    390   1.1  mrg 
    391   1.1  mrg #if __GTHREAD_HIDE_WIN32API
    392   1.1  mrg 
    393   1.1  mrg /* The implementations are in config/i386/gthr-win32.c in libgcc.a.
    394   1.1  mrg    Only stubs are exposed to avoid polluting the C++ namespace with
    395   1.1  mrg    windows api definitions.  */
    396   1.1  mrg 
    397   1.1  mrg extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
    398   1.1  mrg extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
    399   1.1  mrg extern int __gthr_win32_key_delete (__gthread_key_t);
    400   1.1  mrg extern void * __gthr_win32_getspecific (__gthread_key_t);
    401   1.1  mrg extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
    402   1.1  mrg extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
    403   1.1  mrg extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
    404   1.1  mrg extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
    405   1.1  mrg extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
    406   1.1  mrg extern void
    407   1.1  mrg   __gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *);
    408   1.1  mrg extern int __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *);
    409   1.1  mrg extern int
    410   1.1  mrg   __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
    411   1.1  mrg extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *);
    412   1.1  mrg extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *);
    413   1.1  mrg extern int
    414   1.1  mrg   __gthr_win32_recursive_mutex_destroy (__gthread_recursive_mutex_t *);
    415   1.1  mrg 
    416   1.1  mrg static inline int
    417   1.1  mrg __gthread_once (__gthread_once_t *__once, void (*__func) (void))
    418   1.1  mrg {
    419   1.1  mrg   if (__gthread_active_p ())
    420   1.1  mrg     return __gthr_win32_once (__once, __func);
    421   1.1  mrg   else
    422   1.1  mrg     return -1;
    423   1.1  mrg }
    424   1.1  mrg 
    425   1.1  mrg static inline int
    426   1.1  mrg __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
    427   1.1  mrg {
    428   1.1  mrg   return __gthr_win32_key_create (__key, __dtor);
    429   1.1  mrg }
    430   1.1  mrg 
    431   1.1  mrg static inline int
    432   1.1  mrg __gthread_key_delete (__gthread_key_t __key)
    433   1.1  mrg {
    434   1.1  mrg   return __gthr_win32_key_delete (__key);
    435   1.1  mrg }
    436   1.1  mrg 
    437   1.1  mrg static inline void *
    438   1.1  mrg __gthread_getspecific (__gthread_key_t __key)
    439   1.1  mrg {
    440   1.1  mrg   return __gthr_win32_getspecific (__key);
    441   1.1  mrg }
    442   1.1  mrg 
    443   1.1  mrg static inline int
    444   1.1  mrg __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
    445   1.1  mrg {
    446   1.1  mrg   return __gthr_win32_setspecific (__key, __ptr);
    447   1.1  mrg }
    448   1.1  mrg 
    449   1.1  mrg static inline void
    450   1.1  mrg __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
    451   1.1  mrg {
    452   1.1  mrg   __gthr_win32_mutex_init_function (__mutex);
    453   1.1  mrg }
    454   1.1  mrg 
    455   1.1  mrg static inline void
    456   1.1  mrg __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
    457   1.1  mrg {
    458   1.1  mrg   __gthr_win32_mutex_destroy (__mutex);
    459   1.1  mrg }
    460   1.1  mrg 
    461   1.1  mrg static inline int
    462   1.1  mrg __gthread_mutex_lock (__gthread_mutex_t *__mutex)
    463   1.1  mrg {
    464   1.1  mrg   if (__gthread_active_p ())
    465   1.1  mrg     return __gthr_win32_mutex_lock (__mutex);
    466   1.1  mrg   else
    467   1.1  mrg     return 0;
    468   1.1  mrg }
    469   1.1  mrg 
    470   1.1  mrg static inline int
    471   1.1  mrg __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
    472   1.1  mrg {
    473   1.1  mrg   if (__gthread_active_p ())
    474   1.1  mrg     return __gthr_win32_mutex_trylock (__mutex);
    475   1.1  mrg   else
    476   1.1  mrg     return 0;
    477   1.1  mrg }
    478   1.1  mrg 
    479   1.1  mrg static inline int
    480   1.1  mrg __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
    481   1.1  mrg {
    482   1.1  mrg   if (__gthread_active_p ())
    483   1.1  mrg     return __gthr_win32_mutex_unlock (__mutex);
    484   1.1  mrg   else
    485   1.1  mrg     return 0;
    486   1.1  mrg }
    487   1.1  mrg 
    488   1.1  mrg static inline void
    489   1.1  mrg __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
    490   1.1  mrg {
    491   1.1  mrg    __gthr_win32_recursive_mutex_init_function (__mutex);
    492   1.1  mrg }
    493   1.1  mrg 
    494   1.1  mrg static inline int
    495   1.1  mrg __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
    496   1.1  mrg {
    497   1.1  mrg   if (__gthread_active_p ())
    498   1.1  mrg     return __gthr_win32_recursive_mutex_lock (__mutex);
    499   1.1  mrg   else
    500   1.1  mrg     return 0;
    501   1.1  mrg }
    502   1.1  mrg 
    503   1.1  mrg static inline int
    504   1.1  mrg __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
    505   1.1  mrg {
    506   1.1  mrg   if (__gthread_active_p ())
    507   1.1  mrg     return __gthr_win32_recursive_mutex_trylock (__mutex);
    508   1.1  mrg   else
    509   1.1  mrg     return 0;
    510   1.1  mrg }
    511   1.1  mrg 
    512   1.1  mrg static inline int
    513   1.1  mrg __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
    514   1.1  mrg {
    515   1.1  mrg   if (__gthread_active_p ())
    516   1.1  mrg     return __gthr_win32_recursive_mutex_unlock (__mutex);
    517   1.1  mrg   else
    518   1.1  mrg     return 0;
    519   1.1  mrg }
    520   1.1  mrg 
    521   1.1  mrg static inline int
    522   1.1  mrg __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
    523   1.1  mrg {
    524   1.1  mrg   return __gthr_win32_recursive_mutex_destroy (__mutex);
    525   1.1  mrg }
    526   1.1  mrg 
    527   1.1  mrg #else /* ! __GTHREAD_HIDE_WIN32API */
    528   1.1  mrg 
    529   1.6  mrg #define NOGDI
    530   1.1  mrg #include <windows.h>
    531   1.1  mrg #include <errno.h>
    532   1.1  mrg 
    533   1.1  mrg static inline int
    534   1.1  mrg __gthread_once (__gthread_once_t *__once, void (*__func) (void))
    535   1.1  mrg {
    536   1.1  mrg   if (! __gthread_active_p ())
    537   1.1  mrg     return -1;
    538   1.1  mrg   else if (__once == NULL || __func == NULL)
    539   1.1  mrg     return EINVAL;
    540   1.1  mrg 
    541   1.1  mrg   if (! __once->done)
    542   1.1  mrg     {
    543   1.1  mrg       if (InterlockedIncrement (&(__once->started)) == 0)
    544   1.1  mrg 	{
    545   1.1  mrg 	  (*__func) ();
    546   1.1  mrg 	  __once->done = TRUE;
    547   1.1  mrg 	}
    548   1.1  mrg       else
    549   1.1  mrg 	{
    550   1.1  mrg 	  /* Another thread is currently executing the code, so wait for it
    551   1.1  mrg 	     to finish; yield the CPU in the meantime.  If performance
    552   1.1  mrg 	     does become an issue, the solution is to use an Event that
    553   1.1  mrg 	     we wait on here (and set above), but that implies a place to
    554   1.1  mrg 	     create the event before this routine is called.  */
    555   1.1  mrg 	  while (! __once->done)
    556   1.1  mrg 	    Sleep (0);
    557   1.1  mrg 	}
    558   1.1  mrg     }
    559   1.1  mrg 
    560   1.1  mrg   return 0;
    561   1.1  mrg }
    562   1.1  mrg 
    563   1.1  mrg /* Windows32 thread local keys don't support destructors; this leads to
    564   1.1  mrg    leaks, especially in threaded applications making extensive use of
    565   1.1  mrg    C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
    566   1.1  mrg static inline int
    567   1.1  mrg __gthread_key_create (__gthread_key_t *__key,
    568   1.3  mrg 		      void (*__dtor) (void *) __attribute__((__unused__)))
    569   1.1  mrg {
    570   1.1  mrg   int __status = 0;
    571   1.1  mrg   DWORD __tls_index = TlsAlloc ();
    572   1.1  mrg   if (__tls_index != 0xFFFFFFFF)
    573   1.1  mrg     {
    574   1.1  mrg       *__key = __tls_index;
    575   1.1  mrg #ifdef MINGW32_SUPPORTS_MT_EH
    576   1.1  mrg       /* Mingw runtime will run the dtors in reverse order for each thread
    577   1.1  mrg          when the thread exits.  */
    578   1.1  mrg       __status = __mingwthr_key_dtor (*__key, __dtor);
    579   1.1  mrg #endif
    580   1.1  mrg     }
    581   1.1  mrg   else
    582   1.1  mrg     __status = (int) GetLastError ();
    583   1.1  mrg   return __status;
    584   1.1  mrg }
    585   1.1  mrg 
    586   1.1  mrg static inline int
    587   1.1  mrg __gthread_key_delete (__gthread_key_t __key)
    588   1.1  mrg {
    589   1.1  mrg   return (TlsFree (__key) != 0) ? 0 : (int) GetLastError ();
    590   1.1  mrg }
    591   1.1  mrg 
    592   1.1  mrg static inline void *
    593   1.1  mrg __gthread_getspecific (__gthread_key_t __key)
    594   1.1  mrg {
    595   1.1  mrg   DWORD __lasterror;
    596   1.1  mrg   void *__ptr;
    597   1.1  mrg 
    598   1.1  mrg   __lasterror = GetLastError ();
    599   1.1  mrg 
    600   1.1  mrg   __ptr = TlsGetValue (__key);
    601   1.1  mrg 
    602   1.1  mrg   SetLastError (__lasterror);
    603   1.1  mrg 
    604   1.1  mrg   return __ptr;
    605   1.1  mrg }
    606   1.1  mrg 
    607   1.1  mrg static inline int
    608   1.1  mrg __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
    609   1.1  mrg {
    610   1.1  mrg   if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)) != 0)
    611   1.1  mrg     return 0;
    612   1.1  mrg   else
    613   1.1  mrg     return GetLastError ();
    614   1.1  mrg }
    615   1.1  mrg 
    616   1.1  mrg static inline void
    617   1.1  mrg __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
    618   1.1  mrg {
    619   1.1  mrg   __mutex->counter = -1;
    620   1.3  mrg   __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
    621   1.1  mrg }
    622   1.1  mrg 
    623   1.1  mrg static inline void
    624   1.1  mrg __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
    625   1.1  mrg {
    626   1.1  mrg   CloseHandle ((HANDLE) __mutex->sema);
    627   1.1  mrg }
    628   1.1  mrg 
    629   1.1  mrg static inline int
    630   1.1  mrg __gthread_mutex_lock (__gthread_mutex_t *__mutex)
    631   1.1  mrg {
    632   1.1  mrg   int __status = 0;
    633   1.1  mrg 
    634   1.1  mrg   if (__gthread_active_p ())
    635   1.1  mrg     {
    636   1.1  mrg       if (InterlockedIncrement (&__mutex->counter) == 0 ||
    637   1.1  mrg 	  WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
    638   1.1  mrg 	__status = 0;
    639   1.1  mrg       else
    640   1.1  mrg 	{
    641   1.1  mrg 	  /* WaitForSingleObject returns WAIT_FAILED, and we can only do
    642   1.1  mrg 	     some best-effort cleanup here.  */
    643   1.1  mrg 	  InterlockedDecrement (&__mutex->counter);
    644   1.1  mrg 	  __status = 1;
    645   1.1  mrg 	}
    646   1.1  mrg     }
    647   1.1  mrg   return __status;
    648   1.1  mrg }
    649   1.1  mrg 
    650   1.1  mrg static inline int
    651   1.1  mrg __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
    652   1.1  mrg {
    653   1.1  mrg   int __status = 0;
    654   1.1  mrg 
    655   1.1  mrg   if (__gthread_active_p ())
    656   1.1  mrg     {
    657   1.1  mrg       if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
    658   1.1  mrg 	__status = 0;
    659   1.1  mrg       else
    660   1.1  mrg 	__status = 1;
    661   1.1  mrg     }
    662   1.1  mrg   return __status;
    663   1.1  mrg }
    664   1.1  mrg 
    665   1.1  mrg static inline int
    666   1.1  mrg __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
    667   1.1  mrg {
    668   1.1  mrg   if (__gthread_active_p ())
    669   1.1  mrg     {
    670   1.1  mrg       if (InterlockedDecrement (&__mutex->counter) >= 0)
    671   1.1  mrg 	return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
    672   1.1  mrg     }
    673   1.1  mrg   return 0;
    674   1.1  mrg }
    675   1.1  mrg 
    676   1.1  mrg static inline void
    677   1.1  mrg __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
    678   1.1  mrg {
    679   1.1  mrg   __mutex->counter = -1;
    680   1.1  mrg   __mutex->depth = 0;
    681   1.1  mrg   __mutex->owner = 0;
    682   1.3  mrg   __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
    683   1.1  mrg }
    684   1.1  mrg 
    685   1.1  mrg static inline int
    686   1.1  mrg __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
    687   1.1  mrg {
    688   1.1  mrg   if (__gthread_active_p ())
    689   1.1  mrg     {
    690   1.1  mrg       DWORD __me = GetCurrentThreadId();
    691   1.1  mrg       if (InterlockedIncrement (&__mutex->counter) == 0)
    692   1.1  mrg 	{
    693   1.1  mrg 	  __mutex->depth = 1;
    694   1.1  mrg 	  __mutex->owner = __me;
    695   1.1  mrg 	}
    696   1.1  mrg       else if (__mutex->owner == __me)
    697   1.1  mrg 	{
    698   1.1  mrg 	  InterlockedDecrement (&__mutex->counter);
    699   1.1  mrg 	  ++(__mutex->depth);
    700   1.1  mrg 	}
    701   1.1  mrg       else if (WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
    702   1.1  mrg 	{
    703   1.1  mrg 	  __mutex->depth = 1;
    704   1.1  mrg 	  __mutex->owner = __me;
    705   1.1  mrg 	}
    706   1.1  mrg       else
    707   1.1  mrg 	{
    708   1.1  mrg 	  /* WaitForSingleObject returns WAIT_FAILED, and we can only do
    709   1.1  mrg 	     some best-effort cleanup here.  */
    710   1.1  mrg 	  InterlockedDecrement (&__mutex->counter);
    711   1.1  mrg 	  return 1;
    712   1.1  mrg 	}
    713   1.1  mrg     }
    714   1.1  mrg   return 0;
    715   1.1  mrg }
    716   1.1  mrg 
    717   1.1  mrg static inline int
    718   1.1  mrg __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
    719   1.1  mrg {
    720   1.1  mrg   if (__gthread_active_p ())
    721   1.1  mrg     {
    722   1.1  mrg       DWORD __me = GetCurrentThreadId();
    723   1.1  mrg       if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
    724   1.1  mrg 	{
    725   1.1  mrg 	  __mutex->depth = 1;
    726   1.1  mrg 	  __mutex->owner = __me;
    727   1.1  mrg 	}
    728   1.1  mrg       else if (__mutex->owner == __me)
    729   1.1  mrg 	++(__mutex->depth);
    730   1.1  mrg       else
    731   1.1  mrg 	return 1;
    732   1.1  mrg     }
    733   1.1  mrg   return 0;
    734   1.1  mrg }
    735   1.1  mrg 
    736   1.1  mrg static inline int
    737   1.1  mrg __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
    738   1.1  mrg {
    739   1.1  mrg   if (__gthread_active_p ())
    740   1.1  mrg     {
    741   1.1  mrg       --(__mutex->depth);
    742   1.1  mrg       if (__mutex->depth == 0)
    743   1.1  mrg 	{
    744   1.1  mrg 	  __mutex->owner = 0;
    745   1.1  mrg 
    746   1.1  mrg 	  if (InterlockedDecrement (&__mutex->counter) >= 0)
    747   1.1  mrg 	    return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
    748   1.1  mrg 	}
    749   1.1  mrg     }
    750   1.1  mrg   return 0;
    751   1.1  mrg }
    752   1.1  mrg 
    753   1.1  mrg static inline int
    754   1.1  mrg __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
    755   1.1  mrg {
    756   1.1  mrg   CloseHandle ((HANDLE) __mutex->sema);
    757   1.1  mrg   return 0;
    758   1.1  mrg }
    759   1.1  mrg 
    760   1.1  mrg #endif /*  __GTHREAD_HIDE_WIN32API */
    761   1.1  mrg 
    762   1.1  mrg #ifdef __cplusplus
    763   1.1  mrg }
    764   1.1  mrg #endif
    765   1.1  mrg 
    766   1.1  mrg #endif /* _LIBOBJC */
    767   1.1  mrg 
    768   1.1  mrg #endif /* ! GCC_GTHR_WIN32_H */
    769