OSDN Git Service

PR c/20740
[pf3gnuchains/gcc-fork.git] / gcc / gthr-win32.h
index b761804..e9daf3d 100644 (file)
@@ -71,7 +71,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #ifdef _LIBOBJC
 
 /* This is necessary to prevent windef.h (included from windows.h) from
-   defining it's own BOOL as a typedef.  */
+   defining its own BOOL as a typedef.  */
 #ifndef __OBJC__
 #define __OBJC__
 #endif
@@ -88,7 +88,7 @@ static DWORD  __gthread_objc_data_tls = (DWORD) -1;
 int
 __gthread_objc_init_thread_system (void)
 {
-  /* Initialize the thread storage key */
+  /* Initialize the thread storage key */
   if ((__gthread_objc_data_tls = TlsAlloc ()) != (DWORD) -1)
     return 0;
   else
@@ -343,9 +343,19 @@ typedef struct {
   void *sema;
 } __gthread_mutex_t;
 
+typedef struct {
+  long counter;
+  long depth;
+  unsigned long owner;
+  void *sema;
+} __gthread_recursive_mutex_t;
+
 #define __GTHREAD_ONCE_INIT {0, -1}
 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
 #define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0}
+#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
+  __gthread_recursive_mutex_init_function
+#define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0}
 
 #if __MINGW32_MAJOR_VERSION >= 1 || \
   (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
@@ -405,6 +415,12 @@ extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
 extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
 extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
 extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
+extern void
+  __gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *);
+extern int __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *);
+extern int
+  __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
+extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *);
 
 static inline int
 __gthread_once (__gthread_once_t *once, void (*func) (void))
@@ -472,6 +488,39 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
     return 0;
 }
 
+static inline void
+__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
+{
+   __gthr_win32_recursive_mutex_init_function (mutex);
+}
+
+static inline int
+__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
+{
+  if (__gthread_active_p ())
+    return __gthr_win32_recursive_mutex_lock (mutex);
+  else
+    return 0;
+}
+
+static inline int
+__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
+{
+  if (__gthread_active_p ())
+    return __gthr_win32_recursive_mutex_trylock (mutex);
+  else
+    return 0;
+}
+
+static inline int
+__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
+{
+  if (__gthread_active_p ())
+    return __gthr_win32_recursive_mutex_unlock (mutex);
+  else
+    return 0;
+}
+
 #else /* ! __GTHREAD_HIDE_WIN32API */
 
 #include <windows.h>
@@ -610,6 +659,83 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
   return 0;
 }
 
+static inline void
+__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
+{
+  mutex->counter = -1;
+  mutex->depth = 0;
+  mutex->owner = 0;
+  mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
+}
+
+static inline int
+__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
+{
+  if (__gthread_active_p ())
+    {
+      DWORD me = GetCurrentThreadId();
+      if (InterlockedIncrement (&mutex->counter) == 0)
+       {
+         mutex->depth = 1;
+         mutex->owner = me;
+       }
+      else if (mutex->owner == me)
+       {
+         InterlockedDecrement (&mutex->counter);
+         ++(mutex->depth);
+       }
+      else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
+       {
+         mutex->depth = 1;
+         mutex->owner = me;
+       }
+      else
+       {
+         /* WaitForSingleObject returns WAIT_FAILED, and we can only do
+            some best-effort cleanup here.  */
+         InterlockedDecrement (&mutex->counter);
+         return 1;
+       }
+    }
+  return 0;
+}
+
+static inline int
+__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
+{
+  if (__gthread_active_p ())
+    {
+      DWORD me = GetCurrentThreadId();
+      if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
+       {
+         mutex->depth = 1;
+         mutex->owner = me;
+       }
+      else if (mutex->owner == me)
+       ++(mutex->depth);
+      else
+       return 1;
+    }
+  return 0;
+}
+
+static inline int
+__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
+{
+  if (__gthread_active_p ())
+    {
+      --(mutex->depth);
+      if (mutex->depth == 0)
+       {
+         mutex->owner = 0;
+
+         if (InterlockedDecrement (&mutex->counter) >= 0)
+           return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
+       }
+    }
+  return 0;
+}
+
 #endif /*  __GTHREAD_HIDE_WIN32API */
 
 #ifdef __cplusplus