[llvm-branch-commits] [libcxx] 83833ee - [libc++] Fix FreeBSD atomic timed wait system call (#180400)

Cullen Rhodes via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Feb 18 00:23:20 PST 2026


Author: Hui
Date: 2026-02-18T08:23:12Z
New Revision: 83833ee0c30438fc1fa221c3ccea409c7e3ab9bf

URL: https://github.com/llvm/llvm-project/commit/83833ee0c30438fc1fa221c3ccea409c7e3ab9bf
DIFF: https://github.com/llvm/llvm-project/commit/83833ee0c30438fc1fa221c3ccea409c7e3ab9bf.diff

LOG: [libc++] Fix FreeBSD atomic timed wait system call (#180400)

This PR fixes atomic timed wait on FreeBSD platforms.

When we added timed wait support, on FreeBSD platform, we were looking
only the `UMTX_OP_WAIT` section of the FreeBSD doc
https://man.freebsd.org/cgi/man.cgi?query=_umtx_op&apropos=0&sektion=2&manpath=FreeBSD+16.0-CURRENT&format=html
. Somehow we missed the generic section that describes the timeout
parameter that applies to all operations. As a consequence, we missed
the part that the FreeBSD is expecting the `size` to be casted to
`uintptr_t`, then passed in to the `void*` parameter.

This PR fixes the issue by casting the type to what the system requires.

As drive by, this PR also
- uses simple `timespec` instead of the extended one
- as documentation suggests, "Interval counting is always performed by
the monotonic wall clock", and "If the flag is absent, the timeout value
is relative", which means that using the simple version is enough and
using the extended version is unnecessarily complex and might be
confusing to the people who aren't familiar with the API. And using
`timespec` is also consistent with the code in Linux case.
- directly reintepret_cast the comparison value to __cxx_contention_t
- As FreeBSD only supports the old ABI at the moment, the input is ever
going to be the exact type `__cxx_contention_t`. Copying to local buffer
is unnecessary and confusing.

(cherry picked from commit 180f7823cf1952e43b5f27c2deab3318c8d96ace)

Added: 
    

Modified: 
    libcxx/src/atomic.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp
index 9f2e0403f2318..3948f8b037976 100644
--- a/libcxx/src/atomic.cpp
+++ b/libcxx/src/atomic.cpp
@@ -144,22 +144,23 @@ static void __platform_wake_by_address(void const* __ptr, bool __notify_one) {
 template <std::size_t _Size, class MaybeTimeout>
 static void __platform_wait_on_address(void const* __ptr, void const* __val, MaybeTimeout maybe_timeout_ns) {
   static_assert(_Size == 8, "Can only wait on 8 bytes value");
-  alignas(__cxx_contention_t) char buffer[_Size];
-  std::memcpy(&buffer, const_cast<const void*>(__val), _Size);
+  // At the moment, FreeBSD is stuck on stable ABI, which only supports platform wait with __cxx_contention_t
+  // It is safe to reinterpret_cast the val as it is ever going to be passed a __cxx_contention_t under this ABI
+  // If in the future FreeBSD decides to experiment unstable ABI to support more types, this cast will no longer be
+  // safe.
+  __cxx_contention_t value = *reinterpret_cast<const __cxx_contention_t*>(__val);
   if constexpr (is_same_v<MaybeTimeout, NoTimeout>) {
-    _umtx_op(const_cast<void*>(__ptr), UMTX_OP_WAIT, *reinterpret_cast<__cxx_contention_t*>(&buffer), nullptr, nullptr);
+    _umtx_op(const_cast<void*>(__ptr), UMTX_OP_WAIT, value, nullptr, nullptr);
   } else {
-    _umtx_time ut;
-    ut._timeout.tv_sec  = maybe_timeout_ns / 1'000'000'000;
-    ut._timeout.tv_nsec = maybe_timeout_ns % 1'000'000'000;
-    ut._flags           = 0;               // Relative time (not absolute)
-    ut._clockid         = CLOCK_MONOTONIC; // Use monotonic clock
+    timespec timeout{};
+    timeout.tv_sec  = maybe_timeout_ns / 1'000'000'000;
+    timeout.tv_nsec = maybe_timeout_ns % 1'000'000'000;
 
     _umtx_op(const_cast<void*>(__ptr),
              UMTX_OP_WAIT,
-             *reinterpret_cast<__cxx_contention_t*>(&buffer),
-             reinterpret_cast<void*>(sizeof(ut)), // Pass size as uaddr
-             &ut);                                // Pass _umtx_time structure as uaddr2
+             value,
+             reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(timeout))),
+             &timeout);
   }
 }
 


        


More information about the llvm-branch-commits mailing list