From 2807be7080ab71d5c542a2bef7323f9b43f192e6 Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 13 Sep 2022 13:05:25 +0300 Subject: [PATCH] SPU: Regression fix after #12648 --- rpcs3/Emu/Cell/SPUThread.cpp | 32 +++++++++++++++++++++++--------- rpcs3/util/atomic.cpp | 25 ++++++++++++++----------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index a70d3ecee2..12b783bc8a 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -4314,7 +4314,23 @@ s64 spu_thread::get_ch_value(u32 ch) // Don't busy-wait with TSX - memory is sensitive if (!reservation_busy_waiting) { - atomic_wait_engine::set_one_time_use_wait_callback(mask1 != SPU_EVENT_LR ? nullptr : +[](u64) -> bool + if (raddr - spurs_addr <= 0x80 && !g_cfg.core.spu_accurate_reservations && mask1 == SPU_EVENT_LR) + { + atomic_wait_engine::set_one_time_use_wait_callback(+[](u64) -> bool + { + const auto _this = static_cast(cpu_thread::get_current()); + AUDIT(_this->id_type() == 1); + + return !_this->is_stopped(); + }); + + // Wait without timeout, in this situation we have notifications for all writes making it possible + // Abort notifications are handled specially for performance reasons + vm::reservation_notifier(raddr).wait(rtime, -128); + continue; + } + + atomic_wait_engine::set_one_time_use_wait_callback(mask1 != SPU_EVENT_LR ? nullptr : +[](u64 attempts) -> bool { const auto _this = static_cast(cpu_thread::get_current()); AUDIT(_this->id_type() == 1); @@ -4326,6 +4342,12 @@ s64 spu_thread::get_ch_value(u32 ch) return false; } + if (!attempts) + { + // Skip checks which have been done already + return true; + } + if (!vm::check_addr(_this->raddr) || !cmp_rdata(_this->rdata, *_this->resrv_mem)) { _this->set_events(SPU_EVENT_LR); @@ -4336,14 +4358,6 @@ s64 spu_thread::get_ch_value(u32 ch) return true; }); - if (raddr - spurs_addr <= 0x80 && !g_cfg.core.spu_accurate_reservations && mask1 == SPU_EVENT_LR) - { - // Wait without timeout, in this situation we have notifications for all writes making it possible - // Abort notifications are handled specially for performance reasons - vm::reservation_notifier(raddr).wait(rtime, -128); - continue; - } - vm::reservation_notifier(raddr).wait(rtime, -128, atomic_wait_timeout{80'000}); } else diff --git a/rpcs3/util/atomic.cpp b/rpcs3/util/atomic.cpp index d1e5dce9d8..4ee23a00a1 100644 --- a/rpcs3/util/atomic.cpp +++ b/rpcs3/util/atomic.cpp @@ -1107,6 +1107,14 @@ SAFE_BUFFERS(void) atomic_wait_engine::wait(const void* data, u32 size, u128 old while (ptr_cmp(data, size, old_value, mask, ext)) { + if (s_tls_one_time_wait_cb) + { + if (!s_tls_one_time_wait_cb(attempts)) + { + break; + } + } + #ifdef USE_FUTEX struct timespec ts; ts.tv_sec = timeout / 1'000'000'000; @@ -1191,19 +1199,14 @@ SAFE_BUFFERS(void) atomic_wait_engine::wait(const void* data, u32 size, u128 old break; } - if (s_tls_one_time_wait_cb) - { - if (!s_tls_one_time_wait_cb(attempts)) - { - break; - } - - // The condition of the callback overrides timeout escape because it makes little sense to do so when a custom condition is passed - continue; - } - if (timeout + 1) { + if (s_tls_one_time_wait_cb) + { + // The condition of the callback overrides timeout escape because it makes little sense to do so when a custom condition is passed + continue; + } + // TODO: reduce timeout instead break; }