This defines __platform_wait, __platform_notify, and
__platform_wait_until for darwin, making use of the futex syscall.
libstdc++-v3/ChangeLog:
PR libstdc++/120527
* include/bits/atomic_wait.h [__OpenBSD__]: Reuse Linux
definitions of __platform_wait_t and __platform_wait_uses_type.
* src/c++20/atomic.cc [__OpenBSD__] (_GLIBCXX_HAVE_PLATFORM_WAIT)
(__platform_wait, __platform_notify, __platform_wait_until):
Define.
---
Untested, so I don't plan to commit this.
libstdc++-v3/include/bits/atomic_wait.h | 3 +-
libstdc++-v3/src/c++20/atomic.cc | 40 +++++++++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/libstdc++-v3/include/bits/atomic_wait.h
b/libstdc++-v3/include/bits/atomic_wait.h
index af4b2ab46a04..22877ad46755 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -55,7 +55,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= is_scalar_v<_Tp> && (sizeof(_Tp) <= sizeof(__UINT64_TYPE__));
}
-#if defined _GLIBCXX_HAVE_LINUX_FUTEX || defined __DragonFly__
+#if defined _GLIBCXX_HAVE_LINUX_FUTEX || defined __DragonFly__ \
+ || defined __OpenBSD__
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 87a1e24d8980..a788000fab7b 100644
--- a/libstdc++-v3/src/c++20/atomic.cc
+++ b/libstdc++-v3/src/c++20/atomic.cc
@@ -56,6 +56,10 @@ __ulock_wake(uint32_t operation, void* addr, uint64_t
wake_value);
#elif defined __DragonFly__
# include <unistd.h>
# define _GLIBCXX_HAVE_PLATFORM_WAIT 1
+#elif defined __OpenBSD__
+# include <sys/time.h>
+# include <sys/futex.h>
+# define _GLIBCXX_HAVE_PLATFORM_WAIT 1
#endif
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
@@ -242,6 +246,42 @@ namespace
}
return true;
}
+#elif defined __OpenBSD__
+ void
+ __platform_wait(const void* addr, uint64_t val, int /* obj_sz */) noexcept
+ {
+ if (futex(static_cast<uint32_t*>(const_cast<void*>(addr)), FUTEX_WAIT,
+ (int)val, nullptr, nullptr))
+ if (errno == EAGAIN || errno == EINTR || errno == ECANCELED)
+ return;
+ __throw_system_error(errno);
+ }
+
+ void
+ __platform_notify(const void* addr, bool all, int /* obj_sz */) noexcept
+ {
+ futex(static_cast<uint32_t*>(const_cast<void*>(addr)), FUTEX_WAKE,
+ all ? INT_MAX : 1, nullptr, nullptr);
+ }
+
+ // 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
+ {
+ struct timespec timeout = chrono::__to_timeout_timespec(atime);
+ if (futex(static_cast<uint32_t*>(const_cast<void*>(addr)), FUTEX_WAIT,
+ (int)val, &timeout, nullptr))
+ {
+ if (errno == ETIMEDOUT)
+ return false;
+ if (errno == EAGAIN || errno == EINTR || errno == ECANCELED)
+ return true;
+ __throw_system_error(errno);
+ }
+ return true;
+ }
#endif // HAVE_LINUX_FUTEX
// The state used by atomic waiting and notifying functions.
--
2.51.1