[PATCH] [libstdc++] Refactor/cleanup of atomic wait implementation
Jonathan Wakely
jwakely@redhat.com
Tue Apr 20 09:18:15 GMT 2021
On 19/04/21 12:23 -0700, Thomas Rodgers wrote:
> namespace __detail
> {
>- using __platform_wait_t = int;
>-
>- constexpr auto __atomic_spin_count_1 = 16;
>- constexpr auto __atomic_spin_count_2 = 12;
>-
>- template<typename _Tp>
>- inline constexpr bool __platform_wait_uses_type
> #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
>- = is_same_v<remove_cv_t<_Tp>, __platform_wait_t>;
>+ using __platform_wait_t = int;
> #else
>- = false;
>+ using __platform_wait_t = uint64_t;
>+#endif
>+ static constexpr size_t __platform_wait_alignment
>+ = alignof(__platform_wait_t);
The value of this constant can't be alignof(__platform_wait_t). As
discussed, a futex always needs 4-byte alignment, but on at least one
target that GCC supports, alignof(int) == 2.
>+ } // namespace __detail
>+
>+ template<typename _Tp>
>+ inline constexpr bool __platform_wait_uses_type
>+#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
>+ = is_scalar_v<_Tp>
>+ && ((sizeof(_Tp) == sizeof(__detail::__platform_wait_t))
>+ && (alignof(_Tp*) >= alignof(__detail::__platform_wait_t)));
Now that we have the __platform_wait_alignment it should be used here
(so that when we fix the constant, this gets fixed too).
>+#else
>+ = false;
> #endif
>
>+ namespace __detail
>+ {
> #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
>+#define _GLIBCXX_HAVE_PLATFORM_WAIT 1
> enum class __futex_wait_flags : int
> {
> #ifdef _GLIBCXX_HAVE_LINUX_FUTEX_PRIVATE
>+
>+ static __waiter_type&
>+ _S_for(const void* __addr)
>+ {
>+ static_assert(sizeof(__waiter_type) == sizeof(__waiter_pool_base));
>+ auto& res = __waiter_pool_base::_S_for(__addr);
>+ return reinterpret_cast<__waiter_type&>(res);
>+ }
Nit: this is still indented as if it were a function template.
> : _M_a(__expected) { }
>@@ -73,8 +73,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> _GLIBCXX_ALWAYS_INLINE void
> wait() const noexcept
> {
>- auto const __old = __atomic_impl::load(&_M_a, memory_order::acquire);
>- std::__atomic_wait(&_M_a, __old, [this] { return this->try_wait(); });
>+ auto const __pred = [this] { return this->try_wait(); };
>+ std::__atomic_wait_address(&_M_a, __pred);
> }
>
> _GLIBCXX_ALWAYS_INLINE void
>@@ -85,7 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> }
>
> private:
>- alignas(__alignof__(ptrdiff_t)) ptrdiff_t _M_a;
>+ alignas(__alignof__(__detail::__platform_wait_t)) __detail::__platform_wait_t _M_a;
This should use the new constant too.
More information about the Libstdc++
mailing list