windows-recmutex: New module.
authorBruno Haible <bruno@clisp.org>
Thu, 20 Jun 2019 02:10:39 +0000 (04:10 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 20 Jun 2019 02:11:36 +0000 (04:11 +0200)
* lib/windows-recmutex.h: New file, extracted from lib/glthread/lock.h.
* lib/windows-recmutex.c: New file, extracted from lib/glthread/lock.c.
* lib/glthread/lock.h: Include windows-recmutex.h.
(gl_recursive_lock_t): Define using glwthread_recmutex_t.
(gl_recursive_lock_initializer): Define using GLWTHREAD_RECMUTEX_INIT.
(glthread_recursive_lock_init): Define using glwthread_recmutex_init.
(glthread_recursive_lock_lock): Define using glwthread_recmutex_lock.
(glthread_recursive_lock_unlock): Define using
glwthread_recmutex_unlock.
(glthread_recursive_lock_destroy): Define using
glwthread_recmutex_destroy.
(glthread_recursive_lock_init_func, glthread_recursive_lock_lock_func,
glthread_recursive_lock_unlock_func,
glthread_recursive_lock_destroy_func): Remove declarations.
* lib/glthread/lock.c (glthread_recursive_lock_init_func,
glthread_recursive_lock_lock_func, glthread_recursive_lock_unlock_func,
glthread_recursive_lock_destroy_func): Remove functions.
* modules/windows-recmutex: New file.
* modules/lock (Depends-on): Add windows-recmutex.

ChangeLog
lib/glthread/lock.c
lib/glthread/lock.h
lib/windows-recmutex.c [new file with mode: 0644]
lib/windows-recmutex.h [new file with mode: 0644]
modules/lock
modules/windows-recmutex [new file with mode: 0644]

index a168b238bca8b3fb7bd80d91c052dfdfdd76b5d8..1ac54909928662148cad644eeed7a45fd45e1a08 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2019-06-20  Bruno Haible  <bruno@clisp.org>
+
+       windows-recmutex: New module.
+       * lib/windows-recmutex.h: New file, extracted from lib/glthread/lock.h.
+       * lib/windows-recmutex.c: New file, extracted from lib/glthread/lock.c.
+       * lib/glthread/lock.h: Include windows-recmutex.h.
+       (gl_recursive_lock_t): Define using glwthread_recmutex_t.
+       (gl_recursive_lock_initializer): Define using GLWTHREAD_RECMUTEX_INIT.
+       (glthread_recursive_lock_init): Define using glwthread_recmutex_init.
+       (glthread_recursive_lock_lock): Define using glwthread_recmutex_lock.
+       (glthread_recursive_lock_unlock): Define using
+       glwthread_recmutex_unlock.
+       (glthread_recursive_lock_destroy): Define using
+       glwthread_recmutex_destroy.
+       (glthread_recursive_lock_init_func, glthread_recursive_lock_lock_func,
+       glthread_recursive_lock_unlock_func,
+       glthread_recursive_lock_destroy_func): Remove declarations.
+       * lib/glthread/lock.c (glthread_recursive_lock_init_func,
+       glthread_recursive_lock_lock_func, glthread_recursive_lock_unlock_func,
+       glthread_recursive_lock_destroy_func): Remove functions.
+       * modules/windows-recmutex: New file.
+       * modules/lock (Depends-on): Add windows-recmutex.
+
 2019-06-20  Bruno Haible  <bruno@clisp.org>
 
        windows-mutex: New module.
index e17f524ca15241ffba5b7ea85445930e944b2893..a686a306d613458cecbae0db333ed693d19009ed 100644 (file)
@@ -1073,76 +1073,6 @@ glthread_rwlock_destroy_func (gl_rwlock_t *lock)
   return 0;
 }
 
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-void
-glthread_recursive_lock_init_func (gl_recursive_lock_t *lock)
-{
-  lock->owner = 0;
-  lock->depth = 0;
-  InitializeCriticalSection (&lock->lock);
-  lock->guard.done = 1;
-}
-
-int
-glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock)
-{
-  if (!lock->guard.done)
-    {
-      if (InterlockedIncrement (&lock->guard.started) == 0)
-        /* This thread is the first one to need this lock.  Initialize it.  */
-        glthread_recursive_lock_init (lock);
-      else
-        {
-          /* Don't let lock->guard.started grow and wrap around.  */
-          InterlockedDecrement (&lock->guard.started);
-          /* Yield the CPU while waiting for another thread to finish
-             initializing this lock.  */
-          while (!lock->guard.done)
-            Sleep (0);
-        }
-    }
-  {
-    DWORD self = GetCurrentThreadId ();
-    if (lock->owner != self)
-      {
-        EnterCriticalSection (&lock->lock);
-        lock->owner = self;
-      }
-    if (++(lock->depth) == 0) /* wraparound? */
-      {
-        lock->depth--;
-        return EAGAIN;
-      }
-  }
-  return 0;
-}
-
-int
-glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock)
-{
-  if (lock->owner != GetCurrentThreadId ())
-    return EPERM;
-  if (lock->depth == 0)
-    return EINVAL;
-  if (--(lock->depth) == 0)
-    {
-      lock->owner = 0;
-      LeaveCriticalSection (&lock->lock);
-    }
-  return 0;
-}
-
-int
-glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock)
-{
-  if (lock->owner != 0)
-    return EBUSY;
-  DeleteCriticalSection (&lock->lock);
-  lock->guard.done = 0;
-  return 0;
-}
-
 #endif
 
 /* ========================================================================= */
index e2a49dcec77e7b4dc82724620ee05dd305d1377b..fb1ebc636269e04bea7571b5f1ef4d50ff584e11 100644 (file)
@@ -692,6 +692,7 @@ extern int glthread_once_singlethreaded (gl_once_t *once_control);
 
 # include "windows-spinlock.h"
 # include "windows-mutex.h"
+# include "windows-recmutex.h"
 # include "windows-once.h"
 
 # ifdef __cplusplus
@@ -774,36 +775,21 @@ extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
 
 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 
-/* The native Windows documentation says that CRITICAL_SECTION already
-   implements a recursive lock.  But we need not rely on it: It's easy to
-   implement a recursive lock without this assumption.  */
-
-typedef struct
-        {
-          glwthread_spinlock_t guard; /* protects the initialization */
-          DWORD owner;
-          unsigned long depth;
-          CRITICAL_SECTION lock;
-        }
-        gl_recursive_lock_t;
+typedef glwthread_recmutex_t gl_recursive_lock_t;
 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_recursive_lock_t NAME;
 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
 # define gl_recursive_lock_initializer \
-    { GLWTHREAD_SPINLOCK_INIT, 0, 0 }
+    GLWTHREAD_RECMUTEX_INIT
 # define glthread_recursive_lock_init(LOCK) \
-    (glthread_recursive_lock_init_func (LOCK), 0)
+    (glwthread_recmutex_init (LOCK), 0)
 # define glthread_recursive_lock_lock(LOCK) \
-    glthread_recursive_lock_lock_func (LOCK)
+    glwthread_recmutex_lock (LOCK)
 # define glthread_recursive_lock_unlock(LOCK) \
-    glthread_recursive_lock_unlock_func (LOCK)
+    glwthread_recmutex_unlock (LOCK)
 # define glthread_recursive_lock_destroy(LOCK) \
-    glthread_recursive_lock_destroy_func (LOCK)
-extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock);
+    glwthread_recmutex_destroy (LOCK)
 
 /* -------------------------- gl_once_t datatype -------------------------- */
 
diff --git a/lib/windows-recmutex.c b/lib/windows-recmutex.c
new file mode 100644 (file)
index 0000000..9629bf4
--- /dev/null
@@ -0,0 +1,127 @@
+/* Plain recursive mutexes (native Windows implementation).
+   Copyright (C) 2005-2019 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+   Based on GCC's gthr-win32.h.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "windows-recmutex.h"
+
+#include <errno.h>
+
+void
+glwthread_recmutex_init (glwthread_recmutex_t *mutex)
+{
+  mutex->owner = 0;
+  mutex->depth = 0;
+  InitializeCriticalSection (&mutex->lock);
+  mutex->guard.done = 1;
+}
+
+int
+glwthread_recmutex_lock (glwthread_recmutex_t *mutex)
+{
+  if (!mutex->guard.done)
+    {
+      if (InterlockedIncrement (&mutex->guard.started) == 0)
+        /* This thread is the first one to need this mutex.  Initialize it.  */
+        glwthread_recmutex_init (mutex);
+      else
+        {
+          /* Don't let mutex->guard.started grow and wrap around.  */
+          InterlockedDecrement (&mutex->guard.started);
+          /* Yield the CPU while waiting for another thread to finish
+             initializing this mutex.  */
+          while (!mutex->guard.done)
+            Sleep (0);
+        }
+    }
+  {
+    DWORD self = GetCurrentThreadId ();
+    if (mutex->owner != self)
+      {
+        EnterCriticalSection (&mutex->lock);
+        mutex->owner = self;
+      }
+    if (++(mutex->depth) == 0) /* wraparound? */
+      {
+        mutex->depth--;
+        return EAGAIN;
+      }
+  }
+  return 0;
+}
+
+int
+glwthread_recmutex_trylock (glwthread_recmutex_t *mutex)
+{
+  if (!mutex->guard.done)
+    {
+      if (InterlockedIncrement (&mutex->guard.started) == 0)
+        /* This thread is the first one to need this mutex.  Initialize it.  */
+        glwthread_recmutex_init (mutex);
+      else
+        {
+          /* Don't let mutex->guard.started grow and wrap around.  */
+          InterlockedDecrement (&mutex->guard.started);
+          /* Let another thread finish initializing this mutex, and let it also
+             lock this mutex.  */
+          return EBUSY;
+        }
+    }
+  {
+    DWORD self = GetCurrentThreadId ();
+    if (mutex->owner != self)
+      {
+        if (!TryEnterCriticalSection (&mutex->lock))
+          return EBUSY;
+        mutex->owner = self;
+      }
+    if (++(mutex->depth) == 0) /* wraparound? */
+      {
+        mutex->depth--;
+        return EAGAIN;
+      }
+  }
+  return 0;
+}
+
+int
+glwthread_recmutex_unlock (glwthread_recmutex_t *mutex)
+{
+  if (mutex->owner != GetCurrentThreadId ())
+    return EPERM;
+  if (mutex->depth == 0)
+    return EINVAL;
+  if (--(mutex->depth) == 0)
+    {
+      mutex->owner = 0;
+      LeaveCriticalSection (&mutex->lock);
+    }
+  return 0;
+}
+
+int
+glwthread_recmutex_destroy (glwthread_recmutex_t *mutex)
+{
+  if (mutex->owner != 0)
+    return EBUSY;
+  DeleteCriticalSection (&mutex->lock);
+  mutex->guard.done = 0;
+  return 0;
+}
diff --git a/lib/windows-recmutex.h b/lib/windows-recmutex.h
new file mode 100644 (file)
index 0000000..a4fcb47
--- /dev/null
@@ -0,0 +1,57 @@
+/* Plain recursive mutexes (native Windows implementation).
+   Copyright (C) 2005-2019 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+   Based on GCC's gthr-win32.h.  */
+
+#ifndef _WINDOWS_RECMUTEX_H
+#define _WINDOWS_RECMUTEX_H
+
+#define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+#include <windows.h>
+
+#include "windows-spinlock.h"
+
+/* The native Windows documentation says that CRITICAL_SECTION already
+   implements a recursive lock.  But we need not rely on it: It's easy to
+   implement a recursive lock without this assumption.  */
+
+typedef struct
+        {
+          glwthread_spinlock_t guard; /* protects the initialization */
+          DWORD owner;
+          unsigned long depth;
+          CRITICAL_SECTION lock;
+        }
+        glwthread_recmutex_t;
+
+#define GLWTHREAD_RECMUTEX_INIT { GLWTHREAD_SPINLOCK_INIT, 0, 0 }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void glwthread_recmutex_init (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_lock (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_trylock (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_unlock (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_destroy (glwthread_recmutex_t *mutex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WINDOWS_RECMUTEX_H */
index 351e902bc98134e11579e298647249fcd147c103..0be823c76b8862297d4668815a304450503b81a1 100644 (file)
@@ -10,8 +10,9 @@ m4/pthread_rwlock_rdlock.m4
 Depends-on:
 extensions
 threadlib
-windows-mutex   [test $gl_threads_api = windows]
-windows-once    [test $gl_threads_api = windows]
+windows-mutex    [test $gl_threads_api = windows]
+windows-recmutex [test $gl_threads_api = windows]
+windows-once     [test $gl_threads_api = windows]
 
 configure.ac:
 gl_LOCK
diff --git a/modules/windows-recmutex b/modules/windows-recmutex
new file mode 100644 (file)
index 0000000..f8c0861
--- /dev/null
@@ -0,0 +1,28 @@
+Description:
+Plain recursive mutexes (native Windows implementation).
+
+Files:
+lib/windows-recmutex.h
+lib/windows-recmutex.c
+lib/windows-spinlock.h
+
+Depends-on:
+
+configure.ac:
+AC_REQUIRE([AC_CANONICAL_HOST])
+case "$host_os" in
+  mingw*)
+    AC_LIBOBJ([windows-recmutex])
+    ;;
+esac
+
+Makefile.am:
+
+Include:
+"windows-recmutex.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all