diff --git a/src/snmalloc/pal/pal_openbsd.h b/src/snmalloc/pal/pal_openbsd.h index fa15750..b0ae586 100644 --- a/src/snmalloc/pal/pal_openbsd.h +++ b/src/snmalloc/pal/pal_openbsd.h @@ -3,6 +3,8 @@ #if defined(__OpenBSD__) && !defined(_KERNEL) # include "pal_bsd.h" +# include + namespace snmalloc { /** @@ -21,7 +23,50 @@ namespace snmalloc * declared explicitly to remind anyone who modifies this class that they * should add any required features. */ - static constexpr uint64_t pal_features = PALBSD::pal_features; + static constexpr uint64_t pal_features = + PALBSD::pal_features | WaitOnAddress; + + using WaitingWord = int; + + template + static void wait_on_address(std::atomic& addr, T expected) + { + int backup = errno; + static_assert( + sizeof(T) == sizeof(WaitingWord) && alignof(T) == alignof(WaitingWord), + "T must be the same size and alignment as WaitingWord"); + while (addr.load(std::memory_order_relaxed) == expected) + { + long ret = futex( + (uint32_t*)&addr, + FUTEX_WAIT_PRIVATE, + static_cast(expected), + nullptr, + nullptr); + + if (ret == 0) + break; + } + errno = backup; + } + + template + static void notify_one_on_address(std::atomic& addr) + { + static_assert( + sizeof(T) == sizeof(WaitingWord) && alignof(T) == alignof(WaitingWord), + "T must be the same size and alignment as WaitingWord"); + futex((uint32_t*)&addr, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr); + } + + template + static void notify_all_on_address(std::atomic& addr) + { + static_assert( + sizeof(T) == sizeof(WaitingWord) && alignof(T) == alignof(WaitingWord), + "T must be the same size and alignment as WaitingWord"); + futex((uint32_t*)&addr, FUTEX_WAKE_PRIVATE, INT_MAX, nullptr, nullptr); + } }; } // namespace snmalloc #endif