From a17a6527f61c2bad1865593e7d6b630954966007 Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 26 Jul 2022 09:26:25 +0300 Subject: [PATCH] LV2: Move memory unlocking outside of mutex ownership and make it conditional --- rpcs3/Emu/Cell/lv2/lv2.cpp | 15 ++++++++++++--- rpcs3/Emu/Cell/lv2/sys_cond.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_event.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_event_flag.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_lwcond.cpp | 4 ++-- rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_mutex.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_rwlock.cpp | 4 ++-- rpcs3/Emu/Cell/lv2/sys_semaphore.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_sync.h | 27 +++++++++++++++++++++++++++ 10 files changed, 49 insertions(+), 13 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 1c0b933a5c..0ee2798433 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1207,8 +1207,12 @@ namespace cpu_counter void lv2_obj::sleep(cpu_thread& cpu, const u64 timeout, bool notify_later) { - vm::temporary_unlock(cpu); - cpu_counter::remove(&cpu); + // Should already be performed when using this flag + if (!notify_later) + { + vm::temporary_unlock(cpu); + cpu_counter::remove(&cpu); + } { std::lock_guard lock{g_mutex}; sleep_unlocked(cpu, timeout, notify_later); @@ -1218,7 +1222,12 @@ void lv2_obj::sleep(cpu_thread& cpu, const u64 timeout, bool notify_later) bool lv2_obj::awake(cpu_thread* const thread, bool notify_later, s32 prio) { - vm::temporary_unlock(); + // Too risky to postpone it in case the notified thread may wait for this thread to free its passive lock + if (!notify_later) + { + vm::temporary_unlock(); + } + std::lock_guard lock(g_mutex); return awake_unlocked(thread, notify_later, prio); } diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index a78d150a5a..97b13be5ac 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -300,7 +300,7 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout) return -1; } - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(cond.mutex->mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 2442b06970..41fab64e6d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -421,7 +421,7 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptrlwcond_waiters++; - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(cond.mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp index 206fbdb73b..2aaf24c769 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp @@ -146,7 +146,7 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout) return true; } - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(mutex.mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp index 547d3ccbbe..5fc5c297af 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp @@ -141,7 +141,7 @@ error_code sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout) if (result == CELL_EBUSY) { - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(mutex.mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp index 0b669a49f1..ef0afe46ed 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp @@ -114,7 +114,7 @@ error_code sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) } } - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(rwlock.mutex); @@ -346,7 +346,7 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout) return val; } - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(rwlock.mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp index 7fcb67952c..b73344a589 100644 --- a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp @@ -123,7 +123,7 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout) } } - lv2_obj::notify_all_t notify; + lv2_obj::notify_all_t notify(ppu); std::lock_guard lock(sema.mutex); diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index cd1bc70ffe..be631488a8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -61,6 +61,16 @@ enum enum ppu_thread_status : u32; +namespace vm +{ + void temporary_unlock(cpu_thread& cpu) noexcept; +} + +namespace cpu_counter +{ + void remove(cpu_thread*) noexcept; +} + // Base class for some kernel objects (shared set of 8192 objects). struct lv2_obj { @@ -495,10 +505,27 @@ public: } } + template struct notify_all_t { + notify_all_t() noexcept = default; + + notify_all_t(T& cpu) noexcept + { + vm::temporary_unlock(cpu); + cpu_counter::remove(&cpu); + } + ~notify_all_t() noexcept { + if constexpr (!std::is_base_of_v) + { + if (auto cpu = cpu_thread::get_current(); cpu && cpu->is_paused()) + { + vm::temporary_unlock(*cpu); + } + } + lv2_obj::notify_all(); } };