diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 9ee9bca926..477d3e90c0 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -79,6 +79,28 @@ namespace vm // Memory pages std::array g_pages{}; + void reservation_update(u32 addr, u32 size, bool lsb) + { + u64 old = UINT64_MAX; + const auto cpu = get_current_cpu_thread(); + + while (true) + { + const auto [ok, rtime] = try_reservation_update(addr, size, lsb); + if (ok || old / 128 < rtime / 128) + { + return; + } + + old = rtime; + + if (cpu && cpu->test_stopped()) + { + return; + } + } + } + static void _register_lock(cpu_thread* _cpu) { for (u32 i = 0, max = g_cfg.core.ppu_threads;;) diff --git a/rpcs3/Emu/Memory/vm_reservation.h b/rpcs3/Emu/Memory/vm_reservation.h index c6573a4084..95011bdba3 100644 --- a/rpcs3/Emu/Memory/vm_reservation.h +++ b/rpcs3/Emu/Memory/vm_reservation.h @@ -14,12 +14,17 @@ namespace vm } // Update reservation status - inline void reservation_update(u32 addr, u32 size, bool lsb = false) + inline std::pair try_reservation_update(u32 addr, u32 size, bool lsb = false) { // Update reservation info with new timestamp - reservation_acquire(addr, size) += 128; + auto& res = reservation_acquire(addr, size); + const u64 rtime = res; + + return {!(rtime & 127) && res.compare_and_swap_test(rtime, rtime + 128), rtime}; } + void reservation_update(u32 addr, u32 size, bool lsb = false); + // Get reservation sync variable inline atomic_t& reservation_notifier(u32 addr, u32 size) {