diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index ef53522bfb..aa92c51761 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -151,7 +151,8 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id) const auto cond = idm::check(cond_id, [&](lv2_cond& cond) -> int { - if (!idm::check_unlocked>(thread_id)) + if (const auto cpu = idm::check_unlocked>(thread_id); + !cpu || cpu->joiner == ppu_join_status::exited) { return -1; } diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp index e92fee2116..2ed65bc0e3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp @@ -87,9 +87,13 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3 const auto cond = idm::check(lwcond_id, [&](lv2_lwcond& cond) -> int { - if (ppu_thread_id != umax && !idm::check_unlocked>(ppu_thread_id)) + if (ppu_thread_id != umax) { - return -1; + if (const auto cpu = idm::check_unlocked>(ppu_thread_id); + !cpu || cpu->joiner == ppu_join_status::exited) + { + return -1; + } } lv2_lwmutex* mutex; @@ -136,13 +140,25 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3 static_cast(result)->gpr[3] = CELL_EBUSY; } - if (mode == 1) + if (mode != 2) { verify(HERE), !mutex->signaled; std::lock_guard lock(mutex->mutex); - verify(HERE), mutex->add_waiter(result); + + if (mode == 3 && !mutex->sq.empty()) [[unlikely]] + { + // Respect ordering of the sleep queue + mutex->sq.emplace_back(result); + result = mutex->schedule(mutex->sq, mutex->protocol); + } + else if (mode == 1) + { + verify(HERE), mutex->add_waiter(result); + result = nullptr; + } } - else + + if (result) { cond.awake(result); }