>From 2535ce3ac9fdd46ec44b0fa5f1e4f6dcaaaebd99 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:08:16 +0200 Subject: [PATCH 09/26] 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. * lib/windows-spinlock.h: New file, extracted from lib/glthread/lock.h. * lib/glthread/lock.h: Include windows-spinlock.h, windows-mutex.h. (gl_spinlock_t): Remove type. (gl_lock_t): Define using glwthread_mutex_t. (gl_lock_initializer): Define using GLWTHREAD_MUTEX_INIT. (glthread_lock_init): Define using glwthread_mutex_init. (glthread_lock_lock): Define using glwthread_mutex_lock. (glthread_lock_unlock): Define using glwthread_mutex_unlock. (glthread_lock_destroy): Define using glwthread_mutex_destroy. (glthread_lock_init_func, glthread_lock_lock_func, glthread_lock_unlock_func, glthread_lock_destroy_func): Remove declarations. Use glwthread_spinlock_t instead of gl_spinlock_t. (gl_rwlock_initializer, gl_recursive_lock_initializer): Define using GLWTHREAD_SPINLOCK_INIT. * lib/glthread/lock.c (glthread_lock_init_func, glthread_lock_lock_func, glthread_lock_unlock_func, glthread_lock_destroy_func): Remove functions. * lib/glthread/cond.h: Use glwthread_spinlock_t instead of gl_spinlock_t. * modules/windows-mutex: New file. * modules/lock (Depends-on): Add windows-mutex. --- ChangeLog | 28 +++++++++++++++ lib/glthread/cond.h | 2 +- lib/glthread/lock.c | 50 -------------------------- lib/glthread/lock.h | 33 +++++++----------- lib/windows-mutex.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/windows-mutex.h | 51 +++++++++++++++++++++++++++ lib/windows-spinlock.h | 35 +++++++++++++++++++ modules/lock | 1 + modules/windows-mutex | 28 +++++++++++++++ 9 files changed, 251 insertions(+), 72 deletions(-) create mode 100644 lib/windows-mutex.c create mode 100644 lib/windows-mutex.h create mode 100644 lib/windows-spinlock.h create mode 100644 modules/windows-mutex diff --git a/ChangeLog b/ChangeLog index 06474ea..a168b23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,33 @@ 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. + * lib/windows-spinlock.h: New file, extracted from lib/glthread/lock.h. + * lib/glthread/lock.h: Include windows-spinlock.h, windows-mutex.h. + (gl_spinlock_t): Remove type. + (gl_lock_t): Define using glwthread_mutex_t. + (gl_lock_initializer): Define using GLWTHREAD_MUTEX_INIT. + (glthread_lock_init): Define using glwthread_mutex_init. + (glthread_lock_lock): Define using glwthread_mutex_lock. + (glthread_lock_unlock): Define using glwthread_mutex_unlock. + (glthread_lock_destroy): Define using glwthread_mutex_destroy. + (glthread_lock_init_func, glthread_lock_lock_func, + glthread_lock_unlock_func, glthread_lock_destroy_func): Remove + declarations. + Use glwthread_spinlock_t instead of gl_spinlock_t. + (gl_rwlock_initializer, gl_recursive_lock_initializer): Define using + GLWTHREAD_SPINLOCK_INIT. + * lib/glthread/lock.c (glthread_lock_init_func, glthread_lock_lock_func, + glthread_lock_unlock_func, glthread_lock_destroy_func): Remove + functions. + * lib/glthread/cond.h: Use glwthread_spinlock_t instead of + gl_spinlock_t. + * modules/windows-mutex: New file. + * modules/lock (Depends-on): Add windows-mutex. + +2019-06-20 Bruno Haible + windows-once: New module. * lib/windows-once.h: New file, extracted from lib/glthread/lock.h. * lib/windows-once.c: New file, extracted from lib/glthread/lock.c. diff --git a/lib/glthread/cond.h b/lib/glthread/cond.h index 6540f1d..f252c32 100644 --- a/lib/glthread/cond.h +++ b/lib/glthread/cond.h @@ -311,7 +311,7 @@ typedef struct gl_linked_waitqueue_t; typedef struct { - gl_spinlock_t guard; /* protects the initialization */ + glwthread_spinlock_t guard; /* protects the initialization */ CRITICAL_SECTION lock; /* protects the remaining fields */ gl_linked_waitqueue_t waiters; /* waiting threads */ } diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c index 587d1e7..e17f524 100644 --- a/lib/glthread/lock.c +++ b/lib/glthread/lock.c @@ -793,56 +793,6 @@ glthread_once_singlethreaded (gl_once_t *once_control) #if USE_WINDOWS_THREADS -/* -------------------------- gl_lock_t datatype -------------------------- */ - -void -glthread_lock_init_func (gl_lock_t *lock) -{ - InitializeCriticalSection (&lock->lock); - lock->guard.done = 1; -} - -int -glthread_lock_lock_func (gl_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_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); - } - } - EnterCriticalSection (&lock->lock); - return 0; -} - -int -glthread_lock_unlock_func (gl_lock_t *lock) -{ - if (!lock->guard.done) - return EINVAL; - LeaveCriticalSection (&lock->lock); - return 0; -} - -int -glthread_lock_destroy_func (gl_lock_t *lock) -{ - if (!lock->guard.done) - return EINVAL; - DeleteCriticalSection (&lock->lock); - lock->guard.done = 0; - return 0; -} - /* ------------------------- gl_rwlock_t datatype ------------------------- */ /* In this file, the waitqueues are implemented as circular arrays. */ diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h index 93e2e48..e2a49dc 100644 --- a/lib/glthread/lock.h +++ b/lib/glthread/lock.h @@ -690,6 +690,8 @@ extern int glthread_once_singlethreaded (gl_once_t *once_control); # define WIN32_LEAN_AND_MEAN /* avoid including junk */ # include +# include "windows-spinlock.h" +# include "windows-mutex.h" # include "windows-once.h" # ifdef __cplusplus @@ -707,34 +709,23 @@ extern "C" { /* There is no way to statically initialize a CRITICAL_SECTION. It needs to be done lazily, once only. For this we need spinlocks. */ -typedef struct { volatile int done; volatile long started; } gl_spinlock_t; - /* -------------------------- gl_lock_t datatype -------------------------- */ -typedef struct - { - gl_spinlock_t guard; /* protects the initialization */ - CRITICAL_SECTION lock; - } - gl_lock_t; +typedef glwthread_mutex_t gl_lock_t; # define gl_lock_define(STORAGECLASS, NAME) \ STORAGECLASS gl_lock_t NAME; # define gl_lock_define_initialized(STORAGECLASS, NAME) \ STORAGECLASS gl_lock_t NAME = gl_lock_initializer; # define gl_lock_initializer \ - { { 0, -1 } } + GLWTHREAD_MUTEX_INIT # define glthread_lock_init(LOCK) \ - (glthread_lock_init_func (LOCK), 0) + (glwthread_mutex_init (LOCK), 0) # define glthread_lock_lock(LOCK) \ - glthread_lock_lock_func (LOCK) + glwthread_mutex_lock (LOCK) # define glthread_lock_unlock(LOCK) \ - glthread_lock_unlock_func (LOCK) + glwthread_mutex_unlock (LOCK) # define glthread_lock_destroy(LOCK) \ - glthread_lock_destroy_func (LOCK) -extern void glthread_lock_init_func (gl_lock_t *lock); -extern int glthread_lock_lock_func (gl_lock_t *lock); -extern int glthread_lock_unlock_func (gl_lock_t *lock); -extern int glthread_lock_destroy_func (gl_lock_t *lock); + glwthread_mutex_destroy (LOCK) /* ------------------------- gl_rwlock_t datatype ------------------------- */ @@ -752,7 +743,7 @@ typedef struct gl_carray_waitqueue_t; typedef struct { - gl_spinlock_t guard; /* protects the initialization */ + glwthread_spinlock_t guard; /* protects the initialization */ CRITICAL_SECTION lock; /* protects the remaining fields */ gl_carray_waitqueue_t waiting_readers; /* waiting readers */ gl_carray_waitqueue_t waiting_writers; /* waiting writers */ @@ -764,7 +755,7 @@ typedef struct # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; # define gl_rwlock_initializer \ - { { 0, -1 } } + { GLWTHREAD_SPINLOCK_INIT } # define glthread_rwlock_init(LOCK) \ (glthread_rwlock_init_func (LOCK), 0) # define glthread_rwlock_rdlock(LOCK) \ @@ -789,7 +780,7 @@ extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock); typedef struct { - gl_spinlock_t guard; /* protects the initialization */ + glwthread_spinlock_t guard; /* protects the initialization */ DWORD owner; unsigned long depth; CRITICAL_SECTION lock; @@ -800,7 +791,7 @@ typedef struct # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; # define gl_recursive_lock_initializer \ - { { 0, -1 }, 0, 0 } + { GLWTHREAD_SPINLOCK_INIT, 0, 0 } # define glthread_recursive_lock_init(LOCK) \ (glthread_recursive_lock_init_func (LOCK), 0) # define glthread_recursive_lock_lock(LOCK) \ diff --git a/lib/windows-mutex.c b/lib/windows-mutex.c new file mode 100644 index 0000000..e2c94b8 --- /dev/null +++ b/lib/windows-mutex.c @@ -0,0 +1,95 @@ +/* Plain 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-mutex.h" + +#include + +void +glwthread_mutex_init (glwthread_mutex_t *mutex) +{ + InitializeCriticalSection (&mutex->lock); + mutex->guard.done = 1; +} + +int +glwthread_mutex_lock (glwthread_mutex_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_mutex_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); + } + } + EnterCriticalSection (&mutex->lock); + return 0; +} + +int +glwthread_mutex_trylock (glwthread_mutex_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_mutex_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; + } + } + if (!TryEnterCriticalSection (&mutex->lock)) + return EBUSY; + return 0; +} + +int +glwthread_mutex_unlock (glwthread_mutex_t *mutex) +{ + if (!mutex->guard.done) + return EINVAL; + LeaveCriticalSection (&mutex->lock); + return 0; +} + +int +glwthread_mutex_destroy (glwthread_mutex_t *mutex) +{ + if (!mutex->guard.done) + return EINVAL; + DeleteCriticalSection (&mutex->lock); + mutex->guard.done = 0; + return 0; +} diff --git a/lib/windows-mutex.h b/lib/windows-mutex.h new file mode 100644 index 0000000..edc738e --- /dev/null +++ b/lib/windows-mutex.h @@ -0,0 +1,51 @@ +/* Plain 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_MUTEX_H +#define _WINDOWS_MUTEX_H + +#define WIN32_LEAN_AND_MEAN /* avoid including junk */ +#include + +#include "windows-spinlock.h" + +typedef struct + { + glwthread_spinlock_t guard; /* protects the initialization */ + CRITICAL_SECTION lock; + } + glwthread_mutex_t; + +#define GLWTHREAD_MUTEX_INIT { GLWTHREAD_SPINLOCK_INIT } + +#ifdef __cplusplus +extern "C" { +#endif + +extern void glwthread_mutex_init (glwthread_mutex_t *mutex); +extern int glwthread_mutex_lock (glwthread_mutex_t *mutex); +extern int glwthread_mutex_trylock (glwthread_mutex_t *mutex); +extern int glwthread_mutex_unlock (glwthread_mutex_t *mutex); +extern int glwthread_mutex_destroy (glwthread_mutex_t *mutex); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINDOWS_MUTEX_H */ diff --git a/lib/windows-spinlock.h b/lib/windows-spinlock.h new file mode 100644 index 0000000..26a4b65 --- /dev/null +++ b/lib/windows-spinlock.h @@ -0,0 +1,35 @@ +/* Spinlocks (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_SPINLOCK_H +#define _WINDOWS_SPINLOCK_H + +#define WIN32_LEAN_AND_MEAN /* avoid including junk */ +#include + +typedef struct + { + volatile int done; + volatile LONG started; + } + glwthread_spinlock_t; + +#define GLWTHREAD_SPINLOCK_INIT { 0, -1 } + +#endif /* _WINDOWS_SPINLOCK_H */ diff --git a/modules/lock b/modules/lock index fca8341..351e902 100644 --- a/modules/lock +++ b/modules/lock @@ -10,6 +10,7 @@ m4/pthread_rwlock_rdlock.m4 Depends-on: extensions threadlib +windows-mutex [test $gl_threads_api = windows] windows-once [test $gl_threads_api = windows] configure.ac: diff --git a/modules/windows-mutex b/modules/windows-mutex new file mode 100644 index 0000000..18aabcc --- /dev/null +++ b/modules/windows-mutex @@ -0,0 +1,28 @@ +Description: +Plain mutexes (native Windows implementation). + +Files: +lib/windows-mutex.h +lib/windows-mutex.c +lib/windows-spinlock.h + +Depends-on: + +configure.ac: +AC_REQUIRE([AC_CANONICAL_HOST]) +case "$host_os" in + mingw*) + AC_LIBOBJ([windows-mutex]) + ;; +esac + +Makefile.am: + +Include: +"windows-mutex.h" + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4