bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* ISO C 23, <stdlib.h>, and once_flag
@ 2023-03-25 21:04 Bruno Haible
  2023-03-25 21:19 ` Jeffrey Walton
  0 siblings, 1 reply; 3+ messages in thread
From: Bruno Haible @ 2023-03-25 21:04 UTC (permalink / raw)
  To: bug-gnulib

[-- Attachment #1: Type: text/plain, Size: 2357 bytes --]

In ISO C 23,
  - the type 'once_flag',
  - the macro ONCE_FLAG_INIT,
  - the declaration of function 'call_once'
are all available from <stdlib.h>, not only from <threads.h>.

1) This makes it clear that often call_once is needed in an application
without also needing mutexes. For this reason, I'm moving the 'call_once'
function definition out of the 'mtx' module, into a module of its own.

2) The requirement to have 'once_flag' defined in <stdlib.h> would mean
that Gnulib's stdlib.h replacement would have
  - to include <pthread.h> on Unix platforms, and
  - to include <windows.h> on native Windows.

Each of the two includes would cause a lot of trouble to users:
  - for <pthread.h>, by having many more cases of header file recursion
    (we had that often, and the workarounds were always ad-hoc),
  - for <windows.h>, by defining lots of identifiers in the namespace.

This is not worth the trouble, given that the workaround — include
<threads.h> instead of <stdlib.h> — is in the realm of ISO C and
very simple. I'm therefore not implementing ISO C 23 compatibility
on this point. We can revisit it in 10 years or so; then hopefully
some platforms will have restructured their header files and will
define 'once_flag' in <stdlib.h>.


2023-03-25  Bruno Haible  <bruno@clisp.org>

	stdlib: ISO C 23: Document issue with once_flag and call_once.
	* doc/posix-headers/stdlib.texi: Document issue and workaround.

2023-03-25  Bruno Haible  <bruno@clisp.org>

	call_once: New module, separate from mtx.
	* lib/threads.in.h (call_once): Declare as part of module 'call_once',
	not module 'mtx'.
	* lib/call_once.c: New file, extracted from lib/mtx.c.
	* lib/mtx.c (call_once): Remove function.
	* m4/threads_h.m4 (gl_THREADS_H_REQUIRE_DEFAULTS): Inititalize
	GNULIB_CALL_ONCE.
	* modules/threads-h (Makefile.am): Substitute GNULIB_CALL_ONCE.
	* modules/call_once: New file, based on modules/mtx.
	* modules/threads (Depends-on): Add call_once.
	* tests/test-threads-c++.cc: Update accordingly.
	* modules/call_once-tests: New file, based on modules/mtx-tests.
	* modules/mtx-tests (Files): Remove tests/test-call_once.c.
	(Makefile.am): Don't compile test-call_once.
	* doc/posix-functions/call_once.texi: Document that the relevant module
	is now 'call_once'.
	* NEWS: Mention the change.


[-- Attachment #2: 0001-call_once-New-module-separate-from-mtx.patch --]
[-- Type: text/x-patch, Size: 10275 bytes --]

From 53370c23642eb6256dafd7b6abca8cc93581b7c2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 25 Mar 2023 20:54:29 +0100
Subject: [PATCH 1/2] call_once: New module, separate from mtx.

* lib/threads.in.h (call_once): Declare as part of module 'call_once',
not module 'mtx'.
* lib/call_once.c: New file, extracted from lib/mtx.c.
* lib/mtx.c (call_once): Remove function.
* m4/threads_h.m4 (gl_THREADS_H_REQUIRE_DEFAULTS): Inititalize
GNULIB_CALL_ONCE.
* modules/threads-h (Makefile.am): Substitute GNULIB_CALL_ONCE.
* modules/call_once: New file, based on modules/mtx.
* modules/threads (Depends-on): Add call_once.
* tests/test-threads-c++.cc: Update accordingly.
* modules/call_once-tests: New file, based on modules/mtx-tests.
* modules/mtx-tests (Files): Remove tests/test-call_once.c.
(Makefile.am): Don't compile test-call_once.
* doc/posix-functions/call_once.texi: Document that the relevant module
is now 'call_once'.
* NEWS: Mention the change.
---
 ChangeLog                          | 20 ++++++++++
 NEWS                               |  4 ++
 doc/posix-functions/call_once.texi |  2 +-
 lib/call_once.c                    | 59 ++++++++++++++++++++++++++++++
 lib/mtx.c                          | 12 ------
 lib/threads.in.h                   |  2 +-
 m4/threads_h.m4                    |  3 +-
 modules/call_once                  | 31 ++++++++++++++++
 modules/call_once-tests            | 12 ++++++
 modules/mtx-tests                  |  6 +--
 modules/threads                    |  1 +
 modules/threads-h                  |  1 +
 tests/test-threads-c++.cc          |  3 ++
 13 files changed, 137 insertions(+), 19 deletions(-)
 create mode 100644 lib/call_once.c
 create mode 100644 modules/call_once
 create mode 100644 modules/call_once-tests

diff --git a/ChangeLog b/ChangeLog
index 9dd1b50086..07b96d5860 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2023-03-25  Bruno Haible  <bruno@clisp.org>
+
+	call_once: New module, separate from mtx.
+	* lib/threads.in.h (call_once): Declare as part of module 'call_once',
+	not module 'mtx'.
+	* lib/call_once.c: New file, extracted from lib/mtx.c.
+	* lib/mtx.c (call_once): Remove function.
+	* m4/threads_h.m4 (gl_THREADS_H_REQUIRE_DEFAULTS): Inititalize
+	GNULIB_CALL_ONCE.
+	* modules/threads-h (Makefile.am): Substitute GNULIB_CALL_ONCE.
+	* modules/call_once: New file, based on modules/mtx.
+	* modules/threads (Depends-on): Add call_once.
+	* tests/test-threads-c++.cc: Update accordingly.
+	* modules/call_once-tests: New file, based on modules/mtx-tests.
+	* modules/mtx-tests (Files): Remove tests/test-call_once.c.
+	(Makefile.am): Don't compile test-call_once.
+	* doc/posix-functions/call_once.texi: Document that the relevant module
+	is now 'call_once'.
+	* NEWS: Mention the change.
+
 2023-03-25  Bruno Haible  <bruno@clisp.org>
 
 	stdio: ISO C 23: Define _PRINTF_NAN_LEN_MAX.
diff --git a/NEWS b/NEWS
index 7863514118..fcfaf4906b 100644
--- a/NEWS
+++ b/NEWS
@@ -74,6 +74,10 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2023-03-25  mtx             This module no longer provides the function
+                            call_once.  To get this function, use the new
+                            separate module 'call_once'.
+
 2023-03-08  time            This module is renamed to 'time-h'.
                             The new 'time' module now also works around an
                             inconsistency in glibc 2.31+ on Linux.
diff --git a/doc/posix-functions/call_once.texi b/doc/posix-functions/call_once.texi
index ee798db963..e7c6f07542 100644
--- a/doc/posix-functions/call_once.texi
+++ b/doc/posix-functions/call_once.texi
@@ -10,7 +10,7 @@
 @url{https://www.gnu.org/software/libc/manual/html_node/Call-Once.html}.
 @end ifnotinfo
 
-Gnulib module: mtx
+Gnulib module: call_once
 
 Portability problems fixed by Gnulib:
 @itemize
diff --git a/lib/call_once.c b/lib/call_once.c
new file mode 100644
index 0000000000..d11d9506fb
--- /dev/null
+++ b/lib/call_once.c
@@ -0,0 +1,59 @@
+/* ISO C 11 once-only initialization.
+   Copyright (C) 2005-2023 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 <bruno@clisp.org>, 2005, 2019.
+   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */
+
+#include <config.h>
+
+#include <threads.h>
+
+#include <errno.h>
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* Use Windows threads.  */
+
+# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+# include <windows.h>
+
+# include <stdlib.h>
+
+#else
+/* Use POSIX threads.  */
+
+# include <pthread.h>
+
+#endif
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* Use Windows threads.  */
+
+void
+call_once (once_flag *flagp, void (*func) (void))
+{
+  glwthread_once (flagp, func);
+}
+
+#else
+/* Use POSIX threads.  */
+
+void
+call_once (once_flag *flagp, void (*func) (void))
+{
+  pthread_once (flagp, func);
+}
+
+#endif
diff --git a/lib/mtx.c b/lib/mtx.c
index fe15b69494..9292773cf4 100644
--- a/lib/mtx.c
+++ b/lib/mtx.c
@@ -187,12 +187,6 @@ mtx_destroy (mtx_t *mutex)
     }
 }
 
-void
-call_once (once_flag *flagp, void (*func) (void))
-{
-  glwthread_once (flagp, func);
-}
-
 #else
 /* Use POSIX threads.  */
 
@@ -279,10 +273,4 @@ mtx_destroy (mtx_t *mutex)
   pthread_mutex_destroy (mutex);
 }
 
-void
-call_once (once_flag *flagp, void (*func) (void))
-{
-  pthread_once (flagp, func);
-}
-
 #endif
diff --git a/lib/threads.in.h b/lib/threads.in.h
index e34c39de3f..2bc0f23b32 100644
--- a/lib/threads.in.h
+++ b/lib/threads.in.h
@@ -459,7 +459,7 @@ typedef pthread_once_t once_flag;
 
 #endif
 
-#if @GNULIB_MTX@
+#if @GNULIB_CALL_ONCE@
 # if !@HAVE_THREADS_H@
 _GL_FUNCDECL_SYS (call_once, void, (once_flag *, void (*) (void))
                                    _GL_ARG_NONNULL ((1, 2)));
diff --git a/m4/threads_h.m4 b/m4/threads_h.m4
index 77fe20d279..851490c123 100644
--- a/m4/threads_h.m4
+++ b/m4/threads_h.m4
@@ -1,4 +1,4 @@
-# threads_h.m4 serial 10
+# threads_h.m4 serial 11
 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -156,6 +156,7 @@ AC_DEFUN([gl_THREADS_MODULE_INDICATOR]
 AC_DEFUN([gl_THREADS_H_REQUIRE_DEFAULTS],
 [
   m4_defun(GL_MODULE_INDICATOR_PREFIX[_THREADS_H_MODULE_INDICATOR_DEFAULTS], [
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CALL_ONCE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CND])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MTX])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_THRD])
diff --git a/modules/call_once b/modules/call_once
new file mode 100644
index 0000000000..3efc3f3736
--- /dev/null
+++ b/modules/call_once
@@ -0,0 +1,31 @@
+Description:
+call_once() function: ISO C 11 once-only initialization.
+
+Files:
+lib/call_once.c
+
+Depends-on:
+threads-h
+windows-once
+
+configure.ac:
+AC_REQUIRE([gl_THREADS_H])
+gl_CONDITIONAL([GL_COND_OBJ_CALL_ONCE], [test $HAVE_THREADS_H = 0])
+gl_THREADS_MODULE_INDICATOR([call_once])
+
+Makefile.am:
+if GL_COND_OBJ_CALL_ONCE
+lib_SOURCES += call_once.c
+endif
+
+Include:
+<threads.h>
+
+Link:
+$(LIBSTDTHREAD)
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/call_once-tests b/modules/call_once-tests
new file mode 100644
index 0000000000..70bae25eb3
--- /dev/null
+++ b/modules/call_once-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-call_once.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-call_once
+check_PROGRAMS += test-call_once
+test_call_once_LDADD = $(LDADD) @LIBSTDTHREAD@
diff --git a/modules/mtx-tests b/modules/mtx-tests
index 52310625a5..4a021d22fa 100644
--- a/modules/mtx-tests
+++ b/modules/mtx-tests
@@ -1,6 +1,5 @@
 Files:
 tests/test-mtx.c
-tests/test-call_once.c
 tests/atomic-int-isoc.h
 tests/macros.h
 
@@ -14,7 +13,6 @@ AC_CHECK_HEADERS_ONCE([semaphore.h])
 AC_CHECK_DECLS_ONCE([alarm])
 
 Makefile.am:
-TESTS += test-mtx test-call_once
-check_PROGRAMS += test-mtx test-call_once
+TESTS += test-mtx
+check_PROGRAMS += test-mtx
 test_mtx_LDADD = $(LDADD) @LIBSTDTHREAD@ @LIBTHREAD@
-test_call_once_LDADD = $(LDADD) @LIBSTDTHREAD@
diff --git a/modules/threads b/modules/threads
index 18391c1c2d..c5bed1c328 100644
--- a/modules/threads
+++ b/modules/threads
@@ -6,6 +6,7 @@ Files:
 Depends-on:
 threads-h
 thrd
+call_once
 mtx
 cnd
 tss
diff --git a/modules/threads-h b/modules/threads-h
index 50a60dfdab..1a2b83a354 100644
--- a/modules/threads-h
+++ b/modules/threads-h
@@ -50,6 +50,7 @@ threads.h: threads.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(_NORETURN_H
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_AS_FIRST_DIRECTIVE_THREADS_H''@|$(NEXT_AS_FIRST_DIRECTIVE_THREADS_H)|g' \
 	      -e 's|@''NEXT_THREADS_H''@|$(NEXT_THREADS_H)|g' \
+	      -e 's/@''GNULIB_CALL_ONCE''@/$(GNULIB_CALL_ONCE)/g' \
 	      -e 's/@''GNULIB_CND''@/$(GNULIB_CND)/g' \
 	      -e 's/@''GNULIB_MTX''@/$(GNULIB_MTX)/g' \
 	      -e 's/@''GNULIB_THRD''@/$(GNULIB_THRD)/g' \
diff --git a/tests/test-threads-c++.cc b/tests/test-threads-c++.cc
index 7c3bcb80b1..d82b526458 100644
--- a/tests/test-threads-c++.cc
+++ b/tests/test-threads-c++.cc
@@ -45,6 +45,9 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_timedlock, int,
                  (mtx_t *, const struct timespec *));
 SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_unlock, int, (mtx_t *));
 SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_destroy, void, (mtx_t *));
+#endif
+
+#if GNULIB_TEST_CALL_ONCE
 SIGNATURE_CHECK (GNULIB_NAMESPACE::call_once, void,
                  (once_flag *, void (*) (void)));
 #endif
-- 
2.34.1


[-- Attachment #3: 0002-stdlib-ISO-C-23-Document-issue-with-once_flag-and-ca.patch --]
[-- Type: text/x-patch, Size: 1501 bytes --]

From 55a1207abc196655b9ef7c34b3cb7d736e6e7fe7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sat, 25 Mar 2023 21:48:31 +0100
Subject: [PATCH 2/2] stdlib: ISO C 23: Document issue with once_flag and
 call_once.

* doc/posix-headers/stdlib.texi: Document issue and workaround.
---
 ChangeLog                     | 5 +++++
 doc/posix-headers/stdlib.texi | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 07b96d5860..a0de338759 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2023-03-25  Bruno Haible  <bruno@clisp.org>
+
+	stdlib: ISO C 23: Document issue with once_flag and call_once.
+	* doc/posix-headers/stdlib.texi: Document issue and workaround.
+
 2023-03-25  Bruno Haible  <bruno@clisp.org>
 
 	call_once: New module, separate from mtx.
diff --git a/doc/posix-headers/stdlib.texi b/doc/posix-headers/stdlib.texi
index e7145b7dcc..612e794068 100644
--- a/doc/posix-headers/stdlib.texi
+++ b/doc/posix-headers/stdlib.texi
@@ -29,6 +29,12 @@
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+The definition of the type @code{once_flag}, of the macro
+@code{ONCE_FLAG_INIT}, and the declaration of the function
+@code{call_once}, that are required by ISO C 23, are not provided.
+To get them, import Gnulib module @code{call_once} and include
+@code{<threads.h>} rather than @code{<stdlib.h>}.
+@item
 System status macros such as @code{WEXITSTATUS} require an lvalue
 argument on some platforms.
 macOS 11.1.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: ISO C 23, <stdlib.h>, and once_flag
  2023-03-25 21:04 ISO C 23, <stdlib.h>, and once_flag Bruno Haible
@ 2023-03-25 21:19 ` Jeffrey Walton
  2023-03-25 22:32   ` Bruno Haible
  0 siblings, 1 reply; 3+ messages in thread
From: Jeffrey Walton @ 2023-03-25 21:19 UTC (permalink / raw)
  To: Bruno Haible; +Cc: bug-gnulib

On Sat, Mar 25, 2023 at 5:05 PM Bruno Haible <bruno@clisp.org> wrote:
>
> In ISO C 23,
>   - the type 'once_flag',
>   - the macro ONCE_FLAG_INIT,
>   - the declaration of function 'call_once'
> are all available from <stdlib.h>, not only from <threads.h>.
>
> 1) This makes it clear that often call_once is needed in an application
> without also needing mutexes. For this reason, I'm moving the 'call_once'
> function definition out of the 'mtx' module, into a module of its own.
>
> 2) The requirement to have 'once_flag' defined in <stdlib.h> would mean
> that Gnulib's stdlib.h replacement would have
>   - to include <pthread.h> on Unix platforms, and
>   - to include <windows.h> on native Windows.
>
> Each of the two includes would cause a lot of trouble to users:
>   - for <pthread.h>, by having many more cases of header file recursion
>     (we had that often, and the workarounds were always ad-hoc),
>   - for <windows.h>, by defining lots of identifiers in the namespace.
>
> This is not worth the trouble, given that the workaround — include
> <threads.h> instead of <stdlib.h> — is in the realm of ISO C and
> very simple. I'm therefore not implementing ISO C 23 compatibility
> on this point. We can revisit it in 10 years or so; then hopefully
> some platforms will have restructured their header files and will
> define 'once_flag' in <stdlib.h>.

Be careful of call_once.

Several years ago I cut over to C++11's call_once. The problem was, it
only worked reliably on 32-bit and 64-bit Intel platforms. It was a
disaster on Aarch64, PowerPC and Sparc. I had to back it out.

The problems happened back when GCC 6 and 7 were popular. The problem
was due to something sideways in glibc.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146

If you want a call_once-like initialization then rely on N2660:
Dynamic Initialization and Destruction with Concurrency.

Jeff


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: ISO C 23, <stdlib.h>, and once_flag
  2023-03-25 21:19 ` Jeffrey Walton
@ 2023-03-25 22:32   ` Bruno Haible
  0 siblings, 0 replies; 3+ messages in thread
From: Bruno Haible @ 2023-03-25 22:32 UTC (permalink / raw)
  To: noloader; +Cc: bug-gnulib

effrey Walton wrote:
> Be careful of call_once.
> 
> Several years ago I cut over to C++11's call_once. The problem was, it
> only worked reliably on 32-bit and 64-bit Intel platforms. It was a
> disaster on Aarch64, PowerPC and Sparc. I had to back it out.
> 
> The problems happened back when GCC 6 and 7 were popular. The problem
> was due to something sideways in glibc.
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146

This was/is a problem of std::call_once, implemented in libstdc++.
Not about the call_once in C, implemented in glibc.

> If you want a call_once-like initialization then rely on N2660:
> Dynamic Initialization and Destruction with Concurrency.

This too is about C++ only.

AFAIU https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146#c9,
there's a conflict between call_once being compiled in C (and without
special GCC options) and a callee that throws C++ exceptions.

For you, it's a reminder to not use call_once. For me, it's more a
reminder to not use C++. :-)

Bruno





^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-03-25 22:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-25 21:04 ISO C 23, <stdlib.h>, and once_flag Bruno Haible
2023-03-25 21:19 ` Jeffrey Walton
2023-03-25 22:32   ` Bruno Haible

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).