public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-4694] libstdc++: Refactor std::call_once internals
@ 2020-11-03 20:03 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2020-11-03 20:03 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:9f925f3b198e210e0d124a3c69fae034f429942f

commit r11-4694-g9f925f3b198e210e0d124a3c69fae034f429942f
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Nov 3 19:42:07 2020 +0000

    libstdc++: Refactor std::call_once internals
    
    This separates the definition of std::__call_proxy into two funcions,
    one for TLS and one for non-TLS, to make them easier to read. It also
    replaces the __get_once_functor_lock_ptr() internal helper with a new
    set_lock_ptr(unique_lock<mutex>*) function so that __once_proxy doesn't
    need to call it twice.
    
    libstdc++-v3/ChangeLog:
    
            * src/c++11/mutex.cc [_GLIBCXX_HAVE_TLS] (__once_proxy): Define
            separately for TLS targets.
            [!_GLIBCXX_HAVE_TLS] (__get_once_functor_lock_ptr): Replace with ...
            (set_lock_ptr): ... this. Set new value and return previous
            value.
            [!_GLIBCXX_HAVE_TLS] (__set_once_functor_lock_ptr): Adjust to
            use set_lock_ptr.
            [!_GLIBCXX_HAVE_TLS] (__once_proxy): Likewise.

Diff:
---
 libstdc++-v3/src/c++11/mutex.cc | 68 +++++++++++++++++++++++------------------
 1 file changed, 39 insertions(+), 29 deletions(-)

diff --git a/libstdc++-v3/src/c++11/mutex.cc b/libstdc++-v3/src/c++11/mutex.cc
index 286f77f9a45..4d42bed8ecc 100644
--- a/libstdc++-v3/src/c++11/mutex.cc
+++ b/libstdc++-v3/src/c++11/mutex.cc
@@ -84,18 +84,6 @@ std::once_flag::_M_finish(bool returning) noexcept
 
 #endif // ! FUTEX
 
-#ifndef _GLIBCXX_HAVE_TLS
-namespace
-{
-  inline std::unique_lock<std::mutex>*&
-  __get_once_functor_lock_ptr()
-  {
-    static std::unique_lock<std::mutex>* __once_functor_lock_ptr = 0;
-    return __once_functor_lock_ptr;
-  }
-}
-#endif
-
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -103,9 +91,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #ifdef _GLIBCXX_HAVE_TLS
   __thread void* __once_callable;
   __thread void (*__once_call)();
-#else
+
+  extern "C" void __once_proxy()
+  {
+    // The caller stored a function pointer in __once_call. If it requires
+    // any state, it gets it from __once_callable.
+    __once_call();
+  }
+
+#else // ! TLS
+
   // Explicit instantiation due to -fno-implicit-instantiation.
   template class function<void()>;
+
   function<void()> __once_functor;
 
   mutex&
@@ -115,11 +113,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     return once_mutex;
   }
 
+namespace
+{
+  // Store ptr in a global variable and return the previous value.
+  inline unique_lock<mutex>*
+  set_lock_ptr(unique_lock<mutex>* ptr)
+  {
+    static unique_lock<mutex>* __once_functor_lock_ptr = nullptr;
+    return std::__exchange(__once_functor_lock_ptr, ptr);
+  }
+}
+
   // code linked against ABI 3.4.12 and later uses this
   void
   __set_once_functor_lock_ptr(unique_lock<mutex>* __ptr)
   {
-    __get_once_functor_lock_ptr() = __ptr;
+    (void) set_lock_ptr(__ptr);
   }
 
   // unsafe - retained for compatibility with ABI 3.4.11
@@ -129,26 +138,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static unique_lock<mutex> once_functor_lock(__get_once_mutex(), defer_lock);
     return once_functor_lock;
   }
-#endif
 
-  extern "C"
+  // This is called via pthread_once while __get_once_mutex() is locked.
+  extern "C" void
+  __once_proxy()
   {
-    void __once_proxy()
+    // Get the callable out of the global functor.
+    function<void()> callable = std::move(__once_functor);
+
+    // Then unlock the global mutex
+    if (unique_lock<mutex>* lock = set_lock_ptr(nullptr))
     {
-#ifndef _GLIBCXX_HAVE_TLS
-      function<void()> __once_call = std::move(__once_functor);
-      if (unique_lock<mutex>* __lock = __get_once_functor_lock_ptr())
-      {
-        // caller is using new ABI and provided lock ptr
-        __get_once_functor_lock_ptr() = 0;
-        __lock->unlock();
-      }
-      else
-        __get_once_functor_lock().unlock();  // global lock
-#endif
-      __once_call();
+      // Caller is using the new ABI and provided a pointer to its lock.
+      lock->unlock();
     }
+    else
+      __get_once_functor_lock().unlock();  // global lock
+
+    // Finally, invoke the callable.
+    callable();
   }
+#endif // ! TLS
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-03 20:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-03 20:03 [gcc r11-4694] libstdc++: Refactor std::call_once internals Jonathan Wakely

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).