https://gcc.gnu.org/g:7ad39bc909d1b425d0fa1803dc53cd741c10150f

commit r16-6251-g7ad39bc909d1b425d0fa1803dc53cd741c10150f
Author: LIU Hao <[email protected]>
Date:   Wed Dec 3 11:10:46 2025 +0800

    libstdc++: On Windows, retrieve thread-local variables via functions
    
    For Windows, GCC can be configured with `--enable-tls` to enable native TLS.
    The native TLS implementation has a limitation that it is incapable of
    exporting thread-local variables from DLLs. Therefore, they are retrieved
    via getter functions instead.
    
    libstdc++-v3/ChangeLog:
    
            * config/os/mingw32-w64/os_defines.h 
(_GLIBCXX_NO_EXTERN_THREAD_LOCAL):
            New macro.
            * include/std/mutex [_GLIBCXX_NO_EXTERN_THREAD_LOCAL]
            (__get_once_callable, __get_once_call): Declare new functions.
            * src/c++11/mutex.cc [_GLIBCXX_NO_EXTERN_THREAD_LOCAL]
            (__get_once_callable, __get_once_call): Define.
    
    Signed-off-by: LIU Hao <[email protected]>
    Co-authored-by: Jonathan Wakely <[email protected]>

Diff:
---
 libstdc++-v3/config/os/mingw32-w64/os_defines.h |  4 ++++
 libstdc++-v3/include/std/mutex                  | 19 +++++++++++++++++++
 libstdc++-v3/src/c++11/mutex.cc                 | 14 ++++++++++++++
 3 files changed, 37 insertions(+)

diff --git a/libstdc++-v3/config/os/mingw32-w64/os_defines.h 
b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
index 893cd704891b..70106fe792c6 100644
--- a/libstdc++-v3/config/os/mingw32-w64/os_defines.h
+++ b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
@@ -96,4 +96,8 @@
 // See libstdc++/94268
 #define _GLIBCXX_BUFSIZ 4096
 
+// Use functions to access thread-local variables from a different module.
+// Windows does not support exporting thread-local data.
+#define _GLIBCXX_NO_EXTERN_THREAD_LOCAL 1
+
 #endif
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index d4fc4c646488..e29fc7503171 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -817,9 +817,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # 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.
+#  ifdef _GLIBCXX_NO_EXTERN_THREAD_LOCAL
+
+  void*&
+  __get_once_callable() noexcept;
+
+  std::add_lvalue_reference<void (*)()>::type
+  __get_once_call() noexcept;
+
+  // These macros mean that all the code below uses the same syntax:
+#define __once_callable __get_once_callable()
+#define __once_call __get_once_call()
+
+#  else // ! _GLIBCXX_NO_EXTERN_THREAD_LOCAL
+
   extern __thread void* __once_callable;
   extern __thread void (*__once_call)();
 
+#  endif // ! _GLIBCXX_NO_EXTERN_THREAD_LOCAL
+
   // RAII type to set up state for pthread_once call.
   struct once_flag::_Prepare_execution
   {
@@ -844,6 +860,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Prepare_execution& operator=(const _Prepare_execution&) = delete;
   };
 
+#undef __once_callable
+#undef __once_call
+
 # else
   // Without TLS use a global std::mutex and store the callable in a
   // global std::function.
diff --git a/libstdc++-v3/src/c++11/mutex.cc b/libstdc++-v3/src/c++11/mutex.cc
index d5da5c66ae99..82f0afa4cb4e 100644
--- a/libstdc++-v3/src/c++11/mutex.cc
+++ b/libstdc++-v3/src/c++11/mutex.cc
@@ -34,6 +34,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __thread void* __once_callable;
   __thread void (*__once_call)();
 
+# ifdef _GLIBCXX_NO_EXTERN_THREAD_LOCAL
+
+  // When thread-local variables can't be exported, these functions are called
+  // to retrieve these variables.
+  void*&
+  __get_once_callable() noexcept
+  { return __once_callable; }
+
+  __typeof__(void (*)())&
+  __get_once_call() noexcept
+  { return __once_call; }
+
+# endif // _GLIBCXX_NO_EXTERN_THREAD_LOCAL
+
   extern "C" void __once_proxy()
   {
     // The caller stored a function pointer in __once_call. If it requires

Reply via email to