2#include "gaia/config/config.h"
3#include "gaia/config/profiler.h"
8#include "gaia/core/utility.h"
9#include "gaia/mt/event.h"
14 inline static constexpr uint32_t WaitMaskAll = 0x7FFFFFFF;
15 inline static constexpr uint32_t WaitMaskAny = ~0u;
19 const std::atomic_uint32_t* pFutexValue =
nullptr;
20 uint32_t waitMask = WaitMaskAny;
25 GAIA_PROF_MUTEX(std::mutex, mtx);
30 static constexpr uint32_t BUCKET_SIZE = 37;
32 static FutexBucket& get(
const std::atomic_uint32_t* pFutexValue) {
34 return s_buckets[(uintptr_t(pFutexValue) >> 2) % BUCKET_SIZE];
69 static Result wait(
const std::atomic_uint32_t* pFutexValue, uint32_t expected, uint32_t waitMask) {
70 GAIA_PROF_SCOPE(futex::wait);
72 GAIA_ASSERT(waitMask != 0);
74 auto& bucket = detail::FutexBucket::get(pFutexValue);
75 auto& node = detail::t_WaitNode;
76 node.pFutexValue = pFutexValue;
77 node.waitMask = waitMask;
80 auto& mtx = GAIA_PROF_EXTRACT_MUTEX(bucket.mtx);
82 GAIA_PROF_LOCK_MARK(bucket.mtx);
84 const uint32_t futexValue = pFutexValue->load(std::memory_order_relaxed);
85 if (futexValue != expected)
88 node.pNext = bucket.pFirst;
89 bucket.pFirst = &node;
101 wake(
const std::atomic_uint32_t* pFutexValue, uint32_t wakeCount, uint32_t wakeMask = detail::WaitMaskAny) {
102 GAIA_PROF_SCOPE(futex::wake);
104 GAIA_ASSERT(wakeMask != 0);
106 auto& bucket = detail::FutexBucket::get(pFutexValue);
107 auto& mtx = GAIA_PROF_EXTRACT_MUTEX(bucket.mtx);
109 GAIA_PROF_LOCK_MARK(bucket.mtx);
111 uint32_t numAwoken = 0;
112 auto** ppNode = &bucket.pFirst;
113 for (
auto* pNode = *ppNode; numAwoken < wakeCount && pNode !=
nullptr; pNode = *ppNode) {
114 if (pNode->pFutexValue == pFutexValue && (pNode->waitMask & wakeMask) != 0) {
118 *ppNode = pNode->pNext;
119 pNode->pNext =
nullptr;
123 ppNode = &pNode->pNext;
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
An implementation of a simple futex (fast userspace mutex). Only wait and wake are implemented.
Definition futex.h:55
static Result wait(const std::atomic_uint32_t *pFutexValue, uint32_t expected, uint32_t waitMask)
Suspends the caller on the futex while its value remains expected.
Definition futex.h:69
static uint32_t wake(const std::atomic_uint32_t *pFutexValue, uint32_t wakeCount, uint32_t wakeMask=detail::WaitMaskAny)
Wakes up to wakeCount waiters whose waitMask matches wakeMask.
Definition futex.h:101
Result
Definition futex.h:56
@ WakeUp
Futex woken up as a result of wake()
@ Change
Futex value didn't match the expected one.