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;
}
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();

View file

@ -30,14 +30,14 @@ static thread_local bool(*s_tls_wait_cb)(const void* data) = [](const void*)
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)
{
case 1: return reinterpret_cast<const atomic_t<u8>*>(data)->load() == old_value;
case 2: return reinterpret_cast<const atomic_t<u16>*>(data)->load() == old_value;
case 4: return reinterpret_cast<const atomic_t<u32>*>(data)->load() == old_value;
case 8: return reinterpret_cast<const atomic_t<u64>*>(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() & mask) == (old_value & mask);
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() & mask) == (old_value & mask);
}
return false;
@ -78,7 +78,7 @@ namespace
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);
@ -90,7 +90,7 @@ namespace
// Update node key
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
const auto iter = wmap.list.insert(std::move(s_tls_waiter));
@ -152,9 +152,9 @@ namespace
#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)
@ -169,7 +169,7 @@ void atomic_storage_futex::notify_all(const void* data)
#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)
{
@ -222,9 +222,9 @@ void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_valu
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
LARGE_INTEGER qw;

View file

@ -20,7 +20,7 @@ private:
template <typename 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_all(const void* data);
@ -1134,9 +1134,10 @@ public:
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
{
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