在 2024-11-29 23:50, Jonathan Wakely 写道:
It looks like your patch is against gcc-14 not trunk, the GLIBCXX_15.1.0 version is already there.Sorry, I mean GLIBCXX_3.4.34 for 15.1.0
Oops that's what I used to test the patch. Reapplied to master now. -- Best regards, LIU Hao
From bafa1604e632d621a57b50ccd9d7a87b01822fd7 Mon Sep 17 00:00:00 2001 From: LIU Hao <lh_mo...@126.com> Date: Fri, 29 Nov 2024 17:17:01 +0800 Subject: [PATCH] libstdc++: Hide TLS variables in `std::call_once` This is a transitional change for PR80881, because on Windows, thread-local variables can't be exported from a DLL. This commit hides `__once_callable` and `__once` beneath a wrapper function, but also leaves them external for backward compatibility. Another purpose for this wrapper function is that, if in the future we decide to fix PR66146, the changes will be local to source files. libstdc++-v3/ChangeLog: PR libstdc++/66146 PR target/80881 * include/std/mutex (once_flag::_M_use_callable): New function. (call_once): Duplicate from old one for TLS, and make it call `_M_use_callable` instead. * src/c++11/mutex.cc (once_flag::_M_use_callable): New function. --- libstdc++-v3/config/abi/pre/gnu.ver | 2 ++ libstdc++-v3/include/std/mutex | 48 ++++++++++++----------------- libstdc++-v3/src/c++11/mutex.cc | 15 +++++++++ 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index ae79b371d80d..ef7141a06b6a 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2540,6 +2540,8 @@ GLIBCXX_3.4.34 { _ZNSt8__format25__locale_encoding_to_utf8ERKSt6localeSt17basic_string_viewIcSt11char_traitsIcEEPv; # __sso_string constructor and destructor _ZNSt12__sso_string[CD][12]Ev; + # std::once_flag::_M_use_callable(void (*)(void*), void*) + _ZNSt9once_flag15_M_use_callableEPFvPvES0_; } GLIBCXX_3.4.33; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index e0cedc4398a9..0fe624f075c5 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -820,44 +820,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // for most targets this doesn't work correctly for exceptional executions. __gthread_once_t _M_once = __GTHREAD_ONCE_INIT; +# ifdef _GLIBCXX_HAVE_TLS + void + _M_use_callable(void (*__call)(void*), void* __callable); +# else struct _Prepare_execution; +# endif template<typename _Callable, typename... _Args> friend void call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); }; - /// @cond undocumented # ifdef _GLIBCXX_HAVE_TLS - // If TLS is available use thread-local state for the type-erased callable - // that is being run by std::call_once in the current thread. - extern __thread void* __once_callable; - extern __thread void (*__once_call)(); + /// Invoke a callable and synchronize with other calls using the same flag + template<typename _Callable, typename... _Args> + void + call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) + { + // Closure type that runs the function + auto __callable = [&] { + std::__invoke(std::forward<_Callable>(__f), + std::forward<_Args>(__args)...); + }; - // RAII type to set up state for pthread_once call. - struct once_flag::_Prepare_execution - { - template<typename _Callable> - explicit - _Prepare_execution(_Callable& __c) - { - // Store address in thread-local pointer: - __once_callable = std::__addressof(__c); - // Trampoline function to invoke the closure via thread-local pointer: - __once_call = [] { (*static_cast<_Callable*>(__once_callable))(); }; - } + auto __call = [](void* __p) { + (*static_cast<decltype(__callable)*>(__p))(); + }; - ~_Prepare_execution() - { - // PR libstdc++/82481 - __once_callable = nullptr; - __once_call = nullptr; + __once._M_use_callable(__call, &__callable); } - _Prepare_execution(const _Prepare_execution&) = delete; - _Prepare_execution& operator=(const _Prepare_execution&) = delete; - }; - # else // Without TLS use a global std::mutex and store the callable in a // global std::function. @@ -894,8 +887,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Prepare_execution(const _Prepare_execution&) = delete; _Prepare_execution& operator=(const _Prepare_execution&) = delete; }; -# endif - /// @endcond // This function is passed to pthread_once by std::call_once. // It runs __once_call() or __once_functor(). @@ -918,6 +909,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (int __e = __gthread_once(&__once._M_once, &__once_proxy)) __throw_system_error(__e); } +# endif #else // _GLIBCXX_HAS_GTHREADS diff --git a/libstdc++-v3/src/c++11/mutex.cc b/libstdc++-v3/src/c++11/mutex.cc index bfeea538a7c3..5aea0e7b60e2 100644 --- a/libstdc++-v3/src/c++11/mutex.cc +++ b/libstdc++-v3/src/c++11/mutex.cc @@ -41,6 +41,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __once_call(); } + void + once_flag::_M_use_callable(void (*__call)(void*), void* __callable) + { + auto once_p = make_pair(__call, __callable); + __once_callable = &once_p; + __once_call = [] { + auto p = static_cast<decltype(once_p)*>(__once_callable); + (*p->first)(p->second); + }; + + // XXX pthread_once does not reset the flag if an exception is thrown. + if (int __e = __gthread_once(&_M_once, &__once_proxy)) + __throw_system_error(__e); + } + #else // ! TLS // Explicit instantiation due to -fno-implicit-instantiation. -- 2.47.1
OpenPGP_signature.asc
Description: OpenPGP digital signature