atomic.hpp: add atomic wait mask support

This commit is contained in:
Nekotekina 2019-09-12 15:43:26 +03:00
parent c59cb1bdd3
commit 2fc8844315
3 changed files with 16 additions and 15 deletions

View file

@ -2394,7 +2394,7 @@ s64 spu_thread::get_ch_value(u32 ch)
return -1; return -1;
} }
vm::reservation_notifier(raddr, 128).wait(rtime, atomic_wait_timeout{30000}); vm::reservation_notifier(raddr, 128).wait<UINT64_MAX & -128>(rtime, atomic_wait_timeout{30000});
} }
check_state(); check_state();

View file

@ -30,14 +30,14 @@ static thread_local bool(*s_tls_wait_cb)(const void* data) = [](const void*)
return true; return true;
}; };
static inline bool ptr_cmp(const void* data, std::size_t size, u64 old_value) static inline bool ptr_cmp(const void* data, std::size_t size, u64 old_value, u64 mask)
{ {
switch (size) switch (size)
{ {
case 1: return reinterpret_cast<const atomic_t<u8>*>(data)->load() == old_value; case 1: return (reinterpret_cast<const atomic_t<u8>*>(data)->load() & mask) == (old_value & mask);
case 2: return reinterpret_cast<const atomic_t<u16>*>(data)->load() == old_value; case 2: return (reinterpret_cast<const atomic_t<u16>*>(data)->load() & mask) == (old_value & mask);
case 4: return reinterpret_cast<const atomic_t<u32>*>(data)->load() == old_value; case 4: return (reinterpret_cast<const atomic_t<u32>*>(data)->load() & mask) == (old_value & mask);
case 8: return reinterpret_cast<const atomic_t<u64>*>(data)->load() == old_value; case 8: return (reinterpret_cast<const atomic_t<u64>*>(data)->load() & mask) == (old_value & mask);
} }
return false; return false;
@ -78,7 +78,7 @@ namespace
return s_waiter_maps[std::hash<const void*>()(ptr) % std::size(s_waiter_maps)]; return s_waiter_maps[std::hash<const void*>()(ptr) % std::size(s_waiter_maps)];
} }
void fallback_wait(const void* data, std::size_t size, u64 old_value, u64 timeout) void fallback_wait(const void* data, std::size_t size, u64 old_value, u64 timeout, u64 mask)
{ {
auto& wmap = get_fallback_map(data); auto& wmap = get_fallback_map(data);
@ -90,7 +90,7 @@ namespace
// Update node key // Update node key
s_tls_waiter.key() = data; s_tls_waiter.key() = data;
if (std::unique_lock lock(wmap.mutex); ptr_cmp(data, size, old_value) && s_tls_wait_cb(data)) if (std::unique_lock lock(wmap.mutex); ptr_cmp(data, size, old_value, mask) && s_tls_wait_cb(data))
{ {
// Add node to the waiter list // Add node to the waiter list
const auto iter = wmap.list.insert(std::move(s_tls_waiter)); const auto iter = wmap.list.insert(std::move(s_tls_waiter));
@ -152,9 +152,9 @@ namespace
#if !defined(_WIN32) && !defined(__linux__) #if !defined(_WIN32) && !defined(__linux__)
void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value, u64 timeout) void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value, u64 timeout, u64 mask)
{ {
fallback_wait(data, size, old_value, timeout); fallback_wait(data, size, old_value, timeout, mask);
} }
void atomic_storage_futex::notify_one(const void* data) void atomic_storage_futex::notify_one(const void* data)
@ -169,7 +169,7 @@ void atomic_storage_futex::notify_all(const void* data)
#else #else
void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value, u64 timeout) void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value, u64 timeout, u64 mask)
{ {
if (!timeout) if (!timeout)
{ {
@ -222,9 +222,9 @@ void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_valu
if (fallback) if (fallback)
{ {
fallback_wait(data, size, old_value, timeout); fallback_wait(data, size, old_value, timeout, mask);
} }
else if (ptr_cmp(data, size, old_value) && s_tls_wait_cb(data)) else if (ptr_cmp(data, size, old_value, mask) && s_tls_wait_cb(data))
{ {
#ifdef _WIN32 #ifdef _WIN32
LARGE_INTEGER qw; LARGE_INTEGER qw;

View file

@ -20,7 +20,7 @@ private:
template <typename T> template <typename T>
friend class atomic_t; friend class atomic_t;
static void wait(const void* data, std::size_t size, u64 old_value, u64 timeout); static void wait(const void* data, std::size_t size, u64 old_value, u64 timeout, u64 mask);
static void notify_one(const void* data); static void notify_one(const void* data);
static void notify_all(const void* data); static void notify_all(const void* data);
@ -1134,9 +1134,10 @@ public:
return atomic_storage<type>::btr(m_data, bit); return atomic_storage<type>::btr(m_data, bit);
} }
template <u64 Mask = 0xffff'ffff'ffff'ffff>
void wait(type old_value, atomic_wait_timeout timeout = atomic_wait_timeout::inf) const noexcept void wait(type old_value, atomic_wait_timeout timeout = atomic_wait_timeout::inf) const noexcept
{ {
atomic_storage_futex::wait(&m_data, sizeof(T), std::bit_cast<get_uint_t<sizeof(T)>>(old_value), static_cast<u64>(timeout)); atomic_storage_futex::wait(&m_data, sizeof(T), std::bit_cast<get_uint_t<sizeof(T)>>(old_value), static_cast<u64>(timeout), Mask);
} }
void notify_one() noexcept void notify_one() noexcept