diff options
author | Bruno Haible <bruno@clisp.org> | 2019-06-20 04:04:45 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2019-06-20 04:07:03 +0200 |
commit | 6c3d118e8303b1f2cfdf17749d39392f1340077d (patch) | |
tree | c4c31e84311c7dc5160a5aff6b9dca7b7b95278c | |
parent | 7078fef393b8d06c522c690c1fe7017596b12734 (diff) | |
download | gnulib-6c3d118e8303b1f2cfdf17749d39392f1340077d.tar.gz gnulib-6c3d118e8303b1f2cfdf17749d39392f1340077d.tar.bz2 |
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.
* lib/glthread/lock.h: Include windows-once.h.
(gl_once_t): Define using glwthread_once_t.
(gl_once_define): Define using GLWTHREAD_ONCE_INIT.
(glthread_once): Define using glwthread_once.
(glthread_once_func): Remove declaration.
* lib/glthread/lock.c (glthread_once_func): Remove function.
* modules/windows-once: New file.
* modules/lock (Depends-on): Add windows-once.
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | lib/glthread/lock.c | 39 | ||||
-rw-r--r-- | lib/glthread/lock.h | 15 | ||||
-rw-r--r-- | lib/windows-once.c | 62 | ||||
-rw-r--r-- | lib/windows-once.h | 47 | ||||
-rw-r--r-- | modules/lock | 1 | ||||
-rw-r--r-- | modules/windows-once | 27 |
7 files changed, 156 insertions, 49 deletions
@@ -1,5 +1,19 @@ 2019-06-20 Bruno Haible <bruno@clisp.org> + 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. + * lib/glthread/lock.h: Include windows-once.h. + (gl_once_t): Define using glwthread_once_t. + (gl_once_define): Define using GLWTHREAD_ONCE_INIT. + (glthread_once): Define using glwthread_once. + (glthread_once_func): Remove declaration. + * lib/glthread/lock.c (glthread_once_func): Remove function. + * modules/windows-once: New file. + * modules/lock (Depends-on): Add windows-once. + +2019-06-20 Bruno Haible <bruno@clisp.org> + lock, cond: Avoid possible counter wraparound on Windows. * lib/glthread/lock.c (glthread_lock_lock_func): Leave the 'started' field of the guard unchanged if it was already positive. diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c index 4774573675..587d1e7a29 100644 --- a/lib/glthread/lock.c +++ b/lib/glthread/lock.c @@ -1193,45 +1193,6 @@ glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock) return 0; } -/* -------------------------- gl_once_t datatype -------------------------- */ - -void -glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) -{ - if (once_control->inited <= 0) - { - if (InterlockedIncrement (&once_control->started) == 0) - { - /* This thread is the first one to come to this once_control. */ - InitializeCriticalSection (&once_control->lock); - EnterCriticalSection (&once_control->lock); - once_control->inited = 0; - initfunction (); - once_control->inited = 1; - LeaveCriticalSection (&once_control->lock); - } - else - { - /* Don't let once_control->started grow and wrap around. */ - InterlockedDecrement (&once_control->started); - /* Some other thread has already started the initialization. - Yield the CPU while waiting for the other thread to finish - initializing and taking the lock. */ - while (once_control->inited < 0) - Sleep (0); - if (once_control->inited <= 0) - { - /* Take the lock. This blocks until the other thread has - finished calling the initfunction. */ - EnterCriticalSection (&once_control->lock); - LeaveCriticalSection (&once_control->lock); - if (!(once_control->inited > 0)) - abort (); - } - } - } -} - #endif /* ========================================================================= */ diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h index cc6fb5e60d..93e2e48241 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 <windows.h> +# include "windows-once.h" + # ifdef __cplusplus extern "C" { # endif @@ -814,18 +816,11 @@ extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock); /* -------------------------- gl_once_t datatype -------------------------- */ -typedef struct - { - volatile int inited; - volatile long started; - CRITICAL_SECTION lock; - } - gl_once_t; +typedef glwthread_once_t gl_once_t; # define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_once_t NAME = { -1, -1 }; + STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT; # define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0) -extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)); + (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0) # ifdef __cplusplus } diff --git a/lib/windows-once.c b/lib/windows-once.c new file mode 100644 index 0000000000..4a18922aaf --- /dev/null +++ b/lib/windows-once.c @@ -0,0 +1,62 @@ +/* Once-only control (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-once.h" + +#include <stdlib.h> + +void +glwthread_once (glwthread_once_t *once_control, void (*initfunction) (void)) +{ + if (once_control->inited <= 0) + { + if (InterlockedIncrement (&once_control->started) == 0) + { + /* This thread is the first one to come to this once_control. */ + InitializeCriticalSection (&once_control->lock); + EnterCriticalSection (&once_control->lock); + once_control->inited = 0; + initfunction (); + once_control->inited = 1; + LeaveCriticalSection (&once_control->lock); + } + else + { + /* Don't let once_control->started grow and wrap around. */ + InterlockedDecrement (&once_control->started); + /* Some other thread has already started the initialization. + Yield the CPU while waiting for the other thread to finish + initializing and taking the lock. */ + while (once_control->inited < 0) + Sleep (0); + if (once_control->inited <= 0) + { + /* Take the lock. This blocks until the other thread has + finished calling the initfunction. */ + EnterCriticalSection (&once_control->lock); + LeaveCriticalSection (&once_control->lock); + if (!(once_control->inited > 0)) + abort (); + } + } + } +} diff --git a/lib/windows-once.h b/lib/windows-once.h new file mode 100644 index 0000000000..8b56a392d9 --- /dev/null +++ b/lib/windows-once.h @@ -0,0 +1,47 @@ +/* Once-only control (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_ONCE_H +#define _WINDOWS_ONCE_H + +#define WIN32_LEAN_AND_MEAN /* avoid including junk */ +#include <windows.h> + +typedef struct + { + volatile int inited; + volatile LONG started; + CRITICAL_SECTION lock; + } + glwthread_once_t; + +#define GLWTHREAD_ONCE_INIT { -1, -1 } + +#ifdef __cplusplus +extern "C" { +#endif + +extern void glwthread_once (glwthread_once_t *once_control, + void (*initfunction) (void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINDOWS_ONCE_H */ diff --git a/modules/lock b/modules/lock index dafeeeba3c..fca83413ad 100644 --- a/modules/lock +++ b/modules/lock @@ -10,6 +10,7 @@ m4/pthread_rwlock_rdlock.m4 Depends-on: extensions threadlib +windows-once [test $gl_threads_api = windows] configure.ac: gl_LOCK diff --git a/modules/windows-once b/modules/windows-once new file mode 100644 index 0000000000..34d5b1e3bd --- /dev/null +++ b/modules/windows-once @@ -0,0 +1,27 @@ +Description: +Once-only control (native Windows implementation). + +Files: +lib/windows-once.h +lib/windows-once.c + +Depends-on: + +configure.ac: +AC_REQUIRE([AC_CANONICAL_HOST]) +case "$host_os" in + mingw*) + AC_LIBOBJ([windows-once]) + ;; +esac + +Makefile.am: + +Include: +"windows-once.h" + +License: +LGPLv2+ + +Maintainer: +all |