>From 6c3d118e8303b1f2cfdf17749d39392f1340077d Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:04:45 +0200 Subject: [PATCH 08/26] 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. --- ChangeLog | 14 ++++++++++++ lib/glthread/lock.c | 39 --------------------------------- lib/glthread/lock.h | 15 +++++-------- lib/windows-once.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/windows-once.h | 47 +++++++++++++++++++++++++++++++++++++++ modules/lock | 1 + modules/windows-once | 27 +++++++++++++++++++++++ 7 files changed, 156 insertions(+), 49 deletions(-) create mode 100644 lib/windows-once.c create mode 100644 lib/windows-once.h create mode 100644 modules/windows-once diff --git a/ChangeLog b/ChangeLog index ba91fda..06474ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 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. + * 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 + 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 4774573..587d1e7 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 cc6fb5e..93e2e48 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-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 0000000..4a18922 --- /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 . */ + +/* Written by Bruno Haible , 2005. + Based on GCC's gthr-win32.h. */ + +#include + +/* Specification. */ +#include "windows-once.h" + +#include + +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 0000000..8b56a39 --- /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 . */ + +/* Written by Bruno Haible , 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 + +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 dafeeeb..fca8341 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 0000000..34d5b1e --- /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 -- 2.7.4