From 494953997e783d929c6392e281cc9344ac7effa0 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 15 Oct 2020 12:40:53 +0300 Subject: [PATCH] PPU/SPU: give up on conditional stores if locking fails Restores Non-TSX behaviour partially. --- rpcs3/Emu/Cell/PPUThread.cpp | 64 ++++++++++-------------------------- rpcs3/Emu/Cell/SPUThread.cpp | 21 ++++-------- 2 files changed, 25 insertions(+), 60 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 3e205dd454..82610bf088 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1595,27 +1595,20 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) }); } - while (res.bts(std::countr_zero(vm::rsrv_unique_lock))) + auto [_oldd, _ok] = res.fetch_op([&](u64& r) { - // Give up if reservation has been updated - if ((res & -128) != rtime) + if ((r & -128) != rtime || (r & 127)) { return false; } - if (ppu.state && ppu.check_state()) - { - return false; - } - else - { - busy_wait(100); - } - } + r += vm::rsrv_unique_lock; + return true; + }); - if ((res & -128) != rtime) + if (!_ok) { - res -= vm::rsrv_unique_lock; + // Already locked or updated: give up return false; } @@ -1661,43 +1654,22 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) // Aligned 8-byte reservations will be used here addr &= -8; - for (u64 count = 0;; count++) + auto [_oldd, _ok] = res.fetch_op([&](u64& r) { - auto [_old, _ok] = res.fetch_op([&](u64& r) - { - if ((r & -128) != rtime || (r & vm::rsrv_unique_lock)) - { - return false; - } - - r += 1; - return true; - }); - - // Give up if reservation has been updated - if ((_old & -128) != rtime) + if ((r & -128) != rtime || (r & 127)) { return false; } - if (_ok) - { - if (count >= 20) - { - ppu_log.notice("%s took too long (%u):", sizeof(T) == 4 ? "STWCX" : "STDCX", count); - } + // Despite using shared lock, doesn't allow other shared locks (TODO) + r += 1; + return true; + }); - break; - } - - if (ppu.state && ppu.check_state()) - { - return false; - } - else - { - busy_wait(100); - } + // Give up if reservation has been locked or updated + if (!_ok) + { + return false; } if (data.compare_and_swap_test(old_data, reg_value)) @@ -1706,7 +1678,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) return true; } - res -=1; + res -= 1; return false; }()) { diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 91c22df1c2..19ed330a18 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2118,27 +2118,20 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args) } } - while (res.bts(std::countr_zero(vm::rsrv_unique_lock))) + auto [_oldd, _ok] = res.fetch_op([&](u64& r) { - // Give up if reservation has been updated - if ((res & -128) != rtime) + if ((r & -128) != rtime || (r & 127)) { return false; } - if (state && check_state()) - { - return false; - } - else - { - busy_wait(100); - } - } + r += vm::rsrv_unique_lock; + return true; + }); - if ((res & -128) != rtime) + if (!_ok) { - res -= vm::rsrv_unique_lock; + // Already locked or updated: give up return false; }