From fe49046a961fa2551739df588a3422d0980b7efb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 21 Jul 2014 02:30:16 +0400 Subject: [PATCH] sys_spinlock fixed --- rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp | 48 ++++++++++++++----------- rpcs3/Emu/SysCalls/lv2/sys_spinlock.h | 13 +++---- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp index 9d70571088..358b234f37 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.cpp @@ -4,53 +4,59 @@ #include "Emu/System.h" #include "Emu/Cell/PPUThread.h" #include "Emu/SysCalls/SysCalls.h" + #include "sys_spinlock.h" SysCallBase sys_spinlock("sys_spinlock"); -void sys_spinlock_initialize(mem_ptr_t lock) +void sys_spinlock_initialize(mem_ptr_t>> lock) { sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.GetAddr()); - lock->mutex.initialize(); + // prx: set 0 and sync + *lock = be_t::MakeFromBE(0); } -void sys_spinlock_lock(mem_ptr_t lock) +void sys_spinlock_lock(mem_ptr_t>> lock) { sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.GetAddr()); - be_t tid = be_t::MakeFromLE(GetCurrentPPUThread().GetId()); - switch (lock->mutex.lock(tid)) + // prx: exchange with 0xabadcafe, repeat until exchanged with 0 + while (lock->exchange(be_t::MakeFromBE(se32(0xabadcafe))).ToBE()) { - case SMR_ABORT: LOG_WARNING(HLE, "sys_spinlock_lock(0x%x) aborted", lock.GetAddr()); break; - case SMR_DEADLOCK: LOG_ERROR(HLE, "sys_spinlock_lock(0x%x) reached deadlock", lock.GetAddr()); break; // ??? - default: break; + while (lock->load(std::memory_order_relaxed).ToBE()) + { + if (Emu.IsStopped()) + { + break; + } + } + + if (Emu.IsStopped()) + { + LOG_WARNING(HLE, "sys_spinlock_lock(0x%x) aborted", lock.GetAddr()); + break; + } } } -s32 sys_spinlock_trylock(mem_ptr_t lock) +s32 sys_spinlock_trylock(mem_ptr_t>> lock) { sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.GetAddr()); - be_t tid = be_t::MakeFromLE(GetCurrentPPUThread().GetId()); - switch (lock->mutex.trylock(tid)) + // prx: exchange with 0xabadcafe, translate exchanged value + if (lock->exchange(be_t::MakeFromBE(se32(0xabadcafe))).ToBE()) { - case SMR_FAILED: return CELL_EBUSY; - case SMR_ABORT: LOG_WARNING(HLE, "sys_spinlock_trylock(0x%x) aborted", lock.GetAddr()); break; - case SMR_DEADLOCK: LOG_ERROR(HLE, "sys_spinlock_trylock(0x%x) reached deadlock", lock.GetAddr()); break; - default: break; + return CELL_EBUSY; } return CELL_OK; } -void sys_spinlock_unlock(mem_ptr_t lock) +void sys_spinlock_unlock(mem_ptr_t>> lock) { sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr()); - while(true) - { - if (lock->mutex.unlock(lock->mutex.GetOwner()) != SMR_PERMITTED) - break; - } + // prx: sync and set 0 + *lock = be_t::MakeFromBE(0); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h index ed81750400..0dfaa371fc 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spinlock.h @@ -1,12 +1,7 @@ #pragma once -struct spinlock -{ - SMutexBE mutex; -}; - // SysCalls -void sys_spinlock_initialize(mem_ptr_t lock); -void sys_spinlock_lock(mem_ptr_t lock); -s32 sys_spinlock_trylock(mem_ptr_t lock); -void sys_spinlock_unlock(mem_ptr_t lock); +void sys_spinlock_initialize(mem_ptr_t>> lock); +void sys_spinlock_lock(mem_ptr_t>> lock); +s32 sys_spinlock_trylock(mem_ptr_t>> lock); +void sys_spinlock_unlock(mem_ptr_t>> lock);