gcc/libstdc++-v3/testsuite
Jonathan Wakely 93e79ed391 libstdc++: Rewrite std::call_once to use futexes [PR 66146]
The current implementation of std::call_once uses pthread_once, which
only meets the C++ requirements when compiled with support for
exceptions. For most glibc targets and all non-glibc targets,
pthread_once does not work correctly if the init_routine exits via an
exception. The pthread_once_t object is left in the "active" state, and
any later attempts to run another init_routine will block forever.

This change makes std::call_once work correctly for Linux targets, by
replacing the use of pthread_once with a futex, based on the code from
__cxa_guard_acquire. For both glibc and musl, the Linux implementation
of pthread_once is already based on futexes, and pthread_once_t is just
a typedef for int, so this change does not alter the layout of
std::once_flag. By choosing the values for the int appropriately, the
new code is even ABI compatible. Code that calls the old implementation
of std::call_once will use pthread_once to manipulate the int, while new
code will use the new std::once_flag members to manipulate it, but they
should interoperate correctly. In both cases, the int is initially zero,
has the lowest bit set when there is an active execution, and equals 2
after a successful returning execution. The difference with the new code
is that exceptional exceptions are correctly detected and the int is
reset to zero.

The __cxa_guard_acquire code (and musl's pthread_once) use an additional
state to say there are other threads waiting. This allows the futex wake
syscall to be skipped if there is no contention. Glibc doesn't use a
waiter bit, so we have to unconditionally issue the wake in order to be
compatible with code calling the old std::call_once that uses Glibc's
pthread_once. If we know that we're using musl (and musl's pthread_once
doesn't change) it would be possible to set a waiting state and check
for it in std::once_flag::_M_finish(bool), but this patch doesn't do
that.

This doesn't fix the bug for non-linux targets. A similar approach could
be used for targets where we know the definition of pthread_once_t is a
mutex and an integer. We could make once_flag._M_activate() use
pthread_mutex_lock on the mutex member within the pthread_once_t, and
then only set the integer if the execution finishes, and then unlock the
mutex. That would require careful study of each target's pthread_once
implementation and that work is left for a later date.

This also fixes PR 55394 because pthread_once is no longer needed, and
PR 84323 because the fast path is now just an atomic load.

As a consequence of the new implementation that doesn't use
pthread_once, we can also make std::call_once work for targets with no
gthreads support. The code for the single-threaded implementation
follows the same methods as on Linux, but with no need for atomics or
futexes.

libstdc++-v3/ChangeLog:

	PR libstdc++/55394
	PR libstdc++/66146
	PR libstdc++/84323
	* config/abi/pre/gnu.ver (GLIBCXX_3.4.29): Add new symbols.
	* include/std/mutex [!_GLIBCXX_HAS_GTHREADS] (once_flag): Define
	even when gthreads is not supported.
	(once_flag::_M_once) [_GLIBCXX_HAVE_LINUX_FUTEX]: Change type
	from __gthread_once_t to int.
	(once_flag::_M_passive(), once_flag::_M_activate())
	(once_flag::_M_finish(bool), once_flag::_Active_execution):
	Define new members for futex and non-threaded implementation.
	[_GLIBCXX_HAS_GTHREADS] (once_flag::_Prepare_execution): New
	RAII helper type.
	(call_once): Use new members of once_flag.
	* src/c++11/mutex.cc (std::once_flag::_M_activate): Define.
	(std::once_flag::_M_finish): Define.
	* testsuite/30_threads/call_once/39909.cc: Do not require
	gthreads.
	* testsuite/30_threads/call_once/49668.cc: Likewise.
	* testsuite/30_threads/call_once/60497.cc: Likewise.
	* testsuite/30_threads/call_once/call_once1.cc: Likewise.
	* testsuite/30_threads/call_once/dr2442.cc: Likewise.
	* testsuite/30_threads/call_once/once_flag.cc: Add test for
	constexpr constructor.
	* testsuite/30_threads/call_once/66146.cc: New test.
	* testsuite/30_threads/call_once/constexpr.cc: Removed.
	* testsuite/30_threads/once_flag/cons/constexpr.cc: Removed.
2020-11-03 18:44:49 +00:00
..
17_intro libstdc++: Replace use of reserved name that clashes [PR 97362] 2020-10-10 21:22:12 +01:00
18_support libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
19_diagnostics libstdc++: Ensure c++NN effective target present in all C++17 tests 2020-07-31 19:58:02 +01:00
20_util libstdc++: AIX xfail for_overwrite.cc testcase 2020-10-29 21:57:24 -04:00
21_strings libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
22_locale libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
23_containers libstdc++: Fix some more warnings in test 2020-10-30 20:58:08 +00:00
24_iterators libstdc++: Add missing P0896 changes to <iterator> 2020-10-02 10:51:31 -04:00
25_algorithms libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
26_numerics libstdc++: Prefer double to long double in std::shuffle_order_engine 2020-10-31 12:54:03 +00:00
27_io libstdc++: Add c++2a <syncstream> 2020-11-02 10:41:32 -08:00
28_regex libstdc++: Ensure c++NN effective-target present in more tests 2020-07-31 19:58:03 +01:00
29_atomics libstdc++: Change test to work without 64-bit atomics 2020-10-02 22:18:51 +01:00
30_threads libstdc++: Rewrite std::call_once to use futexes [PR 66146] 2020-11-03 18:44:49 +00:00
abi
backward
config
data
decimal
experimental libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
ext libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
lib libstdc++: Improve comments for check_effective_target_cxx11-abi 2020-10-14 12:52:47 +01:00
libstdc++-abi
libstdc++-dg
libstdc++-prettyprinters libstdc++: Remove inheritance from elements in std::tuple 2020-08-17 15:27:51 +01:00
libstdc++-xmethods
performance libstdc++: Add performance test for <random> 2020-10-09 14:01:54 +01:00
special_functions
std libstdc++: Don't initialize from *this inside some views [PR97600] 2020-10-30 20:33:19 -04:00
tr1 libstdc++: Prevent deprecation warnings from <tr1/shared_ptr> 2020-10-29 22:47:22 +00:00
tr2
util libstdc++: Avoid warnings in tests 2020-10-29 22:47:21 +00:00
Makefile.am libstdc++: Adjust variable export in makefile 2020-10-09 14:08:42 +01:00
Makefile.in libstdc++: Adjust variable export in makefile 2020-10-09 14:08:42 +01:00