1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

utils/atomic.hpp: Make atomic_op reject non-non-const lvalue

This commit is contained in:
Elad 2024-11-02 08:36:35 +02:00
parent 1417f9b7de
commit 85d1649696
6 changed files with 45 additions and 15 deletions

View File

@ -472,7 +472,7 @@ error_code cellSyncQueuePush(ppu_thread& ppu, vm::ptr<CellSyncQueue> queue, vm::
u32 position;
while (!queue->ctrl.atomic_op([&](auto& ctrl)
while (!queue->ctrl.atomic_op([&](CellSyncQueue::ctrl_t& ctrl)
{
return CellSyncQueue::try_push_begin(ctrl, depth, &position);
}))
@ -509,7 +509,7 @@ error_code cellSyncQueueTryPush(vm::ptr<CellSyncQueue> queue, vm::cptr<void> buf
u32 position;
while (!queue->ctrl.atomic_op([&](auto& ctrl)
while (!queue->ctrl.atomic_op([&](CellSyncQueue::ctrl_t& ctrl)
{
return CellSyncQueue::try_push_begin(ctrl, depth, &position);
}))
@ -543,7 +543,7 @@ error_code cellSyncQueuePop(ppu_thread& ppu, vm::ptr<CellSyncQueue> queue, vm::p
u32 position;
while (!queue->ctrl.atomic_op([&](auto& ctrl)
while (!queue->ctrl.atomic_op([&](CellSyncQueue::ctrl_t& ctrl)
{
return CellSyncQueue::try_pop_begin(ctrl, depth, &position);
}))
@ -580,7 +580,7 @@ error_code cellSyncQueueTryPop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffe
u32 position;
while (!queue->ctrl.atomic_op([&](auto& ctrl)
while (!queue->ctrl.atomic_op([&](CellSyncQueue::ctrl_t& ctrl)
{
return CellSyncQueue::try_pop_begin(ctrl, depth, &position);
}))
@ -614,7 +614,7 @@ error_code cellSyncQueuePeek(ppu_thread& ppu, vm::ptr<CellSyncQueue> queue, vm::
u32 position;
while (!queue->ctrl.atomic_op([&](auto& ctrl)
while (!queue->ctrl.atomic_op([&](CellSyncQueue::ctrl_t& ctrl)
{
return CellSyncQueue::try_peek_begin(ctrl, depth, &position);
}))
@ -651,7 +651,7 @@ error_code cellSyncQueueTryPeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buff
u32 position;
while (!queue->ctrl.atomic_op([&](auto& ctrl)
while (!queue->ctrl.atomic_op([&](CellSyncQueue::ctrl_t& ctrl)
{
return CellSyncQueue::try_peek_begin(ctrl, depth, &position);
}))

View File

@ -2698,7 +2698,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
bool ok = false;
std::tie(old, ok) = bits->fetch_op([&](auto& v)
std::tie(old, ok) = bits->fetch_op([&](u128& v)
{
if (v & wmask)
{
@ -2796,7 +2796,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
res += 127;
// Release bits and notify
bits->atomic_op([&](auto& v)
bits->atomic_op([&](u128& v)
{
v &= ~wmask;
});

View File

@ -1852,7 +1852,7 @@ void lv2_obj::schedule_all(u64 current_time)
target->start_time = 0;
if ((target->state.fetch_op(FN(x += cpu_flag::signal, x -= cpu_flag::suspend, x-= remove_yield, void())) & (cpu_flag::wait + cpu_flag::signal)) != cpu_flag::wait)
if ((target->state.fetch_op(AOFN(x += cpu_flag::signal, x -= cpu_flag::suspend, x-= remove_yield, void())) & (cpu_flag::wait + cpu_flag::signal)) != cpu_flag::wait)
{
continue;
}

View File

@ -142,7 +142,7 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id, [&, notify = lv2_obj::notify_all_t()](lv2_lwmutex& mutex)
{
if (s32 signal = mutex.lv2_control.fetch_op([](auto& data)
if (s32 signal = mutex.lv2_control.fetch_op([](lv2_lwmutex::control_data_t& data)
{
if (data.signaled)
{
@ -297,7 +297,7 @@ error_code _sys_lwmutex_trylock(ppu_thread& ppu, u32 lwmutex_id)
const auto mutex = idm::check<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex)
{
auto [_, ok] = mutex.lv2_control.fetch_op([](auto& data)
auto [_, ok] = mutex.lv2_control.fetch_op([](lv2_lwmutex::control_data_t& data)
{
if (data.signaled & 1)
{

View File

@ -434,7 +434,7 @@ static u32 cond_alloc(uptr iptr, u32 tls_slot = -1)
});
// Set lowest clear bit
const u64 bits = s_cond_bits[level3].fetch_op(FN(x |= x + 1, void()));
const u64 bits = s_cond_bits[level3].fetch_op(AOFN(x |= x + 1, void()));
// Find lowest clear bit (before it was set in fetch_op)
const u32 id = level3 * 64 + std::countr_one(bits);
@ -503,9 +503,9 @@ static void cond_free(u32 cond_id, u32 tls_slot = -1)
// Release the semaphore tree in the reverse order
s_cond_bits[cond_id / 64] &= ~(1ull << (cond_id % 64));
s_cond_sem3[level2].atomic_op(FN(x -= u128{1} << (level3 * 7)));
s_cond_sem2[level1].atomic_op(FN(x -= u128{1} << (level2 * 11)));
s_cond_sem1.atomic_op(FN(x -= u128{1} << (level1 * 14)));
s_cond_sem3[level2].atomic_op(AOFN(x -= u128{1} << (level3 * 7)));
s_cond_sem2[level1].atomic_op(AOFN(x -= u128{1} << (level2 * 11)));
s_cond_sem1.atomic_op(AOFN(x -= u128{1} << (level1 * 14)));
}
static cond_handle* cond_id_lock(u32 cond_id, uptr iptr = 0)

View File

@ -1233,6 +1233,7 @@ public:
// Atomic operation; returns old value, or pair of old value and return value (cancel op if evaluates to false)
template <typename F, typename RT = std::invoke_result_t<F, T&>>
requires (!std::is_invocable_v<F, const T> && !std::is_invocable_v<F, volatile T>)
std::conditional_t<std::is_void_v<RT>, type, std::pair<type, RT>> fetch_op(F func)
{
type _new, old = atomic_storage<type>::load(m_data);
@ -1264,6 +1265,7 @@ public:
// Atomic operation; returns function result value, function is the lambda
template <typename F, typename RT = std::invoke_result_t<F, T&>>
requires (!std::is_invocable_v<F, const T> && !std::is_invocable_v<F, volatile T>)
RT atomic_op(F func)
{
type _new, old = atomic_storage<type>::load(m_data);
@ -1798,3 +1800,31 @@ struct std::common_type<T, atomic_t<T2, Align2>> : std::common_type<std::common_
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
namespace utils
{
template <typename F>
struct aofn_helper
{
F f;
aofn_helper(F&& f) noexcept
: f(std::forward<F>(f))
{
}
template <typename Arg> requires (std::is_same_v<std::remove_reference_t<Arg>, std::remove_cvref_t<Arg>> && !std::is_rvalue_reference_v<Arg>)
auto operator()(Arg& arg) const noexcept
{
return f(std::forward<Arg&>(arg));
}
};
template <typename F>
aofn_helper(F&& f) -> aofn_helper<F>;
}
// Shorter lambda for non-cv qualified L-values
// For use with atomic operations
#define AOFN(...) \
::utils::aofn_helper([&](auto& x) { return (__VA_ARGS__); })