[libc++] Use Fuchsia futex operations (#133571)
The basic futex operations have always been available on Fuchsia. Wire them up to properly support C++20 atomic notify_*/wait.
This commit is contained in:
parent
be072baa33
commit
fbdfff47c7
3 changed files with 41 additions and 6 deletions
|
|
@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
// instead.
|
||||
#if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
|
||||
|
||||
# ifdef __linux__
|
||||
# if defined(__linux__) || defined(__Fuchsia__)
|
||||
using __cxx_contention_t _LIBCPP_NODEBUG = int32_t;
|
||||
# elif defined(__APPLE__)
|
||||
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
|
||||
|
|
@ -37,15 +37,15 @@ using __cxx_contention_t _LIBCPP_NODEBUG = int32_t;
|
|||
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
|
||||
# else
|
||||
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
|
||||
# endif // __linux__
|
||||
# endif // __linux__ || __Fuchsia__
|
||||
|
||||
#else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
|
||||
|
||||
# if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__))
|
||||
# if defined(__linux__) || defined(__Fuchsia__) || (defined(_AIX) && !defined(__64BIT__))
|
||||
using __cxx_contention_t _LIBCPP_NODEBUG = int32_t;
|
||||
# else
|
||||
using __cxx_contention_t _LIBCPP_NODEBUG = int64_t;
|
||||
# endif // __linux__ || (_AIX && !__64BIT__)
|
||||
# endif // __linux__ || __Fuchsia__ || (_AIX && !__64BIT__)
|
||||
|
||||
#endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__))
|
||||
#if defined(__linux__) || defined(__Fuchsia__) || (defined(_AIX) && !defined(__64BIT__))
|
||||
using __cxx_contention_t = int32_t;
|
||||
#else
|
||||
using __cxx_contention_t = int64_t;
|
||||
#endif // __linux__ || (_AIX && !__64BIT__)
|
||||
#endif // __linux__ || __Fuchsia__ || (_AIX && !__64BIT__)
|
||||
|
||||
using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@
|
|||
# include <memory>
|
||||
# include <windows.h>
|
||||
|
||||
#elif defined(__Fuchsia__)
|
||||
|
||||
# include <zircon/syscalls.h>
|
||||
|
||||
#else // <- Add other operating systems here
|
||||
|
||||
// Baseline needs no new headers
|
||||
|
|
@ -254,6 +258,37 @@ static void __platform_wake_by_address(void const* __ptr, bool __notify_one) {
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(__Fuchsia__)
|
||||
|
||||
template <std::size_t _Size>
|
||||
static inline zx_futex_t const* __get_zx_futex(void const* __ptr) {
|
||||
static_assert(_Size == sizeof(zx_futex_t), "Can only wait/wake on zx_futex_t-compatible value");
|
||||
|
||||
// Implicitly link against the vDSO system call ABI without requiring the
|
||||
// final link to specify -lzircon explicitly when statically linking libc++.
|
||||
# pragma comment(lib, "zircon")
|
||||
|
||||
return reinterpret_cast<zx_futex_t const*>(__ptr);
|
||||
}
|
||||
|
||||
template <std::size_t _Size, class MaybeTimeout>
|
||||
static void __platform_wait_on_address(void const* __ptr, void const* __val, MaybeTimeout maybe_timeout_ns) {
|
||||
zx_futex_t val;
|
||||
std::memcpy(&val, __val, _Size);
|
||||
zx_instant_mono_t deadline;
|
||||
if constexpr (is_same_v<MaybeTimeout, NoTimeout>) {
|
||||
deadline = ZX_TIME_INFINITE;
|
||||
} else {
|
||||
deadline = _zx_deadline_after(maybe_timeout_ns);
|
||||
}
|
||||
_zx_futex_wait(__get_zx_futex<_Size>(__ptr), val, ZX_HANDLE_INVALID, deadline);
|
||||
}
|
||||
|
||||
template <std::size_t _Size>
|
||||
static void __platform_wake_by_address(void const* __ptr, bool __notify_one) {
|
||||
_zx_futex_wake(__get_zx_futex<_Size>(__ptr), __notify_one ? 1 : UINT32_MAX);
|
||||
}
|
||||
|
||||
#else // <- Add other operating systems here
|
||||
|
||||
// Baseline is just a timed backoff
|
||||
|
|
|
|||
Loading…
Reference in a new issue