From bf14cbdb27e844abdc0cb834b09c96f56b7ea850 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 29 Jul 2017 21:24:57 +0300 Subject: [PATCH] Fix _sys_lwcond_signal, _sys_lwcond_signal_all --- rpcs3/Emu/Cell/lv2/sys_lwcond.cpp | 28 +++++++++++++++++----------- rpcs3/Emu/Cell/lv2/sys_lwcond.h | 5 ++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp index 6bd74b829a..51fe3fbfa6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.cpp @@ -24,7 +24,7 @@ error_code _sys_lwcond_create(vm::ptr lwcond_id, u32 lwmutex_id, vm::ptr(name, lwmutex_id)) + if (const u32 id = idm::make(name, lwmutex_id, control)) { *lwcond_id = id; return CELL_OK; @@ -79,9 +79,9 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3 { mutex = idm::check_unlocked(lwmutex_id); - if (mutex && cond.waiters) + if (cond.waiters) { - semaphore_lock lock(mutex->mutex); + semaphore_lock lock(cond.mutex); cpu_thread* result = nullptr; @@ -99,7 +99,7 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3 } else { - result = cond.schedule(cond.sq, mutex->protocol); + result = cond.schedule(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK); } if (result) @@ -111,8 +111,10 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3 static_cast(result)->gpr[3] = CELL_EBUSY; } - if (mode != 2 && !mutex->signaled.fetch_op([](u32& v) { if (v) v--; })) + if (mode == 1) { + verify(HERE), !mutex->signaled; + semaphore_lock lock(mutex->mutex); mutex->sq.emplace_back(result); result = nullptr; mode = 2; // Enforce CELL_OK @@ -170,13 +172,13 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id { mutex = idm::check_unlocked(lwmutex_id); - if (mutex && cond.waiters) + if (cond.waiters) { - semaphore_lock lock(mutex->mutex); + semaphore_lock lock(cond.mutex); u32 result = 0; - while (const auto cpu = cond.schedule(cond.sq, mutex->protocol)) + while (const auto cpu = cond.schedule(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK)) { cond.waiters--; @@ -185,8 +187,10 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id static_cast(cpu)->gpr[3] = CELL_EBUSY; } - if (mode != 2 && !mutex->signaled.fetch_op([](u32& v) { if (v) v--; })) + if (mode == 1) { + verify(HERE), !mutex->signaled; + semaphore_lock lock(mutex->mutex); mutex->sq.emplace_back(cpu); } else @@ -237,13 +241,15 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id return nullptr; } - semaphore_lock lock(mutex->mutex); + semaphore_lock lock(cond.mutex); // Add a waiter cond.waiters++; cond.sq.emplace_back(&ppu); cond.sleep(ppu, timeout); + semaphore_lock lock2(mutex->mutex); + // Process lwmutex sleep queue if (const auto cpu = mutex->schedule(mutex->sq, mutex->protocol)) { @@ -274,7 +280,7 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id if (passed >= timeout) { - semaphore_lock lock(mutex->mutex); + semaphore_lock lock(cond->mutex); if (!cond->unqueue(cond->sq, &ppu)) { diff --git a/rpcs3/Emu/Cell/lv2/sys_lwcond.h b/rpcs3/Emu/Cell/lv2/sys_lwcond.h index 83ceedb73e..82a547248f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_lwcond.h +++ b/rpcs3/Emu/Cell/lv2/sys_lwcond.h @@ -25,13 +25,16 @@ struct lv2_lwcond final : lv2_obj const u64 name; const u32 lwid; + vm::ps3::ptr control; + semaphore<> mutex; atomic_t waiters{0}; std::deque sq; - lv2_lwcond(u64 name, u32 lwid) + lv2_lwcond(u64 name, u32 lwid, vm::ps3::ptr control) : name(name) , lwid(lwid) + , control(control) { } };