From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [committed] libstdc++: Rewrite std::call_once to use futexes [PR 66146]
Date: Tue, 3 Nov 2020 20:04:18 +0000 [thread overview]
Message-ID: <20201103200418.GW503596@redhat.com> (raw)
In-Reply-To: <20201103184534.GA3112738@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 105 bytes --]
This is a minor refactoring for readability.
Tested x86_64-linux and powerpc-aix. Committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 4055 bytes --]
commit 9f925f3b198e210e0d124a3c69fae034f429942f
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Nov 3 19:42:07 2020
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 --git a/libstdc++-v3/src/c++11/mutex.cc b/libstdc++-v3/src/c++11/mutex.cc
index 286f77f9a454..4d42bed8ecc9 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
next prev parent reply other threads:[~2020-11-03 20:04 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-03 18:45 Jonathan Wakely
2020-11-03 20:04 ` Jonathan Wakely [this message]
2020-11-03 20:13 ` Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201103200418.GW503596@redhat.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).