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

Reply via email to