25#ifndef JOIN_CORE_FUTEX_HPP
26#define JOIN_CORE_FUTEX_HPP
33#include <sys/syscall.h>
34#include <linux/futex.h>
42#if defined(__SANITIZE_THREAD__)
44#elif defined(__has_feature)
45#if __has_feature(thread_sanitizer)
51#include <sanitizer/tsan_interface.h>
52#define JOIN_TSAN_ACQUIRE(addr) __tsan_acquire (addr)
53#define JOIN_TSAN_RELEASE(addr) __tsan_release (addr)
55#define JOIN_TSAN_ACQUIRE(addr)
56#define JOIN_TSAN_RELEASE(addr)
64 template <
class LockPolicy>
112 LockPolicy::lock (_futex, FUTEX_PRIVATE_FLAG);
121 return LockPolicy::tryLock (_futex);
129 LockPolicy::unlock (_futex, FUTEX_PRIVATE_FLAG);
143 alignas (4) std::atomic_uint32_t _futex;
149 template <
class LockPolicy>
197 LockPolicy::lock (_futex, 0);
206 return LockPolicy::tryLock (_futex);
214 LockPolicy::unlock (_futex, 0);
228 alignas (4) std::atomic_uint32_t _futex;
242 static void lock (std::atomic_uint32_t& futex,
int flags)
noexcept
244 uint32_t expected = 0;
245 if (futex.compare_exchange_strong (expected, 1, std::memory_order_acquire, std::memory_order_relaxed))
253 futex.compare_exchange_strong (expected, 2, std::memory_order_relaxed, std::memory_order_relaxed))
255 ::syscall (SYS_futex,
reinterpret_cast<uint32_t*
> (&futex), FUTEX_WAIT | flags, 2,
nullptr,
nullptr,
260 while (!futex.compare_exchange_strong (expected, 2, std::memory_order_acquire, std::memory_order_relaxed));
268 static bool tryLock (std::atomic_uint32_t& futex)
noexcept
270 uint32_t expected = 0;
271 return futex.compare_exchange_strong (expected, 1, std::memory_order_acquire, std::memory_order_relaxed);
279 static void unlock (std::atomic_uint32_t& futex,
int flags)
noexcept
281 if (futex.exchange (0, std::memory_order_release) == 2)
283 ::syscall (SYS_futex,
reinterpret_cast<uint32_t*
> (&futex), FUTEX_WAKE | flags, 1,
nullptr,
nullptr, 0);
299 static void lock (std::atomic_uint32_t& futex,
int flags)
noexcept
301 uint32_t expected = 0;
302 if (futex.compare_exchange_strong (expected,
static_cast<uint32_t
> (
Thread::currentId ()),
303 std::memory_order_acquire, std::memory_order_relaxed))
308 while (::syscall (SYS_futex,
reinterpret_cast<uint32_t*
> (&futex), FUTEX_LOCK_PI | flags, 0,
nullptr,
327 static bool tryLock (std::atomic_uint32_t& futex)
noexcept
329 uint32_t expected = 0;
330 return futex.compare_exchange_strong (expected,
static_cast<uint32_t
> (
Thread::currentId ()),
331 std::memory_order_acquire, std::memory_order_relaxed);
339 static void unlock (std::atomic_uint32_t& futex,
int flags)
noexcept
342 if (futex.compare_exchange_strong (expected, 0, std::memory_order_release, std::memory_order_relaxed))
348 ::syscall (SYS_futex,
reinterpret_cast<uint32_t*
> (&futex), FUTEX_UNLOCK_PI | flags, 0,
nullptr,
nullptr,
Futex-based mutex for intra-process locking.
Definition futex.hpp:66
BasicFutex(BasicFutex &&other)=delete
move constructor.
BasicFutex() noexcept
default constructor.
Definition futex.hpp:71
void lock() noexcept
lock the futex, blocking until it becomes available.
Definition futex.hpp:110
void unlock() noexcept
unlock the futex.
Definition futex.hpp:127
~BasicFutex()=default
destructor.
BasicFutex & operator=(const BasicFutex &other)=delete
copy assignment.
BasicFutex(const BasicFutex &other)=delete
copy constructor.
bool tryLock() noexcept
try to lock the futex without blocking.
Definition futex.hpp:119
std::atomic_uint32_t * handle() noexcept
get a pointer to the underlying futex word.
Definition futex.hpp:136
Futex-based mutex suitable for inter-process locking via shared memory.
Definition futex.hpp:151
bool tryLock() noexcept
try to lock the futex without blocking.
Definition futex.hpp:204
BasicSharedFutex(const BasicSharedFutex &other)=delete
copy constructor.
BasicSharedFutex(BasicSharedFutex &&other)=delete
move constructor.
BasicSharedFutex & operator=(const BasicSharedFutex &other)=delete
copy assignment.
std::atomic_uint32_t * handle() noexcept
get a pointer to the underlying futex word.
Definition futex.hpp:221
void lock() noexcept
lock the futex, blocking until it becomes available.
Definition futex.hpp:195
void unlock() noexcept
unlock the futex.
Definition futex.hpp:212
~BasicSharedFutex()=default
destructor.
BasicSharedFutex() noexcept
default constructor.
Definition futex.hpp:156
priority inheritance policy.
Definition futex.hpp:292
static void lock(std::atomic_uint32_t &futex, int flags) noexcept
lock the futex.
Definition futex.hpp:299
static bool tryLock(std::atomic_uint32_t &futex) noexcept
try to lock the futex.
Definition futex.hpp:327
static void unlock(std::atomic_uint32_t &futex, int flags) noexcept
unlock the futex.
Definition futex.hpp:339
no priority inheritance policy.
Definition futex.hpp:235
static void lock(std::atomic_uint32_t &futex, int flags) noexcept
lock the futex.
Definition futex.hpp:242
static bool tryLock(std::atomic_uint32_t &futex) noexcept
try to lock the futex.
Definition futex.hpp:268
static void unlock(std::atomic_uint32_t &futex, int flags) noexcept
unlock the futex.
Definition futex.hpp:279
static pid_t currentId() noexcept
get calling thread id.
Definition thread.hpp:346
#define JOIN_TSAN_RELEASE(addr)
Definition futex.hpp:56
#define JOIN_TSAN_ACQUIRE(addr)
Definition futex.hpp:55
Definition acceptor.hpp:32