>From 4570a616244efbc2fa4bd8788f27ef0e4b48bdbe Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:10:39 +0200 Subject: [PATCH 10/26] 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. --- ChangeLog | 23 +++++++++ lib/glthread/lock.c | 70 -------------------------- lib/glthread/lock.h | 28 +++-------- lib/windows-recmutex.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++ lib/windows-recmutex.h | 57 +++++++++++++++++++++ modules/lock | 5 +- modules/windows-recmutex | 28 +++++++++++ 7 files changed, 245 insertions(+), 93 deletions(-) create mode 100644 lib/windows-recmutex.c create mode 100644 lib/windows-recmutex.h create mode 100644 modules/windows-recmutex diff --git a/ChangeLog b/ChangeLog index a168b23..1ac5490 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,28 @@ 2019-06-20 Bruno Haible + 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 + windows-mutex: New module. * lib/windows-mutex.h: New file, extracted from lib/glthread/lock.h. * lib/windows-mutex.c: New file, extracted from lib/glthread/lock.c. diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c index e17f524..a686a30 100644 --- a/lib/glthread/lock.c +++ b/lib/glthread/lock.c @@ -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 /* ========================================================================= */ diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h index e2a49dc..fb1ebc6 100644 --- a/lib/glthread/lock.h +++ b/lib/glthread/lock.h @@ -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 index 0000000..9629bf4 --- /dev/null +++ b/lib/windows-recmutex.c @@ -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 . */ + +/* Written by Bruno Haible , 2005. + Based on GCC's gthr-win32.h. */ + +#include + +/* Specification. */ +#include "windows-recmutex.h" + +#include + +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 index 0000000..a4fcb47 --- /dev/null +++ b/lib/windows-recmutex.h @@ -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 . */ + +/* Written by Bruno Haible , 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 + +#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 */ diff --git a/modules/lock b/modules/lock index 351e902..0be823c 100644 --- a/modules/lock +++ b/modules/lock @@ -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 index 0000000..f8c0861 --- /dev/null +++ b/modules/windows-recmutex @@ -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 -- 2.7.4