This defines __platform_wait, __platform_notify, and
__platform_wait_until for DragonFly, making use of the umtx_sleep and
umtx_wakeup functions.

libstdc++-v3/ChangeLog:

        PR libstdc++/120527
        * include/bits/atomic_wait.h [__DragonFly__]: Reuse Linux
        definitions of __platform_wait_t and __platform_wait_uses_type.
        * src/c++20/atomic.cc [__DragonFly__] (_GLIBCXX_HAVE_PLATFORM_WAIT)
        (__platform_wait, __platform_notify, __platform_wait_until):
        Define.
---

Untested, not to be committed.

 libstdc++-v3/include/bits/atomic_wait.h |  2 +-
 libstdc++-v3/src/c++20/atomic.cc        | 40 +++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
b/libstdc++-v3/include/bits/atomic_wait.h
index 22727e2101d9..6d72b328da31 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            && (sizeof(_Tp) <= sizeof(__UINT64_TYPE__));
   }
 
-#if defined _GLIBCXX_HAVE_LINUX_FUTEX
+#if defined _GLIBCXX_HAVE_LINUX_FUTEX || defined __DragonFly__
   namespace __detail
   {
     // Use futex syscall on int objects.
diff --git a/libstdc++-v3/src/c++20/atomic.cc b/libstdc++-v3/src/c++20/atomic.cc
index 918b045adcd5..749071095332 100644
--- a/libstdc++-v3/src/c++20/atomic.cc
+++ b/libstdc++-v3/src/c++20/atomic.cc
@@ -54,6 +54,9 @@ __ulock_wake(uint32_t operation, void* addr, uint64_t 
wake_value);
 # include <sys/umtx.h>
 # include <sys/time.h>
 # define _GLIBCXX_HAVE_PLATFORM_WAIT 1
+#elif defined __DragonFly__
+# include <unistd.h>
+# define _GLIBCXX_HAVE_PLATFORM_WAIT 1
 #endif
 
 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
@@ -216,6 +219,43 @@ namespace
       }
     return true;
   }
+#elif defined __DragonFly__
+  void
+  __platform_wait(const void* addr, uint64_t val, int /* obj_sz */) noexcept
+  {
+    if (umtx_sleep(static_cast<const int*>(addr), (int)val, 0))
+      if (errno == EINVAL)
+       __throw_system_error(errno);
+  }
+
+  void
+  __platform_notify(const void* addr, bool all, int /* obj_sz */) noexcept
+  {
+    umtx_wakeup(static_cast<const int*>(addr), !all);
+  }
+
+  // returns true if wait ended before timeout
+  bool
+  __platform_wait_until(const void* addr, uint64_t val,
+                       const __wait_clock_t::time_point& atime,
+                       int /* obj_sz */) noexcept
+  {
+    auto reltime
+      = chrono::ceil<chrono::microseconds>(__wait_clock_t::now() - atime);
+    if (reltime <= reltime.zero())
+      return false;
+    int timeout = numeric_limits<int>::max();
+    if (std::cmp_less(reltime.count(), timeout)
+       timeout = reltime.count();
+    if (umtx_sleep(static_cast<const int*>(addr), (int)val, reltime.count()))
+      {
+       if (errno == EWOULDBLOCK)
+         return timeout == numeric_limits<int>::max();
+       if (errno == EINVAL)
+         __throw_system_error(errno);
+      }
+    return true;
+  }
 #endif // HAVE_LINUX_FUTEX
 
   // The state used by atomic waiting and notifying functions.
-- 
2.51.1

Reply via email to