mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 06:51:26 +12:00
Fat atomics: implement exchange() and compare_exchange()
Also includes compare_and_swap() and compare_and_swap_test(). Also includes fixes for load(), store(), and atomic_op().
This commit is contained in:
parent
cb14805d78
commit
17f3a114be
1 changed files with 53 additions and 2 deletions
|
@ -1176,7 +1176,6 @@ class atomic_with_lock_bit
|
||||||
static_assert(std::is_pointer_v<T> == (BitWidth == 0), "BitWidth should be 0 for pointers");
|
static_assert(std::is_pointer_v<T> == (BitWidth == 0), "BitWidth should be 0 for pointers");
|
||||||
static_assert(!std::is_pointer_v<T> || (alignof(std::remove_pointer_t<T>) >= 4), "Pointer type should have align 4 or more");
|
static_assert(!std::is_pointer_v<T> || (alignof(std::remove_pointer_t<T>) >= 4), "Pointer type should have align 4 or more");
|
||||||
|
|
||||||
// Use the most significant bit as a mutex
|
|
||||||
atomic_t<type> m_data;
|
atomic_t<type> m_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1255,7 +1254,6 @@ public:
|
||||||
// Try to set dirty bit if not set already
|
// Try to set dirty bit if not set already
|
||||||
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
||||||
{
|
{
|
||||||
// Situation changed
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1301,6 +1299,7 @@ public:
|
||||||
{
|
{
|
||||||
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
||||||
{
|
{
|
||||||
|
old_val = m_data.load();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1313,6 +1312,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void store(T value)
|
void store(T value)
|
||||||
|
{
|
||||||
|
static_cast<void>(exchange(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
T exchange(T value)
|
||||||
{
|
{
|
||||||
type old_val = m_data.load();
|
type old_val = m_data.load();
|
||||||
|
|
||||||
|
@ -1322,6 +1326,7 @@ public:
|
||||||
{
|
{
|
||||||
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
||||||
{
|
{
|
||||||
|
old_val = m_data.load();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1329,6 +1334,51 @@ public:
|
||||||
m_data.wait(old_val);
|
m_data.wait(old_val);
|
||||||
old_val = m_data.load();
|
old_val = m_data.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<T>(clamp_value(old_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
T compare_and_swap(T cmp, T exch)
|
||||||
|
{
|
||||||
|
static_cast<void>(compare_exchange(cmp, exch));
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compare_and_swap_test(T cmp, T exch)
|
||||||
|
{
|
||||||
|
return compare_exchange(cmp, exch);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compare_exchange(T& cmp_and_old, T exch)
|
||||||
|
{
|
||||||
|
type old_val = m_data.load();
|
||||||
|
type expected = clamp_value(reinterpret_cast<type>(cmp_and_old));
|
||||||
|
type new_val = clamp_value(reinterpret_cast<type>(exch));
|
||||||
|
|
||||||
|
while (is_locked(old_val) || (old_val == expected && !m_data.compare_and_swap_test(expected, new_val))) [[unlikely]]
|
||||||
|
{
|
||||||
|
if (old_val == expected)
|
||||||
|
{
|
||||||
|
old_val = m_data.load();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((old_val & c_dirty) == 0)
|
||||||
|
{
|
||||||
|
if (!m_data.compare_and_swap_test(old_val, old_val | c_dirty))
|
||||||
|
{
|
||||||
|
old_val = m_data.load();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data.wait(old_val);
|
||||||
|
old_val = m_data.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmp_and_old = reinterpret_cast<T>(clamp_value(old_val));
|
||||||
|
|
||||||
|
return clamp_value(old_val) == expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F, typename RT = std::invoke_result_t<F, T&>>
|
template <typename F, typename RT = std::invoke_result_t<F, T&>>
|
||||||
|
@ -1345,6 +1395,7 @@ public:
|
||||||
{
|
{
|
||||||
if (!m_data.compare_and_swap_test(old, old | c_dirty))
|
if (!m_data.compare_and_swap_test(old, old | c_dirty))
|
||||||
{
|
{
|
||||||
|
old = m_data.load();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue