[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #57 from GCC Commits --- The releases/gcc-12 branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:415457babf04d077929956ea97132448b0dc4b2c commit r12-10226-g415457babf04d077929956ea97132448b0dc4b2c Author: Jonathan Wakely Date: Thu Mar 14 11:52:17 2024 + libstdc++: Correct notes about std::call_once in manual [PR66146] The bug with exceptions thrown during a std::call_once call affects all targets, so fix the docs that say it only affects non-Linux targets. libstdc++-v3/ChangeLog: PR libstdc++/66146 * doc/xml/manual/status_cxx2011.xml: Remove mention of Linux in note about std::call_once. * doc/xml/manual/status_cxx2014.xml: Likewise. * doc/xml/manual/status_cxx2017.xml: Likewise. * doc/html/manual/status.html: Regenerate. (cherry picked from commit e6836bbbd7a01af0791c02087e568b4822418c0d)
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #56 from GCC Commits --- The releases/gcc-13 branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:a2c960dd7ebe2db0e8153a7e691245a4928341c6 commit r13-8464-ga2c960dd7ebe2db0e8153a7e691245a4928341c6 Author: Jonathan Wakely Date: Thu Mar 14 11:52:17 2024 + libstdc++: Correct notes about std::call_once in manual [PR66146] The bug with exceptions thrown during a std::call_once call affects all targets, so fix the docs that say it only affects non-Linux targets. libstdc++-v3/ChangeLog: PR libstdc++/66146 * doc/xml/manual/status_cxx2011.xml: Remove mention of Linux in note about std::call_once. * doc/xml/manual/status_cxx2014.xml: Likewise. * doc/xml/manual/status_cxx2017.xml: Likewise. * doc/html/manual/status.html: Regenerate. (cherry picked from commit e6836bbbd7a01af0791c02087e568b4822418c0d)
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #55 from GCC Commits --- The master branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:e6836bbbd7a01af0791c02087e568b4822418c0d commit r14-9467-ge6836bbbd7a01af0791c02087e568b4822418c0d Author: Jonathan Wakely Date: Thu Mar 14 11:52:17 2024 + libstdc++: Correct notes about std::call_once in manual [PR66146] The bug with exceptions thrown during a std::call_once call affects all targets, so fix the docs that say it only affects non-Linux targets. libstdc++-v3/ChangeLog: PR libstdc++/66146 * doc/xml/manual/status_cxx2011.xml: Remove mention of Linux in note about std::call_once. * doc/xml/manual/status_cxx2014.xml: Likewise. * doc/xml/manual/status_cxx2017.xml: Likewise. * doc/html/manual/status.html: Regenerate.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #54 from Jonathan Wakely --- Because it would be an ABI break. It's a good option if backwards compatibility is not required, I've suggested it before.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 LIU Hao changed: What|Removed |Added CC||lh_mouse at 126 dot com --- Comment #53 from LIU Hao --- Why not implement `call_once` with `__cxa_guard_{acquire,release,abort}`? It's basically ``` template void call_once(once_flag& __once, _Callable&& __callable, _Args&&... __args) { int __r = ::__cxa_guard_acquire(&__once); if(__r == 0) return; // passive __try { _INVOKE(forward<_Callable>(__callable), forward<_Args>(__args)...); } __catch(...) { ::__cxa_guard_abort(&__once); // exceptional __throw_exception_again; } ::__cxa_guard_release(&__once); // returning } ```
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #52 from Jonathan Wakely --- *** Bug 104495 has been marked as a duplicate of this bug. ***
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added CC||f.heckenb...@fh-soft.de --- Comment #51 from Jonathan Wakely --- *** Bug 104495 has been marked as a duplicate of this bug. ***
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Richard Biener changed: What|Removed |Added Target Milestone|11.2|---
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jakub Jelinek changed: What|Removed |Added Target Milestone|11.0|11.2 --- Comment #50 from Jakub Jelinek --- GCC 11.1 has been released, retargeting bugs to GCC 11.2.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added Assignee|redi at gcc dot gnu.org|unassigned at gcc dot gnu.org Status|ASSIGNED|NEW
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #49 from Jonathan Wakely --- Looks like you didn't rebuild something properly. The __once_functor symbol should not have changed at all.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 cqwrteur changed: What|Removed |Added CC||unlvsur at live dot com --- Comment #48 from cqwrteur --- Created attachment 50518 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50518=edit after this update, my clang does not work any more Jonathan. why? Any solutions?
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #47 from CVS Commits --- The master branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:6ee24638ed0ad51e568c799bacf149ba9bd7628b commit r11-7688-g6ee24638ed0ad51e568c799bacf149ba9bd7628b Author: Jonathan Wakely Date: Fri Mar 12 11:47:20 2021 + libstdc++: Revert to old std::call_once implementation [PR 99341] The new std::call_once implementation is not backwards compatible, contrary to my intention. Because std::once_flag::_M_active() doesn't write glibc's "fork generation" into the pthread_once_t object, it's possible for glibc and libstdc++ to run two active executions concurrently. This violates the primary invariant of the feature! This patch reverts std::once_flag and std::call_once to the old implementation that uses pthread_once. This means PR 66146 is a problem again, but glibc has been changed to solve that. A new API similar to pthread_once but supporting failure and resetting the pthread_once_t will be proposed for inclusion in glibc and other C libraries. This change doesn't simply revert r11-4691 because I want to retain the new implementation for non-ghtreads targets (which didn't previously support std::call_once at all, so there's no backwards compatibility concern). This also leaves the new std::call_once::_M_activate() and std::call_once::_M_finish(bool) symbols present in libstdc++.so.6 so that code already compiled against GCC 11 can still use them. Those symbols will be removed in a subsequent commit (which distros can choose to temporarily revert if needed). libstdc++-v3/ChangeLog: PR libstdc++/99341 * include/std/mutex [_GLIBCXX_HAVE_LINUX_FUTEX] (once_flag): Revert to pthread_once_t implementation. [_GLIBCXX_HAVE_LINUX_FUTEX] (call_once): Likewise. * src/c++11/mutex.cc [_GLIBCXX_HAVE_LINUX_FUTEX] (struct __once_flag_compat): New type matching the reverted implementation of once_flag using futexes. (once_flag::_M_activate): Remove, replace with ... (_ZNSt9once_flag11_M_activateEv): ... alias symbol. (once_flag::_M_finish): Remove, replace with ... (_ZNSt9once_flag9_M_finishEb): ... alias symbol. * testsuite/30_threads/call_once/66146.cc: Removed.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #46 from Rich Felker --- It's a standard and completely reasonable assumption that, if you statically linked libstdc++ into your shared library, the copy there is for *internal use only* and cannot share objects of the standard library's types across boundaries with other libraries or the main application. The problem only comes when the library's implementation (via templates or inline code in headers) imposes the same requirement on normal dynamic linking, where it's a nonstandard and unreasonable one.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #45 from Florian Weimer --- Statically linking libstdc++ into shared objects is also not too uncommon. With luck, the libstdc++ symbols are hidden, but operating on globally shared across multiple libstdc++s exposes similar issues even without inlining.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #44 from Rich Felker --- Uhg. I don't know what kind of retroactive fix for that is possible, if any, but going forward this kind of thing (assumptions that impose ABI boundaries) should not be inlined by the template. It should just expand to an external call so that the implementation details can be kept as implementation details and changed as needed.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #43 from Jonathan Wakely --- (In reply to Rich Felker from comment #42) > I'm confused why this is an ABI boundary at all. Was the old implementation > of std::call_once being inlined into callers? Yes, it's a function template: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/std/mutex;h=12b7e548d179c3a2cb0ed65b6e113031f11293f6;hb=ee5c3db6c5b2c3332912fb4c9cfa2864569ebd9a#l710 The call to __gthread_once (which is a weak alias for pthread_once) is on line 729.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #42 from Rich Felker --- I'm confused why this is an ABI boundary at all. Was the old implementation of std::call_once being inlined into callers? Otherwise all code operating on the same once object should be using a common implementation, either the old one or the new one, from libstdc++.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #41 from Jonathan Wakely --- The new std::call_once using a futex is not backwards compatible, so I think it needs to be reverted, or hidden behind an ABI-breaking flag. The new std::once_flag::_M_activate() function sets _M_once=1 when an initialization is in progress. With glibc, if a call to the new std::call_once happens before a call to the old version of std::call_once, then glibc's pthread_once will find no fork generation value in _M_once and so will think it should run the init_function itself. Both threads will run their init_function, instead of the second one waiting for the first to finish. With musl, if a call to the old std::call_once happens before a call to the new std::call_once, then the second thread won't set _M_once=3 and so musl's pthread_once won't wake the second thread when the first finishes. The second thread will sleep forever (or until a spurious wake from the futex wait).
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #40 from Jonathan Wakely --- (In reply to Libor Bukata from comment #39) > (In reply to Libor Bukata from comment #38) > > (In reply to Jonathan Wakely from comment #34) > > > Untested sketch of a solution for Solaris and BSDs: > > > https://gcc.gnu.org/pipermail/gcc-patches/2020-November/557928.html > > > > Thank you for the patch, I will test it on Solaris > > and let you know when I have the results. > > Patched GCC master with Jonathan's patch, but unfortunately it is not > compilable on Solaris 11: > In file included from > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > sparcv9-sun-solaris2.11/bits/c++config.h:568, > from > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > cassert:43, > from > /gcc_nightly/gcc-11.0.0-master/libstdc++-v3/include/precompiled/stdc++.h:33: > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > mutex:861:10: error: token "{" is not valid in preprocessor expressions > 861 | || _GLIBCXX_COMPAT_PTHREAD_ONCE_T > | ^~ > In file included from > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > sparcv9-sun-solaris2.11/bits/c++config.h:568, > from > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > cassert:43, > from > /gcc_nightly/gcc-11.0.0-master/libstdc++-v3/include/precompiled/stdc++.h:33: > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > mutex:861:10: error: token "{" is not valid in preprocessor expressions > 861 | || _GLIBCXX_COMPAT_PTHREAD_ONCE_T > | ^~ Oops, that should be: || defined _GLIBCXX_COMPAT_PTHREAD_ONCE_T to test if the macro is defined, rather than testing its value. > In file included from > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > future:38, > from > /gcc_nightly/gcc-11.0.0-master/libstdc++-v3/include/precompiled/stdc++.h:105: > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > mutex:675:15: error: explicitly defaulted function 'constexpr > std::once_flag::once_flag()' cannot be declared 'constexpr' because the > implicit declaration is not 'constexpr': > 675 | constexpr once_flag() noexcept = default; > | ^ > /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/ > mutex:699:12: note: defaulted constructor calls non-'constexpr' > 'std::once_flag::_Once::_Once()' > 699 | struct _Once _GLIBCXX_COMPAT_PTHREAD_ONCE_T; This one's a bit trickier. The struct needs a default constructor that initializes all its members, but then it can't be used in the union. I'll provide a new patch when I get a chance to look into it.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #39 from Libor Bukata --- (In reply to Libor Bukata from comment #38) > (In reply to Jonathan Wakely from comment #34) > > Untested sketch of a solution for Solaris and BSDs: > > https://gcc.gnu.org/pipermail/gcc-patches/2020-November/557928.html > > Thank you for the patch, I will test it on Solaris > and let you know when I have the results. Patched GCC master with Jonathan's patch, but unfortunately it is not compilable on Solaris 11: In file included from /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/sparcv9-sun-solaris2.11/bits/c++config.h:568, from /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/cassert:43, from /gcc_nightly/gcc-11.0.0-master/libstdc++-v3/include/precompiled/stdc++.h:33: /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/mutex:861:10: error: token "{" is not valid in preprocessor expressions 861 | || _GLIBCXX_COMPAT_PTHREAD_ONCE_T | ^~ In file included from /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/sparcv9-sun-solaris2.11/bits/c++config.h:568, from /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/cassert:43, from /gcc_nightly/gcc-11.0.0-master/libstdc++-v3/include/precompiled/stdc++.h:33: /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/mutex:861:10: error: token "{" is not valid in preprocessor expressions 861 | || _GLIBCXX_COMPAT_PTHREAD_ONCE_T | ^~ In file included from /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/future:38, from /gcc_nightly/gcc-11.0.0-master/libstdc++-v3/include/precompiled/stdc++.h:105: /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/mutex:675:15: error: explicitly defaulted function 'constexpr std::once_flag::once_flag()' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr': 675 | constexpr once_flag() noexcept = default; | ^ /gcc_nightly/build/sparcv9/sparcv9-sun-solaris2.11/libstdc++-v3/include/mutex:699:12: note: defaulted constructor calls non-'constexpr' 'std::once_flag::_Once::_Once()' 699 | struct _Once _GLIBCXX_COMPAT_PTHREAD_ONCE_T; Note that there was a merge conflict with the current master, however, its resolution was straightforward. If there is an updated patch, I will be happy to test it as well.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Libor Bukata changed: What|Removed |Added CC||libor.bukata at oracle dot com --- Comment #38 from Libor Bukata --- (In reply to Jonathan Wakely from comment #34) > Untested sketch of a solution for Solaris and BSDs: > https://gcc.gnu.org/pipermail/gcc-patches/2020-November/557928.html Thank you for the patch, I will test it on Solaris and let you know when I have the results.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #37 from CVS Commits --- The master branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:9f9dbc8e09cf48406aa24b6c78735f1a7912cc4e commit r11-6229-g9f9dbc8e09cf48406aa24b6c78735f1a7912cc4e Author: Jonathan Wakely Date: Thu Dec 17 13:16:02 2020 + libstdc++: Fix -Wunused warning As noted in PR 66146 comment 35, there is a new warning in the new std::call_once implementation. libstdc++-v3/ChangeLog: * src/c++11/mutex.cc (std::once_flag::_M_finish): Add maybe_unused attribute to variable used in assertion.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #36 from Jonathan Wakely --- Attribute unused, not attribute used. I'll fix it shortly.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Thomas Schwinge changed: What|Removed |Added CC||tschwinge at gcc dot gnu.org --- Comment #35 from Thomas Schwinge --- In an '--enable-werror' configuration (assuming that's relevant), I'm seeing new code from commit r11-4691-g93e79ed391b9c636f087e6eb7e70f14963cd10ad "libstdc++: Rewrite std::call_once to use futexes [PR 66146]" fail to build: [...]/source-gcc/libstdc++-v3/src/c++11/mutex.cc: In member function ‘void std::once_flag::_M_finish(bool)’: [...]/source-gcc/libstdc++-v3/src/c++11/mutex.cc:77:11: error: unused variable ‘prev’ [-Werror=unused-variable] 77 | int prev = __atomic_exchange_n(&_M_once, newval, __ATOMIC_RELEASE); | ^~~~ cc1plus: all warnings being treated as errors Makefile:648: recipe for target 'mutex.lo' failed make[5]: *** [mutex.lo] Error 1 make[5]: Leaving directory '[...]/build-gcc/x86_64-pc-linux-gnu/libstdc++-v3/src/c++11' Should a '(void) prev;' be added (my current workaround), or 'prev' get some attribute 'used' added, or something else?
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #34 from Jonathan Wakely --- Untested sketch of a solution for Solaris and BSDs: https://gcc.gnu.org/pipermail/gcc-patches/2020-November/557928.html
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #33 from Jonathan Wakely --- Fixed for linux targets, not others though.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Bug 66146 depends on bug 84323, which changed state. Bug 84323 Summary: call_once uses TLS even when once_flag is set https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84323 What|Removed |Added Status|ASSIGNED|RESOLVED Resolution|--- |FIXED
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #32 from CVS Commits --- The master branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:93e79ed391b9c636f087e6eb7e70f14963cd10ad commit r11-4691-g93e79ed391b9c636f087e6eb7e70f14963cd10ad Author: Jonathan Wakely Date: Tue Nov 3 18:44:32 2020 + 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.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added Target Milestone|--- |11.0
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Evgeny changed: What|Removed |Added CC||kisha-nik at mail dot ru --- Comment #31 from Evgeny --- (In reply to Jonathan Wakely from comment #27) > Yes, we need to reimplement call_once to not use pthread_once at all, for > any targets. Is there any progress on this issue?
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added Target Milestone|10.2|---
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Peter Dimov changed: What|Removed |Added CC||pdimov at gmail dot com --- Comment #30 from Peter Dimov --- I was going to ask the stupid question "why not just use the straightforward double-checked locking here" but the answer is probably "ABI break".
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jakub Jelinek changed: What|Removed |Added Target Milestone|10.0|10.2 --- Comment #29 from Jakub Jelinek --- GCC 10.1 has been released.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added CC||mariogalindoq at hotmail dot com --- Comment #28 from Jonathan Wakely --- *** Bug 93610 has been marked as a duplicate of this bug. ***
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #27 from Jonathan Wakely --- Yes, we need to reimplement call_once to not use pthread_once at all, for any targets.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #26 from Paul Adobe --- It may be interesting to note that we recently ended up tracking a change in glibc to making this a problem on x86_64 architectures. Apparently when they refactored pthread_once in glibc patch 2.17.288 it changed the problem from an arm/powerpc only problem to an all-architecture problem. (cent7.7 had recently updated to .292, which made this quite evident)
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added Target Milestone|9.2 |10.0 --- Comment #25 from Jonathan Wakely --- Yes, that's why the bug is still open. Jakub's comment accompanied changing the target milestone from 9.1 to 9.2, because it wasn't fixed for 9.1. Changing it to 10, because it won't be done for 9.2 either.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #24 from Jon Cohen --- I don't see anything in the release notes about call_once. Is this still an open issue?
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jakub Jelinek changed: What|Removed |Added Target Milestone|9.0 |9.2 --- Comment #23 from Jakub Jelinek --- GCC 9.1 has been released.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added Target Milestone|--- |9.0 --- Comment #22 from Jonathan Wakely --- It still needs to be fixed, and hoping for a libc fix isn't going to work because even if we get a solution in glibc it won't work for other C libraries. So we need to reimplement our std::call_once. I'll make sure we get this done for GCC 9.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jon Cohen changed: What|Removed |Added CC||cohenjon at google dot com --- Comment #21 from Jon Cohen --- What is the current status on this bug? I'm currently working on exception safety for Abseil's call_once which uses pthread_once under the hood. It looks like there are still people bringing up issue with this in the glibc thread as well -- is this still actively being worked on?
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #20 from Jonathan Wakely --- (In reply to Anthony Williams from comment #16) > Would it be worth ignoring pthread_once and using an implementation of > call_once based on Mike Burrows' algorithm? > > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html That seems to work for pthread_once but not std::call_once, due to this assumption: The number of pthread_once_t variables in a programme is bounded and can be counted in an instance of type T without overflow. If T is 32-bits, this implementation requires that the number of pthread_once_t variables in a programme not exceed 2**31-3. (Recall that pthread_once_t variables are intended to have static storage class, so it would be remarkable for such a huge number to exist.) Nothing prevents an unbounded number of std::once_flag objects in C++: #include int main() { while (true) { std::once_flag f; std::call_once(f, [](){}); } }
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added CC||simon.heybrock at esss dot se --- Comment #19 from Jonathan Wakely --- *** Bug 78184 has been marked as a duplicate of this bug. ***
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely changed: What|Removed |Added Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |redi at gcc dot gnu.org
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #18 from Jonathan Wakely --- *** Bug 71025 has been marked as a duplicate of this bug. ***
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 nsz at gcc dot gnu.org changed: What|Removed |Added CC||nsz at gcc dot gnu.org --- Comment #14 from nsz at gcc dot gnu.org --- call_once is implemented on top of pthread_once in libstdc++ but pthead_once is not exception safe, only cancellation safe and it cannot be both at the same time in glibc with the current cancellation implementation (although there is ongoing work to fix that). in general this is problematic because it relies on an interface contract that pthread_once does not provide, so libstdc++ should fix it even if glibc makes pthread_once exception safe. (i was told that the underlying implementation is visible through "native handles" so a pthread-independent call_once implementation is problematic, this sounds to me like a c++ defect, such handles probably should not be exposed by libstdc++, it will break whenever there is divergence between posix and c++ requirements.. and there are plenty of that already.)
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #16 from Anthony Williams --- Would it be worth ignoring pthread_once and using an implementation of call_once based on Mike Burrows' algorithm? http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 nsz at gcc dot gnu.org changed: What|Removed |Added CC||anthony.ajw at gmail dot com --- Comment #13 from nsz at gcc dot gnu.org --- *** Bug 70298 has been marked as a duplicate of this bug. ***
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #17 from Jonathan Wakely --- Yes, I think we need to do that, because even if glibc were to change that wouldn't help on non-gnu targets.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #15 from Jonathan Wakely --- The native handles are not required by the standard, whether they exist or not is implementation-defined. If they're not supportable we'll remove them, that's not a problem.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #8 from Jonathan Wakely redi at gcc dot gnu.org --- NetBSD 5 and DragonFly BSD fail the test too. I'm going to make libstdc++ assume pthread_once is not exception-aware unless specifically told otherwise for targets where we know it works, such as x86-linux and (hopefully) glibc 2.21
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Rich Felker bugdal at aerifal dot cx changed: What|Removed |Added CC||bugdal at aerifal dot cx --- Comment #9 from Rich Felker bugdal at aerifal dot cx --- This is not portable usage of pthread_once. The longjmp based version is clearly wrong, per the resolution of http://austingroupbugs.net/view.php?id=863 and while POSIX has nothing to say about C++, the lack of any text forbidding the analogous C++ construct does not make a requirement to support it. FYI, this type of usage is not supported, and impossible to support, in musl's implementation of pthread_once (which does not interact with exceptions/unwinding, only with thread cancellation). There's a slim chance the C11 call_once function could be used, but I think the way it's specified also requires this kind of deadlock if you leave the init routine via any means but returning, and it's not widely supported yet anyway. I think the right solution is to use atomics directly to implement std::call_once and only fallback to pthread sync primitives in the contended case. As long as you don't pass arbitrary C++ callback functions provided by the caller to pthread_once, it should be safe to use any pthread functions.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jakub Jelinek jakub at gcc dot gnu.org changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #10 from Jakub Jelinek jakub at gcc dot gnu.org --- In glibc, clear_once_control should clear the pthread_once_t var on throw, wonder why it doesn't work on ppc*, seems like pthread_once.c is correctly compiled with -fexceptions. If musl doesn't want to support it, it is its own bad choice.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #11 from Jonathan Wakely redi at gcc dot gnu.org --- (In reply to Jonathan Wakely from comment #4) Thanks, Martin. So maybe something like this: --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -726,7 +738,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __set_once_functor_lock_ptr(__functor_lock); #endif +#ifdef __powerpc__ + int __e; + __try { + __e = __gthread_once(__once._M_once, __once_proxy); + } __catch(...) { + __once._M_once = once_flag{}._M_once; N.B. This won't work because it races, and may not even compile (if e.g. pthread_once_t has a const member)
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #12 from Rich Felker bugdal at aerifal dot cx --- Jakub, this is not the place to discuss the pros and cons of musl or other particular implementations; libstdc++ needs to support many which do not have the glibc-specific semantics you want. In particular there are plenty of BSDs the current code is broken on too. If you want to use pthread_once directly to implement std::call_once on glibc, that's your business, but there needs to be a portable implementation that works on other systems.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #7 from Martin Sebor msebor at gcc dot gnu.org --- I opened http://sourceware.org/bugzilla/show_bug.cgi?id=18435 for the glibc bug and attached a lightly tested patch to it.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #6 from Andrey V andrey.vul at gmail dot com --- Same failure on s390x.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely redi at gcc dot gnu.org changed: What|Removed |Added CC||msebor at gcc dot gnu.org --- Comment #1 from Jonathan Wakely redi at gcc dot gnu.org --- This has nothing to do with libstdc++, the std::call_once code is identical on x86 and ppc, and you get the same behaviour with pthreads, so it should be reported to glibc instead. #include stdio.h #include pthread.h pthread_once_t flag_ = PTHREAD_ONCE_INIT; int call_count = 0; extern C void func_() { printf(Inside func_ call_count %d\n, call_count); if (++call_count 2) throw 0; } int main() { printf(Before calling call_once flag_: %d\n, *(int*)flag_); try { pthread_once(flag_, func_); } catch(...) { printf(Inside catch all excepton flag_: %d\n, *(int*)flag_); } printf(before the 2nd call to call_once flag_: %d\n, *(int*)flag_); pthread_once(flag_, func_); }
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #2 from Andrey V andrey.vul at gmail dot com --- Replacing throw/try/catch with longjmp/setjmp for non-returning function exit, like so: #include stdio.h #include pthread.h #include setjmp.h pthread_once_t flag_ = PTHREAD_ONCE_INIT; int call_count = 0; jmp_buf catch_; void func_() { printf(Inside func_ call_count %d\n, call_count); if (++call_count 2) longjmp(catch_, 1); } int main() { int signo; printf(Before calling call_once flag_: %d\n, *(int*)flag_); signo = setjmp(catch_); if (!signo) pthread_once(flag_, func_); else printf(Inside catch all excepton flag_: %d\n, *(int*)flag_); printf(before the 2nd call to call_once flag_: %d\n, *(int*)flag_); pthread_once(flag_, func_); } , the invalid behavior isn't triggered. It appears that pthread_once doesn't take kindly to exceptions in the once_func.
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 Jonathan Wakely redi at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2015-05-15 Ever confirmed|0 |1 --- Comment #4 from Jonathan Wakely redi at gcc dot gnu.org --- Thanks, Martin. So maybe something like this: --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -726,7 +738,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __set_once_functor_lock_ptr(__functor_lock); #endif +#ifdef __powerpc__ + int __e; + __try { + __e = __gthread_once(__once._M_once, __once_proxy); + } __catch(...) { + __once._M_once = once_flag{}._M_once; + __throw_exception_again; + } +#else int __e = __gthread_once(__once._M_once, __once_proxy); +#endif #ifndef _GLIBCXX_HAVE_TLS if (__functor_lock)
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #3 from Martin Sebor msebor at gcc dot gnu.org --- On Power, both glibc and AIX pthread_once behave the same way: i.e., they fail to clear the once flag on exception. The test case below mimics glibc's pthread_once and demonstrates the root cause of the problem: the cancellation handler is not invoked when an exception is thrown unless the pthread_cleanup_push/pop macros are compiled in C++ code. Simply recompiling glibc's pthread_once.c using a C++ compiler (and adding the apprpriate extern C decoration) should fix it. Until it's fixed, as a workaround, it seems that libstdc++ could clear the flag when an exception is thrown before propagating it out of call_once. $ cat t.c gcc -O2 -Wall -c -fasynchronous-unwind-tables -g t.c g++ -DMAIN -O2 -Wall t.o -pthread t.c ./a.out #include pthread.h #include stdio.h extern int n; #if MAIN extern C void foo () { throw 0; } extern C void bar (void (*)()); int main () { try { bar (foo); } catch (...) { printf (caught exception: pthread cleanup handler %sinvoked\n, n ? : not ); } return n == 1 ? 0 : 1; } #else int n; #if __cplusplus extern C { #endif static void cleanup (void *arg) { ++n; } void bar (void (*pf)(void)) { pthread_cleanup_push (cleanup, 0); pf (); pthread_cleanup_pop (0); } #if __cplusplus } #endif #endif caught exception: pthread cleanup handler not invoked
[Bug libstdc++/66146] call_once not C++11-compliant on ppc64le
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146 --- Comment #5 from Andrew Pinski pinskia at gcc dot gnu.org --- (In reply to Jonathan Wakely from comment #4) Thanks, Martin. So maybe something like this: This happens on almost all non-x86 machines. I tested it on aarch64 and we had the same failure as powerpc.