From ec8c5453bcb4e2a608eca3c0b9916cb34f58fec8 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 27 Aug 2019 15:01:08 +0300 Subject: [PATCH] Fix sys_cond_wait Schedule PPU thread before relocking. Don't lock mutex in notify functions. --- rpcs3/Emu/Cell/lv2/lv2.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_cond.cpp | 69 ++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index b8117f83b2..127c66c8aa 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1029,7 +1029,7 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout) if (!ok) { - LOG_TRACE(PPU, "sleep() failed (signaled)"); + LOG_FATAL(PPU, "sleep() failed (signaled) (%s)", ppu->current_function); return; } diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index bf5c10d705..f50cf6a7d4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -85,12 +85,7 @@ error_code sys_cond_signal(ppu_thread& ppu, u32 cond_id) if (const auto cpu = cond.schedule(cond.sq, cond.mutex->protocol)) { - cond.waiters--; - - if (cond.mutex->try_own(*cpu, cpu->id)) - { - return cpu; - } + return cpu; } } @@ -118,7 +113,7 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id) const auto cond = idm::check(cond_id, [](lv2_cond& cond) { - cpu_thread* result = nullptr; + uint count = 0; if (cond.waiters) { @@ -126,16 +121,12 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id) while (const auto cpu = cond.schedule(cond.sq, cond.mutex->protocol)) { - cond.waiters--; - - if (cond.mutex->try_own(*cpu, cpu->id)) - { - result = cpu; - } + lv2_obj::append(cpu); + count++; } } - return result; + return count; }); if (!cond) @@ -145,7 +136,7 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id) if (cond.ret) { - cond->awake(cond.ret); + lv2_obj::awake_all(); } return CELL_OK; @@ -172,14 +163,8 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id) { if (cpu->id == thread_id) { - verify(HERE), cond.unqueue(cond.sq, cpu), cond.waiters--; - - if (cond.mutex->try_own(*cpu, cpu->id)) - { - return cpu; - } - - return (cpu_thread*)(2); + verify(HERE), cond.unqueue(cond.sq, cpu); + return cpu; } } } @@ -192,7 +177,7 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id) return CELL_ESRCH; } - if (cond.ret && cond.ret != (cpu_thread*)(2)) + if (cond.ret) { cond->awake(cond.ret); } @@ -269,15 +254,8 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout) // Try to cancel the waiting if (cond->unqueue(cond->sq, &ppu)) { - cond->waiters--; - ppu.gpr[3] = CELL_ETIMEDOUT; - - // Own or requeue - if (cond->mutex->try_own(ppu, ppu.id)) - { - break; - } + break; } timeout = 0; @@ -290,11 +268,38 @@ error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout) } } + bool locked_ok = true; + + // Schedule and relock + if (ppu.check_state()) + { + return 0; + } + else if (cond->mutex->try_lock(ppu.id) != CELL_OK) + { + std::lock_guard lock(cond->mutex->mutex); + + // Own mutex or requeue + locked_ok = cond->mutex->try_own(ppu, ppu.id); + } + + while (!locked_ok && !ppu.state.test_and_reset(cpu_flag::signal)) + { + if (ppu.is_stopped()) + { + return 0; + } + + thread_ctrl::wait(); + } + // Verify ownership verify(HERE), cond->mutex->owner >> 1 == ppu.id; // Restore the recursive value cond->mutex->lock_count = cond.ret; + cond->waiters--; + return not_an_error(ppu.gpr[3]); }