From be80a7c39ce888a7e2c76d460400a3c1bf81f1db Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 23 Mar 2014 01:04:55 +0400 Subject: [PATCH] SC_Lwcond fixed --- rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp | 171 ++++++++++++------------- rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h | 11 ++ rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 7 +- rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp | 2 + 4 files changed, 96 insertions(+), 95 deletions(-) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp index 2b02cd1276..1a359c5ed8 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp @@ -16,7 +16,7 @@ int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t l } lwcond->lwmutex = lwmutex.GetAddr(); - lwcond->lwcond_queue = sys_lwcond.GetNewId(new SleepQueue(attr->name_u64)); + lwcond->lwcond_queue = sys_lwcond.GetNewId(new Lwcond(attr->name_u64)); if (lwmutex.IsGood()) { @@ -49,20 +49,20 @@ int sys_lwcond_destroy(mem_ptr_t lwcond) return CELL_EFAULT; } - u32 lwc = lwcond->lwcond_queue; + u32 id = lwcond->lwcond_queue; - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData(lwc, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData(id, lw)) { return CELL_ESRCH; } - if (!sq->finalize()) + if (!lw->m_queue.finalize()) { return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(lwc); + Emu.GetIdManager().RemoveID(id); return CELL_OK; } @@ -75,37 +75,23 @@ int sys_lwcond_signal(mem_ptr_t lwcond) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } mem_ptr_t mutex(lwcond->lwmutex); - be_t tid = GetCurrentPPUThread().GetId(); - bool was_locked = (mutex->mutex.GetOwner() == tid); - - if (be_t target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())) + if (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop())) { - if (!was_locked) - { - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - } - else - { - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - } - } + lw->signal.lock(target); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_lwcond_signal(sq=%d) aborted", (u32)lwcond->lwcond_queue); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_signal(id=%d) aborted", (u32)lwcond->lwcond_queue); + return CELL_OK; + } } return CELL_OK; @@ -120,37 +106,23 @@ int sys_lwcond_signal_all(mem_ptr_t lwcond) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } mem_ptr_t mutex(lwcond->lwmutex); - be_t tid = GetCurrentPPUThread().GetId(); - bool was_locked = (mutex->mutex.GetOwner() == tid); - - while (be_t target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())) + while (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop())) { - if (!was_locked) - { - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - } - else - { - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - } - } + lw->signal.lock(target); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_lwcond_signal_all(sq=%d) aborted", (u32)lwcond->lwcond_queue); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_signal_all(id=%d) aborted", (u32)lwcond->lwcond_queue); + return CELL_OK; + } } return CELL_OK; @@ -165,8 +137,8 @@ int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } @@ -176,36 +148,20 @@ int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) return CELL_ESRCH; } - if (!sq->invalidate(ppu_thread_id)) + if (!lw->m_queue.invalidate(ppu_thread_id)) { return CELL_EPERM; } - mem_ptr_t mutex(lwcond->lwmutex); - be_t tid = GetCurrentPPUThread().GetId(); - - bool was_locked = (mutex->mutex.GetOwner() == tid); - - be_t target = ppu_thread_id; + u32 target = ppu_thread_id; { - if (!was_locked) - { - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - } - else - { - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - } - } + lw->signal.lock(target); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_lwcond_signal_to(sq=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_signal_to(id=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id); + return CELL_OK; + } } return CELL_OK; @@ -220,8 +176,8 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } @@ -230,29 +186,57 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) u32 tid_le = GetCurrentPPUThread().GetId(); be_t tid = tid_le; + SleepQueue* sq = nullptr; + Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq); + if (mutex->mutex.GetOwner() != tid) { + sys_lwcond.Warning("sys_lwcond_wait(id=%d) failed (EPERM)", (u32)lwcond->lwcond_queue); return CELL_EPERM; // caller must own this lwmutex } - sq->push(tid_le); + lw->m_queue.push(tid_le); + if (mutex->recursive_count.ToBE() != se32(1)) + { + sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had wrong recursive value (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->recursive_count); + } mutex->recursive_count = 0; - mutex->mutex.unlock(tid); + + if (sq) + { + mutex->mutex.unlock(tid, mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()); + } + else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY)) + { + mutex->mutex.unlock(tid); // SYS_SYNC_RETRY + } + else + { + sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had invalid sleep queue (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); + } u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : ~0; + while (true) { - /* switch (mutex->trylock(tid)) + if (lw->signal.unlock(tid, tid) == SMR_OK) { - case SMR_OK: mutex->unlock(tid); break; - case SMR_SIGNAL: return CELL_OK; - } */ - if (mutex->mutex.GetOwner() == tid) - { - _mm_mfence(); + switch (mutex->lock(tid, 0)) + { + case CELL_OK: break; + case CELL_EDEADLK: sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex was locked", + (u32)lwcond->lwcond_queue); return CELL_OK; + case CELL_ESRCH: sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex not found (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); return CELL_ESRCH; + case CELL_EINVAL: goto abort; + } + mutex->recursive_count = 1; + lw->signal.unlock(tid); return CELL_OK; } @@ -260,13 +244,16 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) if (counter++ > max_counter) { - sq->invalidate(tid_le); + lw->m_queue.invalidate(tid_le); return CELL_ETIMEDOUT; } if (Emu.IsStopped()) { - ConLog.Warning("sys_lwcond_wait(sq=%d) aborted", (u32)lwcond->lwcond_queue); - return CELL_OK; + goto abort; } } + +abort: + ConLog.Warning("sys_lwcond_wait(id=%d) aborted", (u32)lwcond->lwcond_queue); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h index f7d8369c13..16e92548e6 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h @@ -13,4 +13,15 @@ struct sys_lwcond_t { be_t lwmutex; be_t lwcond_queue; +}; + +struct Lwcond +{ + SMutex signal; + SleepQueue m_queue; + + Lwcond(u64 name) + : m_queue(name) + { + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index ee3d9a846f..31fedbd349 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -206,10 +206,11 @@ int sys_lwmutex_t::trylock(be_t tid) { if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL; - be_t owner_tid = mutex.GetOwner(); + be_t owner_tid = mutex.GetFreeValue(); - if (owner_tid != mutex.GetFreeValue()) + if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value { + owner_tid = mutex.GetOwner(); if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid)) { if (!tt->IsAlive()) @@ -263,7 +264,7 @@ int sys_lwmutex_t::trylock(be_t tid) int sys_lwmutex_t::unlock(be_t tid) { - if (tid != mutex.GetOwner()) + if (mutex.unlock(tid, tid) != SMR_OK) { return CELL_EPERM; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp index 90d9a35a3a..56bad1cf88 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp @@ -44,8 +44,10 @@ void sys_spinlock_unlock(mem_ptr_t lock) { sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr()); +again: switch (lock->mutex.unlock(lock->mutex.GetOwner())) { + case SMR_PERMITTED: goto again; default: break; } } \ No newline at end of file