The gnulib module 'lock' contain both locking and once-only facilities. Sometimes only the once-only facility is needed. In this case it is not necessary to ship the source code for locks, read-write locks, and recursive locks.
To achieve this, here is a patch set that creates a module 'once'. (Similar to 'call_once' for ISO C or 'pthread-once' for POSIX.) 2024-08-04 Bruno Haible <br...@clisp.org> mtx-tests: Reduce dependencies. * tests/test-mtx.c: Don't include glthread/lock.h. * modules/mtx-tests (Depends-on): Remove lock. 2024-08-04 Bruno Haible <br...@clisp.org> thread: Reduce dependencies. * lib/glthread/thread.c: Don't include glthread/lock.h. * modules/thread (Depends-on): Remove lock. 2024-08-04 Bruno Haible <br...@clisp.org> uchar-c23: Reduce dependencies. * lib/lc-charset-unicode.c: Include glthread/once.h instead of glthread/lock.h. * modules/uchar-c23 (Depends-on): Add once. Remove lock. 2024-08-04 Bruno Haible <br...@clisp.org> strsignal: Reduce dependencies. * lib/strsignal.c: Include glthread/once.h instead of glthread/lock.h. * modules/strsignal (Depends-on): Add once. Remove lock. 2024-08-04 Bruno Haible <br...@clisp.org> immutable: Clarify dependencies. * lib/immutable.c: Include glthread/once.h instead of glthread/lock.h. * modules/immutable (Depends-on): Add once. 2024-08-04 Bruno Haible <br...@clisp.org> fstrcmp: Reduce dependencies. * lib/fstrcmp.c: Include glthread/once.h instead of glthread/lock.h. * modules/fstrcmp (Depends-on): Add once. Remove lock. 2024-08-04 Bruno Haible <br...@clisp.org> lock-tests: Clarify dependencies. * tests/test-lock.c: Include glthread/once.h. * modules/lock-tests (Depends-on): Add once. 2024-08-04 Bruno Haible <br...@clisp.org> fatal-signal: Clarify dependencies. * lib/fatal-signal.c: Include glthread/once.h. * modules/fatal-signal (Depends-on): Add once. 2024-08-04 Bruno Haible <br...@clisp.org> clean-temp-simple: Clarify dependencies. * lib/clean-temp-simple.c: Include glthread/once.h. * modules/clean-temp-simple (Depends-on): Add once. 2024-08-04 Bruno Haible <br...@clisp.org> once-tests: New module, extracted from lock-tests. * modules/once-tests: New file. * modules/lock-tests (Files): Remove tests/test-once.c. (Makefile.am): Don't build and test test-once1 and test-once2. once: New module, extracted from lock. * lib/glthread/once.h: New file, extracted from lib/glthread/lock.h. * lib/glthread/once.c: New file, extracted from lib/glthread/lock.c. * lib/glthread/lock.h: Include glthread/once.h. Don't include windows-once.h. (c11_threads_in_use, glthread_in_use, gl_once_t, gl_once_define, glthread_once): Remove. (glthread_once_singlethreaded, glthread_once_multithreaded): Remove declarations. * lib/glthread/lock.c (fresh_once, glthread_once_singlethreaded, glthread_once_multithreaded): Remove. * modules/once: New file. * modules/lock (Depends-on): Add once. Remove pthread-once, windows-once. * tests/test-once.c: Include glthread/once.h instead of glthread/lock.h. * doc/multithread.texi (Gnulib multithreading): Mention the module 'once'.
>From 1ea75b0bab60e8c197cb9f8a6613dae6823c93cd Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 01/11] once: New module, extracted from lock. * lib/glthread/once.h: New file, extracted from lib/glthread/lock.h. * lib/glthread/once.c: New file, extracted from lib/glthread/lock.c. * lib/glthread/lock.h: Include glthread/once.h. Don't include windows-once.h. (c11_threads_in_use, glthread_in_use, gl_once_t, gl_once_define, glthread_once): Remove. (glthread_once_singlethreaded, glthread_once_multithreaded): Remove declarations. * lib/glthread/lock.c (fresh_once, glthread_once_singlethreaded, glthread_once_multithreaded): Remove. * modules/once: New file. * modules/lock (Depends-on): Add once. Remove pthread-once, windows-once. * tests/test-once.c: Include glthread/once.h instead of glthread/lock.h. * doc/multithread.texi (Gnulib multithreading): Mention the module 'once'. --- ChangeLog | 20 ++++ doc/multithread.texi | 4 +- lib/glthread/lock.c | 42 ------- lib/glthread/lock.h | 151 +----------------------- lib/glthread/once.c | 80 +++++++++++++ lib/glthread/once.h | 266 +++++++++++++++++++++++++++++++++++++++++++ modules/lock | 3 +- modules/once | 31 +++++ tests/test-once.c | 2 +- 9 files changed, 406 insertions(+), 193 deletions(-) create mode 100644 lib/glthread/once.c create mode 100644 lib/glthread/once.h create mode 100644 modules/once diff --git a/ChangeLog b/ChangeLog index 779e593a14..67c46542f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + once: New module, extracted from lock. + * lib/glthread/once.h: New file, extracted from lib/glthread/lock.h. + * lib/glthread/once.c: New file, extracted from lib/glthread/lock.c. + * lib/glthread/lock.h: Include glthread/once.h. Don't include + windows-once.h. + (c11_threads_in_use, glthread_in_use, gl_once_t, gl_once_define, + glthread_once): Remove. + (glthread_once_singlethreaded, glthread_once_multithreaded): Remove + declarations. + * lib/glthread/lock.c (fresh_once, glthread_once_singlethreaded, + glthread_once_multithreaded): Remove. + * modules/once: New file. + * modules/lock (Depends-on): Add once. Remove pthread-once, + windows-once. + * tests/test-once.c: Include glthread/once.h instead of glthread/lock.h. + * doc/multithread.texi (Gnulib multithreading): Mention the module + 'once'. + 2024-08-03 Bruno Haible <br...@clisp.org> gnulib-tool.py: Small refactoring. diff --git a/doc/multithread.texi b/doc/multithread.texi index db350f344e..ff16caa226 100644 --- a/doc/multithread.texi +++ b/doc/multithread.texi @@ -182,6 +182,8 @@ @item @code{<glthread/lock.h>} @item +@code{<glthread/once.h>} +@item @code{<glthread/cond.h>} @item @code{<glthread/tls.h>} @@ -195,7 +197,7 @@ @item For thread creation and management:@tie{} @tab @code{thread} @item For simple locks, recursive locks, and read-write locks:@tie{} @tab @code{lock} -@item For once-only execution:@tie{} @tab @code{lock} +@item For once-only execution:@tie{} @tab @code{once} @item For ``condition variables'' (wait queues):@tie{} @tab @code{cond} @item For thread-local storage:@tie{} @tab @code{tls} @item For relinquishing control:@tie{} @tab @code{yield} diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c index 6661ad6a82..40b2a5ee4f 100644 --- a/lib/glthread/lock.c +++ b/lib/glthread/lock.c @@ -240,8 +240,6 @@ glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) return 0; } -/* -------------------------- gl_once_t datatype -------------------------- */ - #endif /* ========================================================================= */ @@ -698,46 +696,6 @@ glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) # endif -/* -------------------------- gl_once_t datatype -------------------------- */ - -static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT; - -int -glthread_once_singlethreaded (pthread_once_t *once_control) -{ - /* We don't know whether pthread_once_t is an integer type, a floating-point - type, a pointer type, or a structure type. */ - char *firstbyte = (char *)once_control; - if (*firstbyte == *(const char *)&fresh_once) - { - /* First time use of once_control. Invert the first byte. */ - *firstbyte = ~ *(const char *)&fresh_once; - return 1; - } - else - return 0; -} - -# if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK) - -int -glthread_once_multithreaded (pthread_once_t *once_control, - void (*init_function) (void)) -{ - int err = pthread_once (once_control, init_function); - if (err == ENOSYS) - { - /* This happens on FreeBSD 11: The pthread_once function in libc returns - ENOSYS. */ - if (glthread_once_singlethreaded (once_control)) - init_function (); - return 0; - } - return err; -} - -# endif - #endif /* ========================================================================= */ diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h index 2d5cb3209c..2b9c0f2e14 100644 --- a/lib/glthread/lock.h +++ b/lib/glthread/lock.h @@ -64,13 +64,6 @@ Taking the lock: err = glthread_recursive_lock_lock (&name); Releasing the lock: err = glthread_recursive_lock_unlock (&name); De-initialization: err = glthread_recursive_lock_destroy (&name); - - Once-only execution: - Type: gl_once_t - Initializer: gl_once_define(extern, name) - Execution: gl_once (name, initfunction); - Equivalent functions with control of error handling: - Execution: err = glthread_once (&name, initfunction); */ @@ -88,17 +81,9 @@ #include <errno.h> #include <stdlib.h> -#if !defined c11_threads_in_use -# if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC -# define c11_threads_in_use() 1 -# elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK -# include <threads.h> -# pragma weak thrd_exit -# define c11_threads_in_use() (thrd_exit != NULL) -# else -# define c11_threads_in_use() 0 -# endif -#endif +#include "glthread/once.h" + +/* c11_threads_in_use() is defined in glthread/once.h. */ /* ========================================================================= */ @@ -195,14 +180,6 @@ extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock); extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock); -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef once_flag gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS once_flag NAME = ONCE_FLAG_INIT; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (call_once (ONCE_CONTROL, INITFUNCTION), 0) - # ifdef __cplusplus } # endif @@ -221,80 +198,7 @@ typedef once_flag gl_once_t; extern "C" { # endif -# if PTHREAD_IN_USE_DETECTION_HARD - -/* The pthread_in_use() detection needs to be done at runtime. */ -# define pthread_in_use() \ - glthread_in_use () -extern int glthread_in_use (void); - -# endif - -# if USE_POSIX_THREADS_WEAK - -/* Use weak references to the POSIX threads library. */ - -/* Weak references avoid dragging in external libraries if the other parts - of the program don't use them. Here we use them, because we don't want - every program that uses libintl to depend on libpthread. This assumes - that libpthread would not be loaded after libintl; i.e. if libintl is - loaded first, by an executable that does not depend on libpthread, and - then a module is dynamically loaded that depends on libpthread, libintl - will not be multithread-safe. */ - -/* The way to test at runtime whether libpthread is present is to test - whether a function pointer's value, such as &pthread_mutex_init, is - non-NULL. However, some versions of GCC have a bug through which, in - PIC mode, &foo != NULL always evaluates to true if there is a direct - call to foo(...) in the same function. To avoid this, we test the - address of a function in libpthread that we don't use. */ - -# pragma weak pthread_mutex_init -# pragma weak pthread_mutex_lock -# pragma weak pthread_mutex_unlock -# pragma weak pthread_mutex_destroy -# pragma weak pthread_rwlock_init -# pragma weak pthread_rwlock_rdlock -# pragma weak pthread_rwlock_wrlock -# pragma weak pthread_rwlock_unlock -# pragma weak pthread_rwlock_destroy -# pragma weak pthread_once -# pragma weak pthread_cond_init -# pragma weak pthread_cond_wait -# pragma weak pthread_cond_signal -# pragma weak pthread_cond_broadcast -# pragma weak pthread_cond_destroy -# pragma weak pthread_mutexattr_init -# pragma weak pthread_mutexattr_settype -# pragma weak pthread_mutexattr_destroy -# pragma weak pthread_rwlockattr_init -# if __GNU_LIBRARY__ > 1 -# pragma weak pthread_rwlockattr_setkind_np -# endif -# pragma weak pthread_rwlockattr_destroy -# ifndef pthread_self -# pragma weak pthread_self -# endif - -# if !PTHREAD_IN_USE_DETECTION_HARD - /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols - can be used to determine whether libpthread is in use. These are: - pthread_mutexattr_gettype - pthread_rwlockattr_destroy - pthread_rwlockattr_init - */ -# pragma weak pthread_mutexattr_gettype -# define pthread_in_use() \ - (pthread_mutexattr_gettype != NULL || c11_threads_in_use ()) -# endif - -# else - -# if !PTHREAD_IN_USE_DETECTION_HARD -# define pthread_in_use() 1 -# endif - -# endif +/* pthread_in_use() is defined in glthread/once.h. */ /* -------------------------- gl_lock_t datatype -------------------------- */ @@ -510,26 +414,6 @@ extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *l # endif -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef pthread_once_t gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; -# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (pthread_in_use () \ - ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ - : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) -# else -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (pthread_in_use () \ - ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ - : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) -extern int glthread_once_multithreaded (pthread_once_t *once_control, - void (*init_function) (void)); -# endif -extern int glthread_once_singlethreaded (pthread_once_t *once_control); - # ifdef __cplusplus } # endif @@ -546,7 +430,6 @@ extern int glthread_once_singlethreaded (pthread_once_t *once_control); # include "windows-mutex.h" # include "windows-rwlock.h" # include "windows-recmutex.h" -# include "windows-once.h" # ifdef __cplusplus extern "C" { @@ -619,14 +502,6 @@ typedef glwthread_recmutex_t gl_recursive_lock_t; # define glthread_recursive_lock_destroy(LOCK) \ glwthread_recmutex_destroy (LOCK) -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef glwthread_once_t gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0) - # ifdef __cplusplus } # endif @@ -670,14 +545,6 @@ typedef int gl_recursive_lock_t; # define glthread_recursive_lock_unlock(NAME) 0 # define glthread_recursive_lock_destroy(NAME) 0 -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef int gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_once_t NAME = 0; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) - #endif /* ========================================================================= */ @@ -784,16 +651,6 @@ typedef int gl_once_t; } \ while (0) -/* -------------------------- gl_once_t datatype -------------------------- */ - -#define gl_once(NAME, INITFUNCTION) \ - do \ - { \ - if (glthread_once (&NAME, INITFUNCTION)) \ - abort (); \ - } \ - while (0) - /* ========================================================================= */ #endif /* _LOCK_H */ diff --git a/lib/glthread/once.c b/lib/glthread/once.c new file mode 100644 index 0000000000..869ba3ba9a --- /dev/null +++ b/lib/glthread/once.c @@ -0,0 +1,80 @@ +/* Once-only initialization in multithreaded situations. + Copyright (C) 2005-2024 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <br...@clisp.org>, 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h. */ + +#include <config.h> + +#include "glthread/once.h" + +/* ========================================================================= */ + +#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS + +#endif + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT; + +int +glthread_once_singlethreaded (pthread_once_t *once_control) +{ + /* We don't know whether pthread_once_t is an integer type, a floating-point + type, a pointer type, or a structure type. */ + char *firstbyte = (char *)once_control; + if (*firstbyte == *(const char *)&fresh_once) + { + /* First time use of once_control. Invert the first byte. */ + *firstbyte = ~ *(const char *)&fresh_once; + return 1; + } + else + return 0; +} + +# if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK) + +int +glthread_once_multithreaded (pthread_once_t *once_control, + void (*init_function) (void)) +{ + int err = pthread_once (once_control, init_function); + if (err == ENOSYS) + { + /* This happens on FreeBSD 11: The pthread_once function in libc returns + ENOSYS. */ + if (glthread_once_singlethreaded (once_control)) + init_function (); + return 0; + } + return err; +} + +# endif + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +#endif + +/* ========================================================================= */ diff --git a/lib/glthread/once.h b/lib/glthread/once.h new file mode 100644 index 0000000000..fd00e42350 --- /dev/null +++ b/lib/glthread/once.h @@ -0,0 +1,266 @@ +/* Once-only initialization in multithreaded situations. + Copyright (C) 2005-2024 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <br...@clisp.org>, 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */ + +/* This file contains once-only initialization primitives for use with a given + thread library. + It does not contain primitives for creating threads or for other + synchronization primitives. + + Once-only execution: + Type: gl_once_t + Initializer: gl_once_define(extern, name) + Execution: gl_once (name, initfunction); + Equivalent functions with control of error handling: + Execution: err = glthread_once (&name, initfunction); +*/ + + +#ifndef _ONCE_H +#define _ONCE_H + +/* This file uses HAVE_THREADS_H. */ +#if !_GL_CONFIG_H_INCLUDED + #error "Please include config.h first." +#endif + +#include <errno.h> +#include <stdlib.h> + +#if !defined c11_threads_in_use +# if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC +# define c11_threads_in_use() 1 +# elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK +# include <threads.h> +# pragma weak thrd_exit +# define c11_threads_in_use() (thrd_exit != NULL) +# else +# define c11_threads_in_use() 0 +# endif +#endif + +/* ========================================================================= */ + +#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS + +/* Use the ISO C threads library. */ + +# include <threads.h> + +# ifdef __cplusplus +extern "C" { +# endif + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef once_flag gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS once_flag NAME = ONCE_FLAG_INIT; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (call_once (ONCE_CONTROL, INITFUNCTION), 0) + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include <pthread.h> + +# ifdef __cplusplus +extern "C" { +# endif + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The pthread_in_use() detection needs to be done at runtime. */ +# define pthread_in_use() \ + glthread_in_use () +extern int glthread_in_use (void); + +# endif + +# if USE_POSIX_THREADS_WEAK + +/* Use weak references to the POSIX threads library. */ + +/* Weak references avoid dragging in external libraries if the other parts + of the program don't use them. Here we use them, because we don't want + every program that uses libintl to depend on libpthread. This assumes + that libpthread would not be loaded after libintl; i.e. if libintl is + loaded first, by an executable that does not depend on libpthread, and + then a module is dynamically loaded that depends on libpthread, libintl + will not be multithread-safe. */ + +/* The way to test at runtime whether libpthread is present is to test + whether a function pointer's value, such as &pthread_mutex_init, is + non-NULL. However, some versions of GCC have a bug through which, in + PIC mode, &foo != NULL always evaluates to true if there is a direct + call to foo(...) in the same function. To avoid this, we test the + address of a function in libpthread that we don't use. */ + +# pragma weak pthread_mutex_init +# pragma weak pthread_mutex_lock +# pragma weak pthread_mutex_unlock +# pragma weak pthread_mutex_destroy +# pragma weak pthread_rwlock_init +# pragma weak pthread_rwlock_rdlock +# pragma weak pthread_rwlock_wrlock +# pragma weak pthread_rwlock_unlock +# pragma weak pthread_rwlock_destroy +# pragma weak pthread_once +# pragma weak pthread_cond_init +# pragma weak pthread_cond_wait +# pragma weak pthread_cond_signal +# pragma weak pthread_cond_broadcast +# pragma weak pthread_cond_destroy +# pragma weak pthread_mutexattr_init +# pragma weak pthread_mutexattr_settype +# pragma weak pthread_mutexattr_destroy +# pragma weak pthread_rwlockattr_init +# if __GNU_LIBRARY__ > 1 +# pragma weak pthread_rwlockattr_setkind_np +# endif +# pragma weak pthread_rwlockattr_destroy +# ifndef pthread_self +# pragma weak pthread_self +# endif + +# if !PTHREAD_IN_USE_DETECTION_HARD + /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols + can be used to determine whether libpthread is in use. These are: + pthread_mutexattr_gettype + pthread_rwlockattr_destroy + pthread_rwlockattr_init + */ +# pragma weak pthread_mutexattr_gettype +# define pthread_in_use() \ + (pthread_mutexattr_gettype != NULL || c11_threads_in_use ()) +# endif + +# else + +# if !PTHREAD_IN_USE_DETECTION_HARD +# define pthread_in_use() 1 +# endif + +# endif + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef pthread_once_t gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; +# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pthread_in_use () \ + ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +# else +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pthread_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (pthread_once_t *once_control, + void (*init_function) (void)); +# endif +extern int glthread_once_singlethreaded (pthread_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include <windows.h> + +# include "windows-once.h" + +# ifdef __cplusplus +extern "C" { +# endif + +/* We can use CRITICAL_SECTION directly, rather than the native Windows Event, + Mutex, Semaphore types, because + - we need only to synchronize inside a single process (address space), + not inter-process locking, + - we don't need to support trylock operations. (TryEnterCriticalSection + does not work on Windows 95/98/ME. Packages that need trylock usually + define their own mutex type.) */ + +/* There is no way to statically initialize a CRITICAL_SECTION. It needs + to be done lazily, once only. For this we need spinlocks. */ + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef glwthread_once_t gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0) + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS) + +/* Provide dummy implementation if threads are not supported. */ + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef int gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = 0; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) + +#endif + +/* ========================================================================= */ + +/* Macros with built-in error handling. */ + +/* -------------------------- gl_once_t datatype -------------------------- */ + +#define gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (glthread_once (&NAME, INITFUNCTION)) \ + abort (); \ + } \ + while (0) + +/* ========================================================================= */ + +#endif /* _ONCE_H */ diff --git a/modules/lock b/modules/lock index 2452524987..34ab02f996 100644 --- a/modules/lock +++ b/modules/lock @@ -10,11 +10,10 @@ m4/pthread_rwlock_rdlock.m4 Depends-on: extensions threadlib -pthread-once [test $gl_threads_api = posix] +once windows-mutex [test $gl_threads_api = windows] windows-rwlock [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/once b/modules/once new file mode 100644 index 0000000000..d17197b50b --- /dev/null +++ b/modules/once @@ -0,0 +1,31 @@ +Description: +Once-only initialization in multithreaded situations. + +Files: +lib/glthread/once.h +lib/glthread/once.c +m4/once.m4 + +Depends-on: +extensions +threadlib +pthread-once [test $gl_threads_api = posix] +windows-once [test $gl_threads_api = windows] + +configure.ac: +gl_ONCE + +Makefile.am: +lib_SOURCES += glthread/once.h glthread/once.c + +Include: +"glthread/once.h" + +Link: +$(LIBTHREAD) + +License: +LGPLv2+ + +Maintainer: +all diff --git a/tests/test-once.c b/tests/test-once.c index 332c86e5eb..f23eae514d 100644 --- a/tests/test-once.c +++ b/tests/test-once.c @@ -18,7 +18,7 @@ #include <config.h> -#include "glthread/lock.h" +#include "glthread/once.h" #include "macros.h" -- 2.34.1
>From dcf12b6ca6e79da4a994ff82a63b07aad2e3fcd7 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 02/11] once-tests: New module, extracted from lock-tests. * modules/once-tests: New file. * modules/lock-tests (Files): Remove tests/test-once.c. (Makefile.am): Don't build and test test-once1 and test-once2. --- ChangeLog | 5 +++++ modules/lock-tests | 9 ++------- modules/once-tests | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 modules/once-tests diff --git a/ChangeLog b/ChangeLog index 67c46542f4..87dc7788df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2024-08-04 Bruno Haible <br...@clisp.org> + once-tests: New module, extracted from lock-tests. + * modules/once-tests: New file. + * modules/lock-tests (Files): Remove tests/test-once.c. + (Makefile.am): Don't build and test test-once1 and test-once2. + once: New module, extracted from lock. * lib/glthread/once.h: New file, extracted from lib/glthread/lock.h. * lib/glthread/once.c: New file, extracted from lib/glthread/lock.c. diff --git a/modules/lock-tests b/modules/lock-tests index 7b398e2327..2a9855b0f2 100644 --- a/modules/lock-tests +++ b/modules/lock-tests @@ -1,7 +1,6 @@ Files: tests/test-rwlock1.c tests/test-lock.c -tests/test-once.c tests/atomic-int-gnulib.h tests/macros.h m4/semaphore.m4 @@ -19,11 +18,7 @@ AC_CHECK_DECLS_ONCE([alarm]) AC_REQUIRE([gl_SEMAPHORE]) Makefile.am: -TESTS += test-rwlock1 test-lock test-once1 test-once2 -check_PROGRAMS += test-rwlock1 test-lock test-once1 test-once2 +TESTS += test-rwlock1 test-lock +check_PROGRAMS += test-rwlock1 test-lock test_rwlock1_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@ test_lock_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@ @LIB_SEMAPHORE@ -test_once1_SOURCES = test-once.c -test_once1_LDADD = $(LDADD) @LIBTHREAD@ -test_once2_SOURCES = test-once.c -test_once2_LDADD = $(LDADD) @LIBMULTITHREAD@ diff --git a/modules/once-tests b/modules/once-tests new file mode 100644 index 0000000000..8684f25bc9 --- /dev/null +++ b/modules/once-tests @@ -0,0 +1,15 @@ +Files: +tests/test-once.c +tests/macros.h + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-once1 test-once2 +check_PROGRAMS += test-once1 test-once2 +test_once1_SOURCES = test-once.c +test_once1_LDADD = $(LDADD) @LIBTHREAD@ +test_once2_SOURCES = test-once.c +test_once2_LDADD = $(LDADD) @LIBMULTITHREAD@ -- 2.34.1
>From b1d6ae7b5c09ec618d7ad849e22d6ead79aae4a5 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 03/11] clean-temp-simple: Clarify dependencies. * lib/clean-temp-simple.c: Include glthread/once.h. * modules/clean-temp-simple (Depends-on): Add once. --- ChangeLog | 6 ++++++ lib/clean-temp-simple.c | 1 + modules/clean-temp-simple | 1 + 3 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 87dc7788df..8d628f36da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + clean-temp-simple: Clarify dependencies. + * lib/clean-temp-simple.c: Include glthread/once.h. + * modules/clean-temp-simple (Depends-on): Add once. + 2024-08-04 Bruno Haible <br...@clisp.org> once-tests: New module, extracted from lock-tests. diff --git a/lib/clean-temp-simple.c b/lib/clean-temp-simple.c index 6ceace116d..b394878813 100644 --- a/lib/clean-temp-simple.c +++ b/lib/clean-temp-simple.c @@ -32,6 +32,7 @@ #include "fatal-signal.h" #include "asyncsafe-spin.h" #include "glthread/lock.h" +#include "glthread/once.h" #include "thread-optim.h" #include "gl_list.h" #include "gl_linkedhash_list.h" diff --git a/modules/clean-temp-simple b/modules/clean-temp-simple index 2d2a34d9da..fa66211753 100644 --- a/modules/clean-temp-simple +++ b/modules/clean-temp-simple @@ -13,6 +13,7 @@ list asyncsafe-spin unistd lock +once thread-optim error fatal-signal -- 2.34.1
>From fb5dc5c297ba0bca3227e6a6cd4af70510154056 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 04/11] fatal-signal: Clarify dependencies. * lib/fatal-signal.c: Include glthread/once.h. * modules/fatal-signal (Depends-on): Add once. --- ChangeLog | 6 ++++++ lib/fatal-signal.c | 1 + modules/fatal-signal | 1 + 3 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8d628f36da..0a9379a549 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + fatal-signal: Clarify dependencies. + * lib/fatal-signal.c: Include glthread/once.h. + * modules/fatal-signal (Depends-on): Add once. + 2024-08-04 Bruno Haible <br...@clisp.org> clean-temp-simple: Clarify dependencies. diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index ea92574ca2..8e960f3025 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -26,6 +26,7 @@ #include <unistd.h> #include "glthread/lock.h" +#include "glthread/once.h" #include "thread-optim.h" #include "sig-handler.h" diff --git a/modules/fatal-signal b/modules/fatal-signal index 10351b9b7d..0efcc469ae 100644 --- a/modules/fatal-signal +++ b/modules/fatal-signal @@ -13,6 +13,7 @@ stdbool unistd sigaction lock +once thread-optim sigprocmask raise -- 2.34.1
>From 07398e24537cfc3131f2cc0d0602c2e850df85c5 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 05/11] lock-tests: Clarify dependencies. * tests/test-lock.c: Include glthread/once.h. * modules/lock-tests (Depends-on): Add once. --- ChangeLog | 6 ++++++ modules/lock-tests | 1 + tests/test-lock.c | 1 + 3 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0a9379a549..4504ece595 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + lock-tests: Clarify dependencies. + * tests/test-lock.c: Include glthread/once.h. + * modules/lock-tests (Depends-on): Add once. + 2024-08-04 Bruno Haible <br...@clisp.org> fatal-signal: Clarify dependencies. diff --git a/modules/lock-tests b/modules/lock-tests index 2a9855b0f2..9c43b10c77 100644 --- a/modules/lock-tests +++ b/modules/lock-tests @@ -8,6 +8,7 @@ m4/semaphore.m4 Depends-on: thread stdint +once usleep yield random diff --git a/tests/test-lock.c b/tests/test-lock.c index b5a5240f30..3f56790cb4 100644 --- a/tests/test-lock.c +++ b/tests/test-lock.c @@ -89,6 +89,7 @@ # endif #endif +#include "glthread/once.h" #include "glthread/thread.h" #include "glthread/yield.h" -- 2.34.1
>From c5c1083ed724629a7fae18d5b1a5fdda68e15224 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 06/11] fstrcmp: Reduce dependencies. * lib/fstrcmp.c: Include glthread/once.h instead of glthread/lock.h. * modules/fstrcmp (Depends-on): Add once. Remove lock. --- ChangeLog | 6 ++++++ lib/fstrcmp.c | 2 +- modules/fstrcmp | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4504ece595..50b09cc366 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + fstrcmp: Reduce dependencies. + * lib/fstrcmp.c: Include glthread/once.h instead of glthread/lock.h. + * modules/fstrcmp (Depends-on): Add once. Remove lock. + 2024-08-04 Bruno Haible <br...@clisp.org> lock-tests: Clarify dependencies. diff --git a/lib/fstrcmp.c b/lib/fstrcmp.c index 7bae23739e..0347530892 100644 --- a/lib/fstrcmp.c +++ b/lib/fstrcmp.c @@ -28,7 +28,7 @@ #include <stdlib.h> #include <limits.h> -#include "glthread/lock.h" +#include "glthread/once.h" #include "glthread/tls.h" #include "minmax.h" #include "xalloc.h" diff --git a/modules/fstrcmp b/modules/fstrcmp index 03804c942d..4713c79ac1 100644 --- a/modules/fstrcmp +++ b/modules/fstrcmp @@ -8,7 +8,7 @@ lib/fstrcmp.c Depends-on: c99 diffseq -lock +once tls minmax stdint -- 2.34.1
>From c0ec27bc11f51bd9aa8e8f3d78190d291ae4ed9f Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 07/11] immutable: Clarify dependencies. * lib/immutable.c: Include glthread/once.h instead of glthread/lock.h. * modules/immutable (Depends-on): Add once. --- ChangeLog | 6 ++++++ lib/immutable.c | 2 +- modules/immutable | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 50b09cc366..45027a1c76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + immutable: Clarify dependencies. + * lib/immutable.c: Include glthread/once.h instead of glthread/lock.h. + * modules/immutable (Depends-on): Add once. + 2024-08-04 Bruno Haible <br...@clisp.org> fstrcmp: Reduce dependencies. diff --git a/lib/immutable.c b/lib/immutable.c index 5cd1bf2ee6..3dee5919d7 100644 --- a/lib/immutable.c +++ b/lib/immutable.c @@ -76,7 +76,7 @@ extern # define PATH_MAX 4096 # endif -# include "glthread/lock.h" +# include "glthread/once.h" # endif diff --git a/modules/immutable b/modules/immutable index 0b9bc3a161..c513487ef0 100644 --- a/modules/immutable +++ b/modules/immutable @@ -13,6 +13,7 @@ Depends-on: stdint pathmax open +once ssfmalloc configure.ac: -- 2.34.1
>From 03594300ea8a598fb83c3b72005fdf8dd5a3065d Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 08/11] strsignal: Reduce dependencies. * lib/strsignal.c: Include glthread/once.h instead of glthread/lock.h. * modules/strsignal (Depends-on): Add once. Remove lock. --- ChangeLog | 6 ++++++ lib/strsignal.c | 2 +- modules/strsignal | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45027a1c76..59d8c7f567 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + strsignal: Reduce dependencies. + * lib/strsignal.c: Include glthread/once.h instead of glthread/lock.h. + * modules/strsignal (Depends-on): Add once. Remove lock. + 2024-08-04 Bruno Haible <br...@clisp.org> immutable: Clarify dependencies. diff --git a/lib/strsignal.c b/lib/strsignal.c index dc7415bf32..6f4085dd4b 100644 --- a/lib/strsignal.c +++ b/lib/strsignal.c @@ -37,7 +37,7 @@ #ifdef _LIBC # include <bits/libc-lock.h> #else /* !_LIBC */ -# include "glthread/lock.h" +# include "glthread/once.h" # include "glthread/tls.h" # define __libc_once_define(CLASS, NAME) gl_once_define (CLASS, NAME) # define __libc_once(NAME, INIT) gl_once ((NAME), (INIT)) diff --git a/modules/strsignal b/modules/strsignal index 50a9484115..a11f853086 100644 --- a/modules/strsignal +++ b/modules/strsignal @@ -10,7 +10,7 @@ Depends-on: string extensions gettext-h [test $HAVE_STRSIGNAL = 0 || test $REPLACE_STRSIGNAL = 1] -lock [test $HAVE_STRSIGNAL = 0 || test $REPLACE_STRSIGNAL = 1] +once [test $HAVE_STRSIGNAL = 0 || test $REPLACE_STRSIGNAL = 1] tls [test $HAVE_STRSIGNAL = 0 || test $REPLACE_STRSIGNAL = 1] snprintf [test $HAVE_STRSIGNAL = 0 || test $REPLACE_STRSIGNAL = 1] memset [test $HAVE_STRSIGNAL = 0 || test $REPLACE_STRSIGNAL = 1] -- 2.34.1
>From 559398491b42b0e0f35e7ff87278eebd1da6a128 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 09/11] uchar-c23: Reduce dependencies. * lib/lc-charset-unicode.c: Include glthread/once.h instead of glthread/lock.h. * modules/uchar-c23 (Depends-on): Add once. Remove lock. --- ChangeLog | 7 +++++++ lib/lc-charset-unicode.c | 2 +- modules/uchar-c23 | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 59d8c7f567..7742247adf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + uchar-c23: Reduce dependencies. + * lib/lc-charset-unicode.c: Include glthread/once.h instead of + glthread/lock.h. + * modules/uchar-c23 (Depends-on): Add once. Remove lock. + 2024-08-04 Bruno Haible <br...@clisp.org> strsignal: Reduce dependencies. diff --git a/lib/lc-charset-unicode.c b/lib/lc-charset-unicode.c index 4558f9288e..30df0b9ab3 100644 --- a/lib/lc-charset-unicode.c +++ b/lib/lc-charset-unicode.c @@ -36,7 +36,7 @@ # include "localcharset.h" # include "streq.h" -# include "glthread/lock.h" +# include "glthread/once.h" # include "glthread/tls.h" # include "unistr.h" diff --git a/modules/uchar-c23 b/modules/uchar-c23 index 5fcd2802bf..06d920bf5f 100644 --- a/modules/uchar-c23 +++ b/modules/uchar-c23 @@ -11,7 +11,7 @@ wchar iconv localcharset streq -lock +once tls mbszero wcrtomb -- 2.34.1
>From 1383df21ea37c034147c52249a9f29ab7564b6ae Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 10/11] thread: Reduce dependencies. * lib/glthread/thread.c: Don't include glthread/lock.h. * modules/thread (Depends-on): Remove lock. --- ChangeLog | 6 ++++++ lib/glthread/thread.c | 1 - modules/thread | 1 - 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7742247adf..52984ae25a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + thread: Reduce dependencies. + * lib/glthread/thread.c: Don't include glthread/lock.h. + * modules/thread (Depends-on): Remove lock. + 2024-08-04 Bruno Haible <br...@clisp.org> uchar-c23: Reduce dependencies. diff --git a/lib/glthread/thread.c b/lib/glthread/thread.c index 9c8c3035a4..034abaad65 100644 --- a/lib/glthread/thread.c +++ b/lib/glthread/thread.c @@ -23,7 +23,6 @@ #include "glthread/thread.h" #include <stdlib.h> -#include "glthread/lock.h" /* ========================================================================= */ diff --git a/modules/thread b/modules/thread index f416807b63..a16a269700 100644 --- a/modules/thread +++ b/modules/thread @@ -10,7 +10,6 @@ Depends-on: threadlib stdint extern-inline -lock windows-thread [test $gl_threads_api = windows] pthread_sigmask [test $gl_threads_api = posix] -- 2.34.1
>From ca4cf04ccf057248eb69711900ca9f97a3f5e0cc Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Subject: [PATCH 11/11] mtx-tests: Reduce dependencies. * tests/test-mtx.c: Don't include glthread/lock.h. * modules/mtx-tests (Depends-on): Remove lock. --- ChangeLog | 6 ++++++ modules/mtx-tests | 1 - tests/test-mtx.c | 2 -- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52984ae25a..ecc4dc6f1f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-08-04 Bruno Haible <br...@clisp.org> + + mtx-tests: Reduce dependencies. + * tests/test-mtx.c: Don't include glthread/lock.h. + * modules/mtx-tests (Depends-on): Remove lock. + 2024-08-04 Bruno Haible <br...@clisp.org> thread: Reduce dependencies. diff --git a/modules/mtx-tests b/modules/mtx-tests index 323d392087..b29fb0b6ce 100644 --- a/modules/mtx-tests +++ b/modules/mtx-tests @@ -6,7 +6,6 @@ m4/semaphore.m4 Depends-on: thrd -lock stdint random diff --git a/tests/test-mtx.c b/tests/test-mtx.c index 4c9f22a3c4..da19c4573f 100644 --- a/tests/test-mtx.c +++ b/tests/test-mtx.c @@ -50,8 +50,6 @@ #include <stdlib.h> #include <string.h> -#include "glthread/lock.h" - #if HAVE_DECL_ALARM # include <signal.h> # include <unistd.h> -- 2.34.1