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