On Thu, Jun 5, 2025 at 12:10 AM Jonathan Wakely <jwak...@redhat.com> wrote:

> These overloads should never be used for proxy waits, so add assertions
> to ensure that they aren't used accidentally.
>
> The reason they can't be used is that they don't call
> __args._M_setup_wait to obtain a __wait_state pointer. Even if that was
> changed, they would wait on a proxy wait which is potentially used by
> many other threads waiting on other addresses, meaning spurious wake ups
> are likely. In order to make the functions correct they would need to
> perform additional loads and comparisons of the atomic variable before
> calling __wait_impl or __wait_until_impl, which would make these
> functions no faster than the general purpose overloads that take an
> accessor function and predicate. That would be possible, and I think
> they would then work for proxy waits, but doesn't seem necessary at this
> time.
>
> In order to preseve the property that these functions are more
> lightweight and efficient than the general ones, they should not be used
> for proxy waits.
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/atomic_timed_wait.h (__atomic_wait_address_until_v):
>         Add assertion to prevent use with proxy waits.
>         (__atomic_wait_address_for_v): Likewise.
>         * include/bits/atomic_wait.h (__atomic_wait_address_v):
>         Likewise.
> ---
>
> Tested x86_64-linux and sparc-solaris.
>
I would change all the static_assert into runtime asserts. This functions
are dependent
only on the duration parameters, and I writing something like"
__atomic_wait_address_for_v(add, old, ACQUIRE, 0s);
would lead to hard error even in the , even in dependent context like
platform_semphore_impl:
I think it is surprising that __atomic_wait_address_v works in such cases,
but duration eversion sometimes
does not.


>
>  libstdc++-v3/include/bits/atomic_timed_wait.h | 8 ++++++++
>  libstdc++-v3/include/bits/atomic_wait.h       | 4 +++-
>  2 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h
> b/libstdc++-v3/include/bits/atomic_timed_wait.h
> index bd2e6bf61ecf..9cd79e8829c7 100644
> --- a/libstdc++-v3/include/bits/atomic_timed_wait.h
> +++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
> @@ -156,6 +156,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                                   const chrono::time_point<_Clock, _Dur>&
> __atime,
>                                   bool __bare_wait = false) noexcept
>      {
> +#ifndef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
> +      using namespace __detail;
> +      static_assert(__platform_wait_uses_type<__platform_wait_t>);
> +#endif
>        __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
>        auto __res = __detail::__wait_until(__addr, __args, __atime);
>        return !__res._M_timeout; // C++26 will also return last observed
> __val
> @@ -205,6 +209,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                                 const chrono::duration<_Rep, _Period>&
> __rtime,
>                                 bool __bare_wait = false) noexcept
>      {
> +#ifndef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
> +      using namespace __detail;
> +      static_assert(__platform_wait_uses_type<__platform_wait_t>);
> +#endif
>        __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
>        auto __res = __detail::__wait_for(__addr, __args, __rtime);
>        return !__res._M_timeout; // C++26 will also return last observed
> __val
> diff --git a/libstdc++-v3/include/bits/atomic_wait.h
> b/libstdc++-v3/include/bits/atomic_wait.h
> index d32fda1c2435..95151479c120 100644
> --- a/libstdc++-v3/include/bits/atomic_wait.h
> +++ b/libstdc++-v3/include/bits/atomic_wait.h
> @@ -250,12 +250,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      }
>
>    // Wait on __addr while *__addr == __old is true.
> -  // Cannot be used for proxy waits.
>    inline void
>    __atomic_wait_address_v(const __detail::__platform_wait_t* __addr,
>                           __detail::__platform_wait_t __old,
>                           int __order, bool __bare_wait = false)
>    {
> +#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
> +    __glibcxx_assert(false); // This function can't be used for proxy
> wait.
> +#endif
>      __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
>      // C++26 will not ignore the return value here
>      __detail::__wait_impl(__addr, __args);
> --
> 2.49.0
>
>

Reply via email to