]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/bits/atomic_wait.h
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / atomic_wait.h
index 2ac07ccd05e53be47681dfe7dc6fba5ace3b6260..6c98f3963ad1f66be9c3b01c869ac17f52d762e7 100644 (file)
@@ -1,6 +1,6 @@
 // -*- C++ -*- header.
 
-// Copyright (C) 2020-2021 Free Software Foundation, Inc.
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 
 #pragma GCC system_header
 
-#include <bits/c++config.h>
-#if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
+#include <bits/version.h>
+
+#if __glibcxx_atomic_wait
+#include <cstdint>
 #include <bits/functional_hash.h>
 #include <bits/gthr.h>
 #include <ext/numeric_traits.h>
@@ -48,8 +50,6 @@
 
 # include <bits/std_mutex.h>  // std::mutex, std::__condvar
 
-#define __cpp_lib_atomic_wait 201907L
-
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -58,14 +58,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
 #define _GLIBCXX_HAVE_PLATFORM_WAIT 1
     using __platform_wait_t = int;
-    static constexpr size_t __platform_wait_alignment = 4;
+    inline constexpr size_t __platform_wait_alignment = 4;
 #else
 // define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait()
 // and __platform_notify() if there is a more efficient primitive supported
 // by the platform (e.g. __ulock_wait()/__ulock_wake()) which is better than
 // a mutex/condvar based wait.
-    using __platform_wait_t = uint64_t;
-    static constexpr size_t __platform_wait_alignment
+# if ATOMIC_LONG_LOCK_FREE == 2
+    using __platform_wait_t = unsigned long;
+# else
+    using __platform_wait_t = unsigned int;
+# endif
+    inline constexpr size_t __platform_wait_alignment
       = __alignof__(__platform_wait_t);
 #endif
   } // namespace __detail
@@ -142,8 +146,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
     }
 
-    constexpr auto __atomic_spin_count_1 = 12;
-    constexpr auto __atomic_spin_count_2 = 4;
+    inline constexpr auto __atomic_spin_count_relax = 12;
+    inline constexpr auto __atomic_spin_count = 16;
 
     struct __default_spin_policy
     {
@@ -157,18 +161,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       bool
       __atomic_spin(_Pred& __pred, _Spin __spin = _Spin{ }) noexcept
       {
-       for (auto __i = 0; __i < __atomic_spin_count_1; ++__i)
+       for (auto __i = 0; __i < __atomic_spin_count; ++__i)
          {
            if (__pred())
              return true;
-           __detail::__thread_relax();
-         }
 
-       for (auto __i = 0; __i < __atomic_spin_count_2; ++__i)
-         {
-           if (__pred())
-             return true;
-           __detail::__thread_yield();
+           if (__i < __atomic_spin_count_relax)
+             __detail::__thread_relax();
+           else
+             __detail::__thread_yield();
          }
 
        while (__spin())
@@ -209,33 +210,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       void
       _M_enter_wait() noexcept
-      { __atomic_fetch_add(&_M_wait, 1, __ATOMIC_ACQ_REL); }
+      { __atomic_fetch_add(&_M_wait, 1, __ATOMIC_SEQ_CST); }
 
       void
       _M_leave_wait() noexcept
-      { __atomic_fetch_sub(&_M_wait, 1, __ATOMIC_ACQ_REL); }
+      { __atomic_fetch_sub(&_M_wait, 1, __ATOMIC_RELEASE); }
 
       bool
       _M_waiting() const noexcept
       {
        __platform_wait_t __res;
-       __atomic_load(&_M_wait, &__res, __ATOMIC_ACQUIRE);
-       return __res > 0;
+       __atomic_load(&_M_wait, &__res, __ATOMIC_SEQ_CST);
+       return __res != 0;
       }
 
       void
-      _M_notify(const __platform_wait_t* __addr, bool __all, bool __bare) noexcept
+      _M_notify(__platform_wait_t* __addr, [[maybe_unused]] bool __all,
+               bool __bare) noexcept
       {
-       if (!(__bare || _M_waiting()))
-         return;
-
 #ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
-       __platform_notify(__addr, __all);
+       if (__addr == &_M_ver)
+         {
+           __atomic_fetch_add(__addr, 1, __ATOMIC_SEQ_CST);
+           __all = true;
+         }
+
+       if (__bare || _M_waiting())
+         __platform_notify(__addr, __all);
 #else
-       if (__all)
+       {
+         lock_guard<mutex> __l(_M_mtx);
+         __atomic_fetch_add(__addr, 1, __ATOMIC_RELAXED);
+       }
+       if (__bare || _M_waiting())
          _M_cv.notify_all();
-       else
-         _M_cv.notify_one();
 #endif
       }
 
@@ -258,11 +266,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        __platform_wait(__addr, __old);
 #else
        __platform_wait_t __val;
-       __atomic_load(__addr, &__val, __ATOMIC_RELAXED);
+       __atomic_load(__addr, &__val, __ATOMIC_SEQ_CST);
        if (__val == __old)
          {
            lock_guard<mutex> __l(_M_mtx);
-           _M_cv.wait(_M_mtx);
+           __atomic_load(__addr, &__val, __ATOMIC_RELAXED);
+           if (__val == __old)
+             _M_cv.wait(_M_mtx);
          }
 #endif // __GLIBCXX_HAVE_PLATFORM_WAIT
       }
@@ -300,20 +310,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            , _M_addr(_S_wait_addr(__addr, &_M_w._M_ver))
          { }
 
-       bool
-       _M_laundered() const
-       { return _M_addr == &_M_w._M_ver; }
-
        void
-       _M_notify(bool __all, bool __bare = false)
-       {
-         if (_M_laundered())
-           {
-             __atomic_fetch_add(_M_addr, 1, __ATOMIC_ACQ_REL);
-             __all = true;
-           }
-         _M_w._M_notify(_M_addr, __all, __bare);
-       }
+       _M_notify(bool __all, bool __bare = false) noexcept
+       { _M_w._M_notify(_M_addr, __all, __bare); }
 
        template<typename _Up, typename _ValFn,
                 typename _Spin = __default_spin_policy>
@@ -332,7 +331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              }
            else
              {
-               __atomic_load(__addr, &__val, __ATOMIC_RELAXED);
+               __atomic_load(__addr, &__val, __ATOMIC_ACQUIRE);
              }
            return __atomic_spin(__pred, __spin);
          }
@@ -353,7 +352,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                     __platform_wait_t& __val,
                     _Spin __spin = _Spin{ })
          {
-           __atomic_load(__addr, &__val, __ATOMIC_RELAXED);
+           __atomic_load(__addr, &__val, __ATOMIC_ACQUIRE);
            return __atomic_spin(__pred, __spin);
          }
 
@@ -388,12 +387,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          void
          _M_do_wait_v(_Tp __old, _ValFn __vfn)
          {
-           __platform_wait_t __val;
-           if (__base_type::_M_do_spin_v(__old, __vfn, __val))
-             return;
-
            do
              {
+               __platform_wait_t __val;
+               if (__base_type::_M_do_spin_v(__old, __vfn, __val))
+                 return;
                __base_type::_M_w._M_do_wait(__base_type::_M_addr, __val);
              }
            while (__detail::__atomic_compare(__old, __vfn()));
@@ -478,5 +476,5 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
-#endif // GTHREADS || LINUX_FUTEX
+#endif // __glibcxx_atomic_wait
 #endif // _GLIBCXX_ATOMIC_WAIT_H