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:
parent
1417f9b7de
commit
85d1649696
@ -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);
|
||||
}))
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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__); })
|
||||
|
Loading…
Reference in New Issue
Block a user