sys_spinlock fixed

This commit is contained in:
Nekotekina 2014-07-21 02:30:16 +04:00
parent 1f64087a3b
commit fe49046a96
2 changed files with 31 additions and 30 deletions

View file

@ -4,53 +4,59 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "sys_spinlock.h" #include "sys_spinlock.h"
SysCallBase sys_spinlock("sys_spinlock"); SysCallBase sys_spinlock("sys_spinlock");
void sys_spinlock_initialize(mem_ptr_t<spinlock> lock) void sys_spinlock_initialize(mem_ptr_t<std::atomic<be_t<u32>>> lock)
{ {
sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.GetAddr()); sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.GetAddr());
lock->mutex.initialize(); // prx: set 0 and sync
*lock = be_t<u32>::MakeFromBE(0);
} }
void sys_spinlock_lock(mem_ptr_t<spinlock> lock) void sys_spinlock_lock(mem_ptr_t<std::atomic<be_t<u32>>> lock)
{ {
sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.GetAddr()); sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.GetAddr());
be_t<u32> tid = be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()); // prx: exchange with 0xabadcafe, repeat until exchanged with 0
switch (lock->mutex.lock(tid)) while (lock->exchange(be_t<u32>::MakeFromBE(se32(0xabadcafe))).ToBE())
{ {
case SMR_ABORT: LOG_WARNING(HLE, "sys_spinlock_lock(0x%x) aborted", lock.GetAddr()); break; while (lock->load(std::memory_order_relaxed).ToBE())
case SMR_DEADLOCK: LOG_ERROR(HLE, "sys_spinlock_lock(0x%x) reached deadlock", lock.GetAddr()); break; // ??? {
default: break; if (Emu.IsStopped())
{
break;
} }
} }
s32 sys_spinlock_trylock(mem_ptr_t<spinlock> lock) if (Emu.IsStopped())
{
LOG_WARNING(HLE, "sys_spinlock_lock(0x%x) aborted", lock.GetAddr());
break;
}
}
}
s32 sys_spinlock_trylock(mem_ptr_t<std::atomic<be_t<u32>>> lock)
{ {
sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.GetAddr()); sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.GetAddr());
be_t<u32> tid = be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()); // prx: exchange with 0xabadcafe, translate exchanged value
switch (lock->mutex.trylock(tid)) if (lock->exchange(be_t<u32>::MakeFromBE(se32(0xabadcafe))).ToBE())
{ {
case SMR_FAILED: return CELL_EBUSY; 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_OK; return CELL_OK;
} }
void sys_spinlock_unlock(mem_ptr_t<spinlock> lock) void sys_spinlock_unlock(mem_ptr_t<std::atomic<be_t<u32>>> lock)
{ {
sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr()); sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr());
while(true) // prx: sync and set 0
{ *lock = be_t<u32>::MakeFromBE(0);
if (lock->mutex.unlock(lock->mutex.GetOwner()) != SMR_PERMITTED)
break;
}
} }

View file

@ -1,12 +1,7 @@
#pragma once #pragma once
struct spinlock
{
SMutexBE mutex;
};
// SysCalls // SysCalls
void sys_spinlock_initialize(mem_ptr_t<spinlock> lock); void sys_spinlock_initialize(mem_ptr_t<std::atomic<be_t<u32>>> lock);
void sys_spinlock_lock(mem_ptr_t<spinlock> lock); void sys_spinlock_lock(mem_ptr_t<std::atomic<be_t<u32>>> lock);
s32 sys_spinlock_trylock(mem_ptr_t<spinlock> lock); s32 sys_spinlock_trylock(mem_ptr_t<std::atomic<be_t<u32>>> lock);
void sys_spinlock_unlock(mem_ptr_t<spinlock> lock); void sys_spinlock_unlock(mem_ptr_t<std::atomic<be_t<u32>>> lock);