>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