Merge pull request #64 from Nekotekina/master

Last changes
This commit is contained in:
Alexandro Sánchez Bach 2014-02-09 14:50:35 +01:00
commit 4ebd974f5e
51 changed files with 1218 additions and 618 deletions

View file

@ -2,6 +2,10 @@
#include "Utilities/GNU.h" #include "Utilities/GNU.h"
#define se16(x) const_se_t<u16, x>::value
#define se32(x) const_se_t<u32, x>::value
#define se64(x) const_se_t<u64, x>::value
template<typename T, int size = sizeof(T)> struct se_t; template<typename T, int size = sizeof(T)> struct se_t;
template<typename T> struct se_t<T, 1> { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } }; template<typename T> struct se_t<T, 1> { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } };
template<typename T> struct se_t<T, 2> { static __forceinline void func(T& dst, const T src) { (u16&)dst = _byteswap_ushort((u16&)src); } }; template<typename T> struct se_t<T, 2> { static __forceinline void func(T& dst, const T src) { (u16&)dst = _byteswap_ushort((u16&)src); } };

26
Utilities/SMutex.cpp Normal file
View file

@ -0,0 +1,26 @@
#include <stdafx.h>
#include <Utilities/SMutex.h>
__forceinline void SM_Sleep()
{
Sleep(1);
}
__forceinline DWORD SM_GetCurrentThreadId()
{
return GetCurrentThreadId();
}
__forceinline u32 SM_GetCurrentCPUThreadId()
{
if (CPUThread* t = GetCurrentCPUThread())
{
return t->GetId();
}
return 0;
}
__forceinline be_t<u32> SM_GetCurrentCPUThreadIdBE()
{
return SM_GetCurrentCPUThreadId();
}

155
Utilities/SMutex.h Normal file
View file

@ -0,0 +1,155 @@
#pragma once
#include <atomic>
extern void SM_Sleep();
extern DWORD SM_GetCurrentThreadId();
extern u32 SM_GetCurrentCPUThreadId();
extern be_t<u32> SM_GetCurrentCPUThreadIdBE();
enum SMutexResult
{
SMR_OK = 0, // succeeded (lock, trylock, unlock)
SMR_FAILED, // failed (trylock, unlock)
SMR_DEADLOCK, // mutex reached deadlock (lock, trylock)
SMR_SIGNAL = SMR_DEADLOCK, // unlock can be used for signaling specific thread
SMR_PERMITTED, // not owner of the mutex (unlock)
SMR_ABORT, // emulator has been stopped (lock, trylock, unlock)
SMR_DESTROYED, // mutex has been destroyed (lock, trylock, unlock)
SMR_TIMEOUT, // timed out (lock)
};
template
<
typename T,
u32 free_value = 0,
u32 dead_value = ~0,
void (wait)() = SM_Sleep
>
class SMutexBase
{
static_assert(sizeof(T) == 4, "Invalid SMutexBase typename");
std::atomic<T> owner;
public:
SMutexBase()
: owner((T)free_value)
{
}
~SMutexBase()
{
lock((T)dead_value);
owner = (T)dead_value;
}
__forceinline T GetOwner() const
{
return (T&)owner;
}
SMutexResult trylock(T tid)
{
T old = (T)free_value;
if (!owner.compare_exchange_strong(old, tid))
{
if (old == tid)
{
return SMR_DEADLOCK;
}
if (Emu.IsStopped())
{
return SMR_ABORT;
}
if (old == (T)dead_value)
{
return SMR_DESTROYED;
}
return SMR_FAILED;
}
return SMR_OK;
}
SMutexResult unlock(T tid, T to = (T)free_value)
{
T old = tid;
if (!owner.compare_exchange_strong(old, to))
{
if (old == (T)free_value)
{
return SMR_FAILED;
}
if (old == (T)dead_value)
{
return SMR_DESTROYED;
}
return SMR_PERMITTED;
}
return SMR_OK;
}
SMutexResult lock(T tid, u64 timeout = 0)
{
u64 counter = 0;
while (true)
{
switch (SMutexResult res = trylock(tid))
{
case SMR_FAILED: break;
default: return res;
}
wait();
if (timeout && counter++ > timeout)
{
return SMR_TIMEOUT;
}
}
}
};
template<typename T, T (get_tid)()>
class SMutexLockerBase
{
SMutexBase<T>& sm;
public:
const T tid;
SMutexLockerBase(SMutexBase<T>& _sm)
: sm(_sm)
, tid(get_tid())
{
if (!tid)
{
ConLog.Error("SMutexLockerBase: thread id == 0");
Emu.Pause();
}
sm.lock(tid);
}
~SMutexLockerBase()
{
sm.unlock(tid);
}
};
typedef SMutexBase<DWORD>
SMutexGeneral;
typedef SMutexBase<u32>
SMutex;
typedef SMutexBase<be_t<u32>>
SMutexBE;
typedef SMutexLockerBase<DWORD, SM_GetCurrentThreadId>
SMutexGeneralLocker;
typedef SMutexLockerBase<u32, SM_GetCurrentCPUThreadId>
SMutexLocker;
typedef SMutexLockerBase<be_t<u32>, SM_GetCurrentCPUThreadIdBE>
SMutexBELocker;

View file

@ -1,6 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "CPUThread.h" #include "CPUThread.h"
reservation_struct reservation;
CPUThread* GetCurrentCPUThread() CPUThread* GetCurrentCPUThread()
{ {
return (CPUThread*)GetCurrentNamedThread(); return (CPUThread*)GetCurrentNamedThread();
@ -89,14 +91,12 @@ void CPUThread::Wait(const CPUThread& thr)
bool CPUThread::Sync() bool CPUThread::Sync()
{ {
wxCriticalSectionLocker lock(m_cs_sync);
return m_sync_wait; return m_sync_wait;
} }
int CPUThread::ThreadStatus() int CPUThread::ThreadStatus()
{ {
if(Emu.IsStopped()) if(Emu.IsStopped() || IsStopped() || IsPaused())
{ {
return CPUThread_Stopped; return CPUThread_Stopped;
} }
@ -236,7 +236,7 @@ void CPUThread::Pause()
DoPause(); DoPause();
Emu.CheckStatus(); Emu.CheckStatus();
ThreadBase::Stop(); // ThreadBase::Stop(); // "Abort() called" exception
#ifndef QT_UI #ifndef QT_UI
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this); wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
#endif #endif

View file

@ -1,6 +1,25 @@
#pragma once #pragma once
#include "Emu/Memory/MemoryBlock.h" #include "Emu/Memory/MemoryBlock.h"
#include "Emu/CPU/CPUDecoder.h" #include "Emu/CPU/CPUDecoder.h"
#include "Utilities/SMutex.h"
struct reservation_struct
{
SMutex mutex; // mutex for updating reservation_owner and data
volatile u32 owner; // id of thread that got reservation
volatile u32 addr;
volatile u32 size;
volatile u32 data32;
volatile u64 data64;
// atm, PPU can't break SPU MFC reservation correctly
__forceinline void clear()
{
owner = 0;
}
};
extern reservation_struct reservation;
enum CPUThreadType enum CPUThreadType
{ {

View file

@ -76,6 +76,8 @@ void CPUThreadManager::RemoveThread(const u32 id)
s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id) s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id)
{ {
std::lock_guard<std::mutex> lock(m_mtx_thread);
s32 num = 0; s32 num = 0;
for(u32 i=0; i<m_threads.GetCount(); ++i) for(u32 i=0; i<m_threads.GetCount(); ++i)
@ -89,16 +91,17 @@ s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id)
CPUThread* CPUThreadManager::GetThread(u32 id) CPUThread* CPUThreadManager::GetThread(u32 id)
{ {
for(u32 i=0; i<m_threads.GetCount(); ++i) CPUThread* res;
{
if(m_threads[i].GetId() == id) return &m_threads[i];
}
return nullptr; if (!Emu.GetIdManager().GetIDData(id, res)) return nullptr;
return res;
} }
void CPUThreadManager::Exec() void CPUThreadManager::Exec()
{ {
std::lock_guard<std::mutex> lock(m_mtx_thread);
for(u32 i=0; i<m_threads.GetCount(); ++i) for(u32 i=0; i<m_threads.GetCount(); ++i)
{ {
m_threads[i].Exec(); m_threads[i].Exec();

View file

@ -16,6 +16,7 @@ PPCThread* GetCurrentPPCThread()
PPCThread::PPCThread(CPUThreadType type) : CPUThread(type) PPCThread::PPCThread(CPUThreadType type) : CPUThread(type)
{ {
memset(m_args, 0, sizeof(m_args));
} }
PPCThread::~PPCThread() PPCThread::~PPCThread()
@ -24,14 +25,13 @@ PPCThread::~PPCThread()
void PPCThread::DoReset() void PPCThread::DoReset()
{ {
memset(m_args, 0, sizeof(u64) * 4);
} }
void PPCThread::InitStack() void PPCThread::InitStack()
{ {
if(m_stack_addr) return; if(m_stack_addr) return;
if(m_stack_size == 0) m_stack_size = 0x10000; if(m_stack_size == 0) m_stack_size = 0x10000;
m_stack_addr = Memory.StackMem.Alloc(Memory.AlignAddr(m_stack_size, 0x100)); m_stack_addr = Memory.StackMem.AllocAlign(m_stack_size, 0x100);
m_stack_point = m_stack_addr + m_stack_size; m_stack_point = m_stack_addr + m_stack_size;
/* /*

View file

@ -1656,7 +1656,7 @@ private:
{ {
CPU.VPR[vd]._u8[15] = CPU.VPR[va]._u8[15] >> sh; CPU.VPR[vd]._u8[15] = CPU.VPR[va]._u8[15] >> sh;
for (uint b = 14; b >= 0; b--) for (uint b = 14; ~b; b--)
{ {
CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] >> sh) | (CPU.VPR[va]._u8[b+1] << (8 - sh)); CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] >> sh) | (CPU.VPR[va]._u8[b+1] << (8 - sh));
} }
@ -2362,9 +2362,12 @@ private:
void LWARX(u32 rd, u32 ra, u32 rb) void LWARX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
CPU.reserve_addr = addr;
CPU.reserve = true; SMutexLocker lock(reservation.mutex);
CPU.GPR[rd] = Memory.Read32(addr); reservation.owner = lock.tid;
reservation.addr = addr;
reservation.size = 4;
reservation.data32 = CPU.GPR[rd] = Memory.Read32(addr);
} }
void LDX(u32 rd, u32 ra, u32 rb) void LDX(u32 rd, u32 ra, u32 rb)
{ {
@ -2535,9 +2538,12 @@ private:
void LDARX(u32 rd, u32 ra, u32 rb) void LDARX(u32 rd, u32 ra, u32 rb)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
CPU.reserve_addr = addr;
CPU.reserve = true; SMutexLocker lock(reservation.mutex);
CPU.GPR[rd] = Memory.Read64(addr); reservation.owner = lock.tid;
reservation.addr = addr;
reservation.size = 8;
reservation.data64 = CPU.GPR[rd] = Memory.Read64(addr);
} }
void DCBF(u32 ra, u32 rb) void DCBF(u32 ra, u32 rb)
{ {
@ -2649,26 +2655,20 @@ private:
Memory.Write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); Memory.Write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]);
} }
void STWCX_(u32 rs, u32 ra, u32 rb) void STWCX_(u32 rs, u32 ra, u32 rb)
{
CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0);
if(CPU.reserve)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr) SMutexLocker lock(reservation.mutex);
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4)
{ {
Memory.Write32(addr, CPU.GPR[rs]); // Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true); CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile long*)(Memory + addr), (u32)CPU.GPR[rs], reservation.data32) == reservation.data32);
CPU.reserve = false; reservation.clear();
} }
else else
{ {
static const bool u = 0; CPU.SetCR_EQ(0, false);
if(u) Memory.Write32(addr, CPU.GPR[rs]); if (lock.tid == reservation.owner) reservation.clear();
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
}
} }
} }
void STWX(u32 rs, u32 ra, u32 rb) void STWX(u32 rs, u32 ra, u32 rb)
@ -2708,24 +2708,20 @@ private:
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]); if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
} }
void STDCX_(u32 rs, u32 ra, u32 rb) void STDCX_(u32 rs, u32 ra, u32 rb)
{
CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0);
if(!CPU.reserve)
{ {
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr) SMutexLocker lock(reservation.mutex);
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8)
{ {
Memory.Write64(addr, CPU.GPR[rs]); // Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true); CPU.SetCR_EQ(0, InterlockedCompareExchange64((volatile long long*)(Memory + addr), CPU.GPR[rs], reservation.data64) == reservation.data64);
reservation.clear();
} }
else else
{ {
static const bool u = 0; CPU.SetCR_EQ(0, false);
if(u) Memory.Write64(addr, CPU.GPR[rs]); if (lock.tid == reservation.owner) reservation.clear();
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
}
} }
} }
void STBX(u32 rs, u32 ra, u32 rb) void STBX(u32 rs, u32 ra, u32 rb)

View file

@ -44,9 +44,6 @@ void PPUThread::DoReset()
VSCR.VSCR = 0; VSCR.VSCR = 0;
cycle = 0; cycle = 0;
reserve = false;
reserve_addr = 0;
} }
void PPUThread::AddArgv(const wxString& arg) void PPUThread::AddArgv(const wxString& arg)
@ -67,14 +64,16 @@ void PPUThread::InitRegs()
SetPc(pc); SetPc(pc);
const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); /*
const s32 thread_num = Emu.GetCPU().GetThread NumById(GetType(), GetId());
if(thread_num < 0) if(thread_num < 0)
{ {
ConLog.Error("GetThreadNumById failed."); ConLog.Error("GetThread NumById failed.");
Emu.Pause(); Emu.Pause();
return; return;
} }
*/
/* /*
const s32 tls_size = Emu.GetTLSFilesz() * thread_num; const s32 tls_size = Emu.GetTLSFilesz() * thread_num;
@ -119,7 +118,7 @@ void PPUThread::InitRegs()
GPR[6] = m_args[3]; GPR[6] = m_args[3];
} }
u32 prx_mem = Memory.PRXMem.Alloc(0x10000); u32 prx_mem = Memory.PRXMem.AllocAlign(0x10000);
Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE); Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE);
GPR[0] = pc; GPR[0] = pc;

View file

@ -602,9 +602,6 @@ public:
}; };
}; };
u64 reserve_addr;
bool reserve;
u64 cycle; u64 cycle;
public: public:

View file

@ -32,15 +32,8 @@ private:
//0 - 10 //0 - 10
void STOP(u32 code) void STOP(u32 code)
{ {
if(code & 0x2000) ConLog.Warning("STOP: 0x%x (m_exit_status -> 0)", code);
{ CPU.SetExitStatus(0);
CPU.SetExitStatus(code & 0xfff);
}
else
{
ConLog.Warning("STOP: 0x%x", code);
//Emu.Pause();
}
CPU.Stop(); CPU.Stop();
} }
void LNOP() void LNOP()
@ -146,7 +139,7 @@ private:
void ROTH(u32 rt, u32 ra, u32 rb) void ROTH(u32 rt, u32 ra, u32 rb)
{ {
for (int h = 0; h < 8; h++) for (int h = 0; h < 8; h++)
CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u16[h] << (CPU.GPR[rb]._u16[h] & 0xf)) | (CPU.GPR[ra]._u16[h] >> (16 - (CPU.GPR[rb]._u32[h] & 0xf))); CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u16[h] << (CPU.GPR[rb]._u16[h] & 0xf)) | (CPU.GPR[ra]._u16[h] >> (16 - (CPU.GPR[rb]._u16[h] & 0xf)));
} }
void ROTHM(u32 rt, u32 ra, u32 rb) void ROTHM(u32 rt, u32 ra, u32 rb)
{ {

View file

@ -61,7 +61,7 @@ void SPUThread::InitRegs()
u64 SPUThread::GetFreeStackSize() const u64 SPUThread::GetFreeStackSize() const
{ {
return (GetStackAddr() + GetStackSize()) - GPR[1]._u64[3]; return (GetStackAddr() + GetStackSize()) - GPR[1]._u32[3];
} }
void SPUThread::DoRun() void SPUThread::DoRun()

View file

@ -4,8 +4,6 @@
#include "MFC.h" #include "MFC.h"
#include <mutex> #include <mutex>
extern std::mutex g_SyncMutex; //can provide compatability for CellSyncMutex through SPU<>PPU and SPU<>SPU
static const char* spu_reg_name[128] = static const char* spu_reg_name[128] =
{ {
"$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7", "$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7",
@ -391,7 +389,7 @@ public:
else else
{ {
#ifdef _M_X64 #ifdef _M_X64
_InterlockedOr64((volatile __int64*)m_indval, ((u64)value << 32) | 1); InterlockedOr64((volatile __int64*)m_indval, ((u64)value << 32) | 1);
#else #else
ConLog.Error("PushUncond_OR(): no code compiled"); ConLog.Error("PushUncond_OR(): no code compiled");
#endif #endif
@ -516,34 +514,80 @@ public:
case MFC_PUT_CMD: case MFC_PUT_CMD:
case MFC_GET_CMD: case MFC_GET_CMD:
{ {
if (enable_log) ConLog.Write("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", /* if (enable_log) ConLog.Write("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
op & MFC_PUT_CMD ? "PUT" : "GET", op & MFC_PUT_CMD ? "PUT" : "GET",
op & MFC_BARRIER_MASK ? "B" : "", op & MFC_BARRIER_MASK ? "B" : "",
op & MFC_FENCE_MASK ? "F" : "", op & MFC_FENCE_MASK ? "F" : "",
lsa, ea, tag, size, cmd); lsa, ea, tag, size, cmd); */
if (op & MFC_PUT_CMD)
{
SMutexLocker lock(reservation.mutex);
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
{
reservation.clear();
}
}
else
{
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
}
} }
break; break;
case MFC_GETLLAR_CMD: case MFC_GETLLAR_CMD:
case MFC_PUTLLC_CMD: case MFC_PUTLLC_CMD:
case MFC_PUTLLUC_CMD: case MFC_PUTLLUC_CMD:
case MFC_PUTQLLUC_CMD:
{ {
if (op == MFC_GETLLAR_CMD) if (enable_log) ConLog.Write("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
{ op == MFC_GETLLAR_CMD ? "GETLLAR" : op == MFC_PUTLLC_CMD ? "PUTLLC" : op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC",
g_SyncMutex.lock();
}
ConLog.Warning("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
op == MFC_GETLLAR_CMD ? "GETLLAR" : op == MFC_PUTLLC_CMD ? "PUTLLC" : "PUTLLUC",
lsa, ea, tag, size, cmd); lsa, ea, tag, size, cmd);
dmac.ProcessCmd(op == MFC_GETLLAR_CMD ? MFC_GET_CMD : MFC_PUT_CMD, tag, lsa, ea, 128); if (op == MFC_GETLLAR_CMD) // get reservation
Prxy.AtomicStat.PushUncond(op == MFC_GETLLAR_CMD ? MFC_GETLLAR_SUCCESS : op == MFC_PUTLLC_CMD ? MFC_PUTLLC_SUCCESS : MFC_PUTLLUC_SUCCESS);
if (op == MFC_PUTLLC_CMD || op == MFC_PUTLLUC_CMD)
{ {
g_SyncMutex.unlock(); SMutexLocker lock(reservation.mutex);
reservation.owner = lock.tid;
reservation.addr = ea;
reservation.size = 128;
dmac.ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128);
Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
}
else if (op == MFC_PUTLLC_CMD) // store conditional
{
SMutexLocker lock(reservation.mutex);
if (reservation.owner == lock.tid) // succeeded
{
if (reservation.addr == ea && reservation.size == 128)
{
dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
}
else
{
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
}
reservation.clear();
}
else // failed
{
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
}
}
else // store unconditional
{
SMutexLocker lock(reservation.mutex);
dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
if (op == MFC_PUTLLUC_CMD)
{
Prxy.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
}
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
{
reservation.clear();
}
} }
} }
break; break;

View file

@ -10,11 +10,13 @@ DynamicMemoryBlockBase<PT>::DynamicMemoryBlockBase()
template<typename PT> template<typename PT>
const u32 DynamicMemoryBlockBase<PT>::GetUsedSize() const const u32 DynamicMemoryBlockBase<PT>::GetUsedSize() const
{ {
std::lock_guard<std::mutex> lock(m_lock);
u32 size = 0; u32 size = 0;
for(u32 i=0; i<m_used_mem.GetCount(); ++i) for(u32 i=0; i<m_allocated.GetCount(); ++i)
{ {
size += m_used_mem[i].size; size += m_allocated[i].size;
} }
return size; return size;
@ -35,38 +37,51 @@ bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr, const u32 size)
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr) bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr)
{ {
for(u32 i=0; i<m_used_mem.GetCount(); ++i) if (!IsInMyRange(addr)) return false;
{
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size)
{
return true;
}
}
return false; const u32 index = MemoryBlock::FixAddr(addr) >> 12;
return m_pages[index] && !m_locked[index];
} }
template<typename PT> template<typename PT>
MemoryBlock* DynamicMemoryBlockBase<PT>::SetRange(const u64 start, const u32 size) MemoryBlock* DynamicMemoryBlockBase<PT>::SetRange(const u64 start, const u32 size)
{ {
m_max_size = size; std::lock_guard<std::mutex> lock(m_lock);
m_max_size = PAGE_4K(size);
MemoryBlock::SetRange(start, 0); MemoryBlock::SetRange(start, 0);
const u32 page_count = m_max_size >> 12;
m_pages.SetCount(page_count);
m_locked.SetCount(page_count);
memset(m_pages.GetPtr(), 0, sizeof(u8*) * page_count);
memset(m_locked.GetPtr(), 0, sizeof(u8*) * page_count);
return this; return this;
} }
template<typename PT> template<typename PT>
void DynamicMemoryBlockBase<PT>::Delete() void DynamicMemoryBlockBase<PT>::Delete()
{ {
m_used_mem.Clear(); std::lock_guard<std::mutex> lock(m_lock);
m_allocated.Clear();
m_max_size = 0; m_max_size = 0;
m_pages.Clear();
m_locked.Clear();
MemoryBlock::Delete(); MemoryBlock::Delete();
} }
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc(u64 addr, u32 size) bool DynamicMemoryBlockBase<PT>::AllocFixed(u64 addr, u32 size)
{ {
size = PAGE_4K(size + (addr & 4095)); // align size
addr &= ~4095; // align start address
if(!IsInMyRange(addr, size)) if(!IsInMyRange(addr, size))
{ {
assert(0); assert(0);
@ -78,43 +93,77 @@ bool DynamicMemoryBlockBase<PT>::Alloc(u64 addr, u32 size)
return false; return false;
} }
for(u32 i=0; i<m_used_mem.GetCount(); ++i) std::lock_guard<std::mutex> lock(m_lock);
for(u32 i=0; i<m_allocated.GetCount(); ++i)
{ {
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) return false; if(addr >= m_allocated[i].addr && addr < m_allocated[i].addr + m_allocated[i].size) return false;
} }
AppendUsedMem(addr, size); AppendMem(addr, size);
return true; return true;
} }
template<typename PT> template<typename PT>
void DynamicMemoryBlockBase<PT>::AppendUsedMem(u64 addr, u32 size) void DynamicMemoryBlockBase<PT>::AppendMem(u64 addr, u32 size) /* private */
{ {
m_used_mem.Move(new MemBlockInfo(addr, size)); u8* pointer = (u8*)m_allocated[m_allocated.Move(new MemBlockInfo(addr, size))].mem;
const u32 first = MemoryBlock::FixAddr(addr) >> 12;
const u32 last = first + ((size - 1) >> 12);
for (u32 i = first; i <= last; i++)
{
m_pages[i] = pointer;
m_locked[i] = nullptr;
pointer += 4096;
}
} }
template<typename PT> template<typename PT>
u64 DynamicMemoryBlockBase<PT>::Alloc(u32 size) u64 DynamicMemoryBlockBase<PT>::AllocAlign(u32 size, u32 align)
{ {
for(u64 addr = MemoryBlock::GetStartAddr(); addr <= MemoryBlock::GetEndAddr() - size;) size = PAGE_4K(size);
u32 exsize;
if (align <= 4096)
{
align = 0;
exsize = size;
}
else
{
align &= ~4095;
exsize = size + align - 1;
}
std::lock_guard<std::mutex> lock(m_lock);
for(u64 addr = MemoryBlock::GetStartAddr(); addr <= MemoryBlock::GetEndAddr() - exsize;)
{ {
bool is_good_addr = true; bool is_good_addr = true;
for(u32 i=0; i<m_used_mem.GetCount(); ++i) for(u32 i=0; i<m_allocated.GetCount(); ++i)
{ {
if((addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) || if((addr >= m_allocated[i].addr && addr < m_allocated[i].addr + m_allocated[i].size) ||
(m_used_mem[i].addr >= addr && m_used_mem[i].addr < addr + size)) (m_allocated[i].addr >= addr && m_allocated[i].addr < addr + exsize))
{ {
is_good_addr = false; is_good_addr = false;
addr = m_used_mem[i].addr + m_used_mem[i].size; addr = m_allocated[i].addr + m_allocated[i].size;
break; break;
} }
} }
if(!is_good_addr) continue; if(!is_good_addr) continue;
AppendUsedMem(addr, size); if (align)
{
addr = (addr + (align - 1)) & ~(align - 1);
}
AppendMem(addr, size);
return addr; return addr;
} }
@ -125,18 +174,38 @@ u64 DynamicMemoryBlockBase<PT>::Alloc(u32 size)
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc() bool DynamicMemoryBlockBase<PT>::Alloc()
{ {
return Alloc(GetSize() - GetUsedSize()) != 0; return AllocAlign(GetSize() - GetUsedSize()) != 0;
} }
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::Free(u64 addr) bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
{ {
for(u32 i=0; i<m_used_mem.GetCount(); ++i) std::lock_guard<std::mutex> lock(m_lock);
for (u32 num = 0; num < m_allocated.GetCount(); num++)
{ {
if(addr == m_used_mem[i].addr) if (addr == m_allocated[num].addr)
{ {
if(IsLocked(m_used_mem[i].addr)) return false; /* if(IsLocked(m_allocated[num].addr)) return false; */
m_used_mem.RemoveAt(i);
const u32 first = MemoryBlock::FixAddr(addr) >> 12;
const u32 last = first + ((m_allocated[num].size - 1) >> 12);
// check if locked:
for (u32 i = first; i <= last; i++)
{
if (!m_pages[i] || m_locked[i]) return false;
}
// clear pointers:
for (u32 i = first; i <= last; i++)
{
m_pages[i] = nullptr;
m_locked[i] = nullptr;
}
m_allocated.RemoveAt(num);
return true; return true;
} }
} }
@ -145,15 +214,15 @@ bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
} }
template<typename PT> template<typename PT>
u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const // lock-free, addr is fixed
{ {
for(u32 i=0; i<m_used_mem.GetCount(); ++i) const u32 index = addr >> 12;
{
u64 _addr = MemoryBlock::FixAddr(m_used_mem[i].addr);
if(addr >= _addr && addr < _addr + m_used_mem[i].size) if (index < m_pages.GetCount())
{ {
return (u8*)m_used_mem[i].mem + addr - _addr; if (u8* res = m_pages[index])
{
return res + (addr & 4095);
} }
} }
@ -163,28 +232,28 @@ u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const
} }
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsLocked(const u64 addr) bool DynamicMemoryBlockBase<PT>::IsLocked(u64 addr) // lock-free
{ {
for(u32 i=0; i<m_locked_mem.GetCount(); ++i) if (IsInMyRange(addr))
{ {
if(addr == m_locked_mem[i].addr) const u32 index = MemoryBlock::FixAddr(addr) >> 12;
if (index < m_locked.GetCount())
{ {
return true; if (m_locked[index]) return true;
} }
} }
return false; return false;
} }
template<typename PT>
void DynamicMemoryBlockBase<PT>::AppendLockedMem(u64 addr, u32 size)
{
m_locked_mem.Move(new MemBlockInfo(addr, size));
}
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size) bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
{ {
size = PAGE_4K(size); // align size
addr &= ~4095; // align start address
if(!IsInMyRange(addr, size)) if(!IsInMyRange(addr, size))
{ {
assert(0); assert(0);
@ -196,33 +265,58 @@ bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
return false; return false;
} }
AppendLockedMem(addr, size); const u32 first = MemoryBlock::FixAddr(addr) >> 12;
const u32 last = first + ((size - 1) >> 12);
for (u32 i = first; i <= last; i++)
{
if (u8* pointer = m_pages[i])
{
m_locked[i] = pointer;
m_pages[i] = nullptr;
}
else // already locked or empty
{
}
}
return true; return true;
} }
template<typename PT> template<typename PT>
bool DynamicMemoryBlockBase<PT>::Unlock(u64 addr , u32 size) bool DynamicMemoryBlockBase<PT>::Unlock(u64 addr, u32 size)
{ {
for(u32 i=0; i<m_locked_mem.GetCount(); ++i) size = PAGE_4K(size); // align size
addr &= ~4095; // align start address
if(!IsInMyRange(addr, size))
{ {
if(addr == m_locked_mem[i].addr) assert(0);
{ return false;
if(m_locked_mem.Get(i).size > size)
{
m_locked_mem.Get(i).size -= size;
} }
else if(m_locked_mem.Get(i).size == size)
{ if(IsMyAddress(addr) || IsMyAddress(addr + size - 1))
m_locked_mem.RemoveAt(i);
}
else
{ {
return false; return false;
} }
return true;
const u32 first = MemoryBlock::FixAddr(addr) >> 12;
const u32 last = first + ((size - 1) >> 12);
for (u32 i = first; i <= last; i++)
{
if (u8* pointer = m_locked[i])
{
m_pages[i] = pointer;
m_locked[i] = nullptr;
}
else // already unlocked or empty
{
} }
} }
return false; return true;
} }

View file

@ -341,7 +341,7 @@ public:
u64 Alloc(const u32 size, const u32 align) u64 Alloc(const u32 size, const u32 align)
{ {
return UserMemory->Alloc(AlignAddr(size, align)); return UserMemory->AllocAlign(size, align);
} }
bool Free(const u64 addr) bool Free(const u64 addr)

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#define PAGE_4K(x) (x + 4095) & ~(4095)
struct MemInfo struct MemInfo
{ {
u64 addr; u64 addr;
@ -21,8 +23,8 @@ struct MemBlockInfo : public MemInfo
void* mem; void* mem;
MemBlockInfo(u64 _addr, u32 _size) MemBlockInfo(u64 _addr, u32 _size)
: MemInfo(_addr, _size) : MemInfo(_addr, PAGE_4K(_size))
, mem(malloc(_size)) , mem(_aligned_malloc(PAGE_4K(_size), 128))
{ {
if(!mem) if(!mem)
{ {
@ -35,7 +37,7 @@ struct MemBlockInfo : public MemInfo
~MemBlockInfo() ~MemBlockInfo()
{ {
free(mem); _aligned_free(mem);
mem = nullptr; mem = nullptr;
} }
}; };
@ -120,8 +122,8 @@ public:
u8* GetMem() const { return mem; } u8* GetMem() const { return mem; }
virtual u8* GetMem(u64 addr) const { return mem + addr; } virtual u8* GetMem(u64 addr) const { return mem + addr; }
virtual bool Alloc(u64 addr, u32 size) { return false; } virtual bool AllocFixed(u64 addr, u32 size) { return false; }
virtual u64 Alloc(u32 size) { return 0; } virtual u64 AllocAlign(u32 size, u32 align = 1) { return 0; }
virtual bool Alloc() { return false; } virtual bool Alloc() { return false; }
virtual bool Free(u64 addr) { return false; } virtual bool Free(u64 addr) { return false; }
virtual bool Lock(u64 addr, u32 size) { return false; } virtual bool Lock(u64 addr, u32 size) { return false; }
@ -190,8 +192,11 @@ class NullMemoryBlock : public MemoryBlock
template<typename PT> template<typename PT>
class DynamicMemoryBlockBase : public PT class DynamicMemoryBlockBase : public PT
{ {
Array<MemBlockInfo> m_used_mem; mutable std::mutex m_lock;
Array<MemBlockInfo> m_locked_mem; Array<MemBlockInfo> m_allocated; // allocation info
Array<u8*> m_pages; // real addresses of every 4096 byte pages (array size should be fixed)
Array<u8*> m_locked; // locked pages should be moved here
u32 m_max_size; u32 m_max_size;
public: public:
@ -209,8 +214,8 @@ public:
virtual void Delete(); virtual void Delete();
virtual bool Alloc(u64 addr, u32 size); virtual bool AllocFixed(u64 addr, u32 size);
virtual u64 Alloc(u32 size); virtual u64 AllocAlign(u32 size, u32 align = 1);
virtual bool Alloc(); virtual bool Alloc();
virtual bool Free(u64 addr); virtual bool Free(u64 addr);
virtual bool Lock(u64 addr, u32 size); virtual bool Lock(u64 addr, u32 size);
@ -219,8 +224,7 @@ public:
virtual u8* GetMem(u64 addr) const; virtual u8* GetMem(u64 addr) const;
private: private:
void AppendUsedMem(u64 addr, u32 size); void AppendMem(u64 addr, u32 size);
void AppendLockedMem(u64 addr, u32 size);
}; };
class VirtualMemoryBlock : public MemoryBlock class VirtualMemoryBlock : public MemoryBlock

View file

@ -83,7 +83,7 @@ struct CellAudioPortConfig
struct CellAudioConfig //custom structure struct CellAudioConfig //custom structure
{ {
bool m_is_audio_initialized; bool m_is_audio_initialized;
bool m_is_audio_port_open; bool m_is_audio_port_opened;
bool m_is_audio_port_started; bool m_is_audio_port_started;
}; };
@ -216,7 +216,7 @@ int cellAudioPortOpen(mem_ptr_t<CellAudioPortParam> audioParam, mem32_t portNum)
cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x,portNum_addr=0x%x)",audioParam.GetAddr(),portNum.GetAddr()); cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x,portNum_addr=0x%x)",audioParam.GetAddr(),portNum.GetAddr());
if(!audioParam.IsGood() || !portNum.IsGood()) return CELL_AUDIO_ERROR_PORT_OPEN; if(!audioParam.IsGood() || !portNum.IsGood()) return CELL_AUDIO_ERROR_PORT_OPEN;
m_config->m_is_audio_port_open = true; m_config->m_is_audio_port_opened = true;
m_param->nChannel = audioParam->nChannel; m_param->nChannel = audioParam->nChannel;
m_param->nBlock = audioParam->nBlock; m_param->nBlock = audioParam->nBlock;
@ -238,13 +238,13 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t<CellAudioPortConfig> portConfi
//if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL; //if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL;
if(m_config->m_is_audio_port_open == false) if(!m_config->m_is_audio_port_opened)
{ {
portConfig->status = CELL_AUDIO_STATUS_CLOSE; portConfig->status = CELL_AUDIO_STATUS_CLOSE;
return CELL_OK; return CELL_OK;
} }
if(m_config->m_is_audio_port_started == true) if(m_config->m_is_audio_port_started)
{ {
portConfig->status = CELL_AUDIO_STATUS_RUN; portConfig->status = CELL_AUDIO_STATUS_RUN;
} }
@ -268,7 +268,7 @@ int cellAudioPortStart(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum); cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum);
if (m_config->m_is_audio_port_open == true) if (!m_config->m_is_audio_port_opened)
return CELL_AUDIO_ERROR_PORT_OPEN; return CELL_AUDIO_ERROR_PORT_OPEN;
m_config->m_is_audio_port_started = true; m_config->m_is_audio_port_started = true;
@ -279,10 +279,10 @@ int cellAudioPortClose(u32 portNum)
{ {
cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",portNum); cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",portNum);
if (m_config->m_is_audio_port_open == false) if (!m_config->m_is_audio_port_opened)
return CELL_AUDIO_ERROR_PORT_NOT_OPEN; return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
m_config->m_is_audio_port_open = false; m_config->m_is_audio_port_opened = false;
return CELL_OK; return CELL_OK;
} }
@ -1016,6 +1016,6 @@ void cellAudio_init()
void cellAudio_unload() void cellAudio_unload()
{ {
m_config->m_is_audio_initialized = false; m_config->m_is_audio_initialized = false;
m_config->m_is_audio_port_open = false; m_config->m_is_audio_port_opened = false;
m_config->m_is_audio_port_started = false; m_config->m_is_audio_port_started = false;
} }

View file

@ -63,7 +63,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
{ {
local_size = 0xf900000; //TODO local_size = 0xf900000; //TODO
local_addr = Memory.RSXFBMem.GetStartAddr(); local_addr = Memory.RSXFBMem.GetStartAddr();
Memory.RSXFBMem.Alloc(local_size); Memory.RSXFBMem.AllocAlign(local_size);
} }
cellGcmSys.Warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size); cellGcmSys.Warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size);
@ -78,7 +78,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
current_config.coreFrequency = re32(500000000); current_config.coreFrequency = re32(500000000);
InitOffsetTable(); InitOffsetTable();
Memory.RSXCMDMem.Alloc(cmdSize); Memory.RSXCMDMem.AllocAlign(cmdSize);
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
cellGcmMapEaIoAddress(ioAddress, 0, ioSize); cellGcmMapEaIoAddress(ioAddress, 0, ioSize);
@ -89,7 +89,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
current_context.current = current_context.begin; current_context.current = current_context.begin;
current_context.callback = re32(Emu.GetRSXCallback() - 4); current_context.callback = re32(Emu.GetRSXCallback() - 4);
gcm_info.context_addr = Memory.MainMem.Alloc(0x1000); gcm_info.context_addr = Memory.MainMem.AllocAlign(0x1000);
gcm_info.control_addr = gcm_info.context_addr + 0x40; gcm_info.control_addr = gcm_info.context_addr + 0x40;
Memory.WriteData(gcm_info.context_addr, current_context); Memory.WriteData(gcm_info.context_addr, current_context);
@ -167,7 +167,7 @@ int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id)
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); // could stall on exit
u32 current = re(ctxt->current); u32 current = re(ctxt->current);
u32 end = re(ctxt->end); u32 end = re(ctxt->end);
@ -682,7 +682,7 @@ int32_t cellGcmMapLocalMemory(u64 address, u64 size)
{ {
local_size = 0xf900000; //TODO local_size = 0xf900000; //TODO
local_addr = Memory.RSXFBMem.GetStartAddr(); local_addr = Memory.RSXFBMem.GetStartAddr();
Memory.RSXFBMem.Alloc(local_size); Memory.RSXFBMem.AllocAlign(local_size);
Memory.Write32(address, local_addr); Memory.Write32(address, local_addr);
Memory.Write32(size, local_size); Memory.Write32(size, local_size);
} }
@ -749,7 +749,7 @@ int32_t cellGcmUnmapEaIoAddress(u64 ea)
ea = ea >> 20; ea = ea >> 20;
io = Memory.Read16(offsetTable.io + (ea*sizeof(u16))); io = Memory.Read16(offsetTable.io + (ea*sizeof(u16)));
for(int i=0; i<size; i++) for(u32 i=0; i<size; i++)
{ {
Memory.Write16(offsetTable.io + ((ea+i)*sizeof(u16)), 0xFFFF); Memory.Write16(offsetTable.io + ((ea+i)*sizeof(u16)), 0xFFFF);
Memory.Write16(offsetTable.ea + ((io+i)*sizeof(u16)), 0xFFFF); Memory.Write16(offsetTable.ea + ((io+i)*sizeof(u16)), 0xFFFF);
@ -772,7 +772,7 @@ int32_t cellGcmUnmapIoAddress(u64 io)
io = io >> 20; io = io >> 20;
ea = Memory.Read16(offsetTable.ea + (io*sizeof(u16))); ea = Memory.Read16(offsetTable.ea + (io*sizeof(u16)));
for(int i=0; i<size; i++) for(u32 i=0; i<size; i++)
{ {
Memory.Write16(offsetTable.io + ((ea+i)*sizeof(u16)), 0xFFFF); Memory.Write16(offsetTable.io + ((ea+i)*sizeof(u16)), 0xFFFF);
Memory.Write16(offsetTable.ea + ((io+i)*sizeof(u16)), 0xFFFF); Memory.Write16(offsetTable.ea + ((io+i)*sizeof(u16)), 0xFFFF);

View file

@ -480,7 +480,7 @@ int cellPamfReaderGetStreamInfo(mem_ptr_t<CellPamfReader> pSelf, u32 pInfo_addr,
pInfo->numberOfChannels = pAudio->channels; pInfo->numberOfChannels = pAudio->channels;
pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; pInfo->samplingFrequency = CELL_PAMF_FS_48kHz;
if (pAudio->bps = 0x40) if (pAudio->bps == 0x40)
pInfo->bitsPerSample = CELL_PAMF_BIT_LENGTH_16; pInfo->bitsPerSample = CELL_PAMF_BIT_LENGTH_16;
else else
//TODO: CELL_PAMF_BIT_LENGTH_24 //TODO: CELL_PAMF_BIT_LENGTH_24

View file

@ -4,9 +4,7 @@
#include <mutex> #include <mutex>
void cellSync_init(); void cellSync_init();
void cellSync_unload(); Module cellSync("cellSync", cellSync_init);
Module cellSync("cellSync", cellSync_init, nullptr, cellSync_unload);
std::mutex g_SyncMutex;
// Return Codes // Return Codes
enum enum
@ -56,8 +54,13 @@ int cellSyncMutexInitialize(mem_ptr_t<CellSyncMutex> mutex)
return CELL_SYNC_ERROR_ALIGN; return CELL_SYNC_ERROR_ALIGN;
} }
{ // global mutex {
std::lock_guard<std::mutex> lock(g_SyncMutex); //??? SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
mutex->m_data = 0; mutex->m_data = 0;
return CELL_OK; return CELL_OK;
} }
@ -77,8 +80,13 @@ int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
} }
be_t<u16> old_order; be_t<u16> old_order;
{ // global mutex {
std::lock_guard<std::mutex> lock(g_SyncMutex); SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
old_order = mutex->m_order; old_order = mutex->m_order;
mutex->m_order = mutex->m_order + 1; mutex->m_order = mutex->m_order + 1;
if (old_order == mutex->m_freed) if (old_order == mutex->m_freed)
@ -98,7 +106,6 @@ int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
mutex.GetAddr(), (u16)old_order, (u16)mutex->m_order, (u16)mutex->m_freed); mutex.GetAddr(), (u16)old_order, (u16)mutex->m_order, (u16)mutex->m_freed);
} }
} }
//while (_InterlockedExchange((volatile long*)&mutex->m_data, 1)) Sleep(1);
_mm_mfence(); _mm_mfence();
return CELL_OK; return CELL_OK;
} }
@ -115,8 +122,13 @@ int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
{ {
return CELL_SYNC_ERROR_ALIGN; return CELL_SYNC_ERROR_ALIGN;
} }
{ /* global mutex */ {
std::lock_guard<std::mutex> lock(g_SyncMutex); SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
if (mutex->m_order != mutex->m_freed) if (mutex->m_order != mutex->m_freed)
{ {
return CELL_SYNC_ERROR_BUSY; return CELL_SYNC_ERROR_BUSY;
@ -140,7 +152,12 @@ int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> mutex)
} }
{ /* global mutex */ { /* global mutex */
std::lock_guard<std::mutex> lock(g_SyncMutex); SMutexLocker lock(reservation.mutex);
if ((reservation.addr + reservation.size > mutex.GetAddr() && reservation.addr <= mutex.GetAddr() + 4) ||
(mutex.GetAddr() + 4 > reservation.addr && mutex.GetAddr() <= reservation.addr + reservation.size))
{
reservation.clear();
}
mutex->m_freed = mutex->m_freed + 1; mutex->m_freed = mutex->m_freed + 1;
return CELL_OK; return CELL_OK;
} }
@ -153,8 +170,3 @@ void cellSync_init()
cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock); cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock);
cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock); cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock);
} }
void cellSync_unload()
{
g_SyncMutex.unlock();
}

View file

@ -460,6 +460,11 @@ int cellSysutilCheckCallback()
cellSysutil.Log("cellSysutilCheckCallback()"); cellSysutil.Log("cellSysutilCheckCallback()");
Emu.GetCallbackManager().m_exit_callback.Check(); Emu.GetCallbackManager().m_exit_callback.Check();
CPUThread& thr = Emu.GetCallbackThread();
while(Emu.IsRunning() && thr.IsAlive())
Sleep(1);
return CELL_OK; return CELL_OK;
} }

View file

@ -164,6 +164,7 @@ void sysPrxForUser_init()
//sysPrxForUser.AddFunc(0xaede4b03, sys_heap_free); //sysPrxForUser.AddFunc(0xaede4b03, sys_heap_free);
//sysPrxForUser.AddFunc(0x8a561d92, sys_heap_delete_heap); //sysPrxForUser.AddFunc(0x8a561d92, sys_heap_delete_heap);
sysPrxForUser.AddFunc(0xb2fcf2c8, sys_heap_create_heap); sysPrxForUser.AddFunc(0xb2fcf2c8, sys_heap_create_heap);
sysPrxForUser.AddFunc(0x44265c08, _sys_heap_memalign);
sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory); sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory);
sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory); sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory);

View file

@ -176,8 +176,8 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
} }
//start callback thread //start callback thread
//if(func) if(func)
//func.async(aio, error, xid, res); func.async(aio, error, xid, res);
ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=%d, res=%d, xid=%d [%s])", ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=%d, res=%d, xid=%d [%s])",
fd, (u64)aio->offset, buf_addr, (u64)aio->size, res, xid, path.c_str()); fd, (u64)aio->offset, buf_addr, (u64)aio->size, res, xid, path.c_str());
@ -195,6 +195,7 @@ int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func)); thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
t.detach(); t.detach();
//fsAioRead(fd, aio, xid, func);
aio_id = xid; aio_id = xid;

View file

@ -87,20 +87,20 @@ static func_caller* sc_table[1024] =
bind_func(sys_rwlock_wunlock), //127 (0x07F) bind_func(sys_rwlock_wunlock), //127 (0x07F)
bind_func(sys_event_queue_create), //128 (0x080) bind_func(sys_event_queue_create), //128 (0x080)
null_func, //129 (0x081) null_func, //129 (0x081)
bind_func(sys_event_queue_receive), null_func, bind_func(sys_event_flag_cancel), null_func, bind_func(sys_event_port_create), //134 bind_func(sys_event_queue_receive), null_func, bind_func(sys_event_flag_cancel), bind_func(sys_event_queue_drain), bind_func(sys_event_port_create), //134
null_func, bind_func(sys_event_port_connect_local), null_func, bind_func(sys_event_port_send), bind_func(sys_event_flag_get), //139 null_func, bind_func(sys_event_port_connect_local), null_func, bind_func(sys_event_port_send), bind_func(sys_event_flag_get), //139
null_func, bind_func(sys_timer_usleep), bind_func(sys_timer_sleep), null_func, bind_func(sys_time_get_timezone), //144 null_func, bind_func(sys_timer_usleep), bind_func(sys_timer_sleep), null_func, bind_func(sys_time_get_timezone), //144
bind_func(sys_time_get_current_time), bind_func(sys_time_get_system_time), bind_func(sys_time_get_timebase_frequency), null_func, null_func, //149 bind_func(sys_time_get_current_time), bind_func(sys_time_get_system_time), bind_func(sys_time_get_timebase_frequency), null_func, null_func, //149
null_func, null_func, null_func, null_func, null_func, //154 null_func, null_func, null_func, null_func, null_func, //154
null_func, bind_func(sys_spu_image_open), null_func, null_func, null_func, //159 null_func, bind_func(sys_spu_image_open), null_func, null_func, null_func, //159
bind_func(sys_raw_spu_create), null_func, null_func, null_func, null_func, //164 bind_func(sys_raw_spu_create), null_func, null_func, null_func, null_func, //164
null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169 bind_func(sys_spu_thread_get_exit_status), bind_func(sys_spu_thread_set_argument), null_func, null_func, bind_func(sys_spu_initialize), //169
bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), //172 bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_group_destroy), bind_func(sys_spu_thread_initialize), //172
bind_func(sys_spu_thread_group_start), bind_func(sys_spu_thread_group_suspend), //174 bind_func(sys_spu_thread_group_start), bind_func(sys_spu_thread_group_suspend), //174
null_func, null_func, null_func, bind_func(sys_spu_thread_group_join), null_func, //179 null_func, null_func, null_func, bind_func(sys_spu_thread_group_join), null_func, //179
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184 null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184
null_func, null_func, bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189 null_func, null_func, bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189
bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, null_func, null_func, //194 bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, bind_func(sys_spu_thread_bind_queue), null_func, //194
null_func, null_func, null_func, null_func, null_func, //199 null_func, null_func, null_func, null_func, null_func, //199
null_func, null_func, null_func, null_func, null_func, //204 null_func, null_func, null_func, null_func, null_func, //204
null_func, null_func, null_func, null_func, null_func, //209 null_func, null_func, null_func, null_func, null_func, //209

View file

@ -7,6 +7,7 @@
#include "lv2/SC_SPU_Thread.h" #include "lv2/SC_SPU_Thread.h"
#include "lv2/SC_Lwmutex.h" #include "lv2/SC_Lwmutex.h"
#include "lv2/SC_Lwcond.h" #include "lv2/SC_Lwcond.h"
#include "lv2/SC_Event_flag.h"
#include "Emu/event.h" #include "Emu/event.h"
//#define SYSCALLS_DEBUG //#define SYSCALLS_DEBUG
@ -126,19 +127,22 @@ extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_add
u32 data, u32 data_size, int prio, u64 flags ); u32 data, u32 data_size, int prio, u64 flags );
//sys_event //sys_event
extern int sys_event_flag_create(u32 eflag_id_addr, u32 attr_addr, u64 init); extern int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size);
extern int sys_event_flag_destroy(u32 eflag_id);
extern int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr, u32 timeout);
extern int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr);
extern int sys_event_flag_set(u32 eflag_id, u64 bitptn);
extern int sys_event_flag_clear(u32 eflag_id, u64 bitptn);
extern int sys_event_flag_cancel(u32 eflag_id, u32 num_addr);
extern int sys_event_flag_get(u32 eflag_id, u32 flag_addr);
extern int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size);
extern int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout); extern int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout);
extern int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name); extern int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name);
extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id); extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
extern int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3); extern int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3);
extern int sys_event_queue_drain(u32 event_queue_id);
//sys_event_flag
extern int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init);
extern int sys_event_flag_destroy(u32 eflag_id);
extern int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u32 timeout);
extern int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result);
extern int sys_event_flag_set(u32 eflag_id, u64 bitptn);
extern int sys_event_flag_clear(u32 eflag_id, u64 bitptn);
extern int sys_event_flag_cancel(u32 eflag_id, mem32_t num);
extern int sys_event_flag_get(u32 eflag_id, mem64_t flags);
//sys_semaphore //sys_semaphore
extern int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_val, int max_val); extern int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_val, int max_val);
@ -188,10 +192,9 @@ extern int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr);
extern int sys_ppu_thread_get_stack_information(u32 info_addr); extern int sys_ppu_thread_get_stack_information(u32 info_addr);
extern int sys_ppu_thread_stop(u32 thread_id); extern int sys_ppu_thread_stop(u32 thread_id);
extern int sys_ppu_thread_restart(u32 thread_id); extern int sys_ppu_thread_restart(u32 thread_id);
extern int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); extern int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry); extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry);
extern int sys_ppu_thread_get_id(const u32 id_addr); extern int sys_ppu_thread_get_id(const u32 id_addr);
extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr);
//memory //memory
extern int sys_memory_container_create(u32 cid_addr, u32 yield_size); extern int sys_memory_container_create(u32 cid_addr, u32 yield_size);
@ -293,17 +296,20 @@ extern int sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr);
//sys_heap //sys_heap
extern int sys_heap_create_heap(const u32 heap_addr, const u32 start_addr, const u32 size); extern int sys_heap_create_heap(const u32 heap_addr, const u32 start_addr, const u32 size);
extern int sys_heap_malloc(const u32 heap_addr, const u32 size); extern int sys_heap_malloc(const u32 heap_addr, const u32 size);
extern int _sys_heap_memalign(u32 heap_id, u32 align, u32 size, u64 p4);
//sys_spu //sys_spu
extern int sys_spu_image_open(mem_ptr_t<sys_spu_image> img, u32 path_addr); extern int sys_spu_image_open(mem_ptr_t<sys_spu_image> img, u32 path_addr);
extern int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<sys_spu_image> img, mem_ptr_t<sys_spu_thread_attribute> attr, mem_ptr_t<sys_spu_thread_argument> arg); extern int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<sys_spu_image> img, mem_ptr_t<sys_spu_thread_attribute> attr, mem_ptr_t<sys_spu_thread_argument> arg);
extern int sys_spu_thread_set_argument(u32 id, mem_ptr_t<sys_spu_thread_argument> arg); extern int sys_spu_thread_set_argument(u32 id, mem_ptr_t<sys_spu_thread_argument> arg);
extern int sys_spu_thread_group_destroy(u32 id);
extern int sys_spu_thread_group_start(u32 id); extern int sys_spu_thread_group_start(u32 id);
extern int sys_spu_thread_group_suspend(u32 id); extern int sys_spu_thread_group_suspend(u32 id);
extern int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr); extern int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr);
extern int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); extern int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
extern int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup); extern int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup);
extern int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status); extern int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status);
extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr);
extern int sys_raw_spu_create(mem32_t id, u32 attr_addr); extern int sys_raw_spu_create(mem32_t id, u32 attr_addr);
extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type); extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
@ -312,6 +318,8 @@ extern int sys_spu_thread_write_spu_mb(u32 id, u32 value);
extern int sys_spu_thread_set_spu_cfg(u32 id, u64 value); extern int sys_spu_thread_set_spu_cfg(u32 id, u64 value);
extern int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value); extern int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value);
extern int sys_spu_thread_write_snr(u32 id, u32 number, u32 value); extern int sys_spu_thread_write_snr(u32 id, u32 number, u32 value);
extern int sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num);
extern int sys_spu_thread_get_exit_status(u32 id, mem32_t status);
//sys_time //sys_time
extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime); extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime);

View file

@ -27,7 +27,7 @@ struct condition
int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr) int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr)
{ {
sys_cond.Log("sys_cond_create(cond_addr=0x%x, mutex_id=0x%x, attr_addr=%d)", sys_cond.Warning("sys_cond_create(cond_addr=0x%x, mutex_id=0x%x, attr_addr=%d)",
cond_addr, mutex_id, attr_addr); cond_addr, mutex_id, attr_addr);
if(!Memory.IsGoodAddr(cond_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT; if(!Memory.IsGoodAddr(cond_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT;
@ -68,9 +68,32 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
condition* cond_data = nullptr; condition* cond_data = nullptr;
if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH; if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH;
cond_data->cond.WaitTimeout(timeout ? timeout : INFINITE); u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
return CELL_OK; switch (cond_data->cond.WaitTimeout(1))
{
case wxCOND_NO_ERROR: return CELL_OK;
case wxCOND_TIMEOUT: break;
default: return CELL_EPERM;
}
if (counter++ > max_counter)
{
if (!timeout)
{
sys_cond.Warning("sys_cond_wait(cond_id=0x%x, timeout=0x%llx): TIMEOUT", cond_id, timeout);
counter = 0;
}
else
{
return CELL_ETIMEDOUT;
}
}
} while (true);
} }
int sys_cond_signal(u32 cond_id) int sys_cond_signal(u32 cond_id)

View file

@ -5,128 +5,25 @@
SysCallBase sys_event("sys_event"); SysCallBase sys_event("sys_event");
int sys_event_flag_create(u32 eflag_id_addr, u32 attr_addr, u64 init)
{
sys_event.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)", eflag_id_addr, attr_addr, init);
if(!Memory.IsGoodAddr(eflag_id_addr, 4) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_event_flag_attr)))
{
return CELL_EFAULT;
}
sys_event_flag_attr attr = (sys_event_flag_attr&)Memory[attr_addr];
attr.protocol = re(attr.protocol);
attr.pshared = re(attr.pshared);
attr.ipc_key = re(attr.ipc_key);
attr.flags = re(attr.flags);
attr.type = re(attr.type);
sys_event.Warning("name = %s", attr.name);
sys_event.Warning("type = %d", attr.type);
Memory.Write32(eflag_id_addr, sys_event.GetNewId(new event_flag(init, attr)));
return CELL_OK;
}
int sys_event_flag_destroy(u32 eflag_id)
{
sys_event.Warning("sys_event_flag_destroy(eflag_id=0x%x)", eflag_id);
if(!sys_event.CheckId(eflag_id)) return CELL_ESRCH;
Emu.GetIdManager().RemoveID(eflag_id);
return CELL_OK;
}
int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr, u32 timeout)
{
sys_event.Warning("Unimplemented function: sys_event_flag_wait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=0x%x)"
, eflag_id, bitptn, mode, result_addr, timeout);
return CELL_OK;
}
int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr)
{
sys_event.Warning("Unimplemented function: sys_event_flag_trywait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)"
, eflag_id, bitptn, mode, result_addr);
return CELL_OK;
}
int sys_event_flag_set(u32 eflag_id, u64 bitptn)
{
sys_event.Warning("sys_event_flag_set(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn);
event_flag* event_flag_data = nullptr;
if(!sys_event.CheckId(eflag_id, event_flag_data)) return CELL_ESRCH;
event_flag_data->pattern |= bitptn;
return CELL_OK;
}
int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
{
sys_event.Warning("sys_event_flag_clear(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn);
event_flag* event_flag_data = nullptr;
if(!sys_event.CheckId(eflag_id, event_flag_data)) return CELL_ESRCH;
event_flag_data->pattern &= bitptn;
return CELL_OK;
}
int sys_event_flag_cancel(u32 eflag_id, u32 num_addr)
{
sys_event.Warning("Unimplemented function: sys_event_flag_cancel(eflag_id=0x%x, num_addr=0x%x)"
, eflag_id, num_addr);
return CELL_OK;
}
int sys_event_flag_get(u32 eflag_id, u32 flag_addr)
{
sys_event.Warning("sys_event_flag_get(eflag_id=0x%x, flag_addr=0x%x)", eflag_id, flag_addr);
if(!Memory.IsGoodAddr(flag_addr, 4))
{
return CELL_EFAULT;
}
event_flag* event_flag_data = nullptr;
if(!sys_event.CheckId(eflag_id, event_flag_data)) return CELL_ESRCH;
Memory.Write64(flag_addr, event_flag_data->pattern);
return CELL_OK;
}
//128 //128
int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size) int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size)
{ {
sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)", sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)",
equeue_id_addr, attr_addr, event_queue_key, size); equeue_id.GetAddr(), attr.GetAddr(), event_queue_key, size);
if(size <= 0 || size > 127) if(size <= 0 || size > 127)
{ {
return CELL_EINVAL; return CELL_EINVAL;
} }
if(!Memory.IsGoodAddr(equeue_id_addr, 4) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_event_queue_attr))) if(!equeue_id.IsGood() || !attr.IsGood())
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
auto& attr = (sys_event_queue_attr&)Memory[attr_addr]; equeue_id = sys_event.GetNewId(new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size));
sys_event.Warning("name = %s", attr.name); sys_event.Warning("*** event_queue created[%s] (protocol=0x%x, type=0x%x): id = %d",
sys_event.Warning("type = %d", re(attr.type)); attr->name, (u32)attr->protocol, (int)attr->type, equeue_id.GetValue());
EventQueue* equeue = new EventQueue();
equeue->size = size;
equeue->pos = 0;
equeue->type = re(attr.type);
strncpy(equeue->name, attr.name, 8);
Memory.Write32(equeue_id_addr, sys_event.GetNewId(equeue));
return CELL_OK; return CELL_OK;
} }
@ -176,10 +73,10 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout)
{ {
auto dst = (sys_event_data&)Memory[event_addr]; auto dst = (sys_event_data&)Memory[event_addr];
re(dst.source, equeue->ports[i]->name); dst.source = equeue->ports[i]->name;
re(dst.data1, equeue->ports[i]->data1); dst.data1 = equeue->ports[i]->data1;
re(dst.data2, equeue->ports[i]->data2); dst.data2 = equeue->ports[i]->data2;
re(dst.data3, equeue->ports[i]->data3); dst.data3 = equeue->ports[i]->data3;
equeue->ports[i]->has_data = false; equeue->ports[i]->has_data = false;
@ -266,3 +163,10 @@ int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3)
return CELL_OK; return CELL_OK;
} }
int sys_event_queue_drain(u32 event_queue_id)
{
sys_event.Error("sys_event_queue_drain(event_queue_id=0x%x)", event_queue_id);
return CELL_OK;
}

View file

@ -0,0 +1,115 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/lv2/SC_Event_flag.h"
SysCallBase sys_event_flag("sys_event_flag");
int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init)
{
sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)", eflag_id.GetAddr(), attr.GetAddr(), init);
if(!eflag_id.IsGood() || !attr.IsGood())
{
return CELL_EFAULT;
}
switch (attr->protocol.ToBE())
{
case se32(SYS_SYNC_PRIORITY): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
case se32(SYS_SYNC_RETRY): break;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case se32(SYS_SYNC_FIFO): sys_event_flag.Warning("TODO: SYS_SYNC_FIFO attr"); break;
default: return CELL_EINVAL;
}
if (attr->pshared.ToBE() != se32(0x200))
{
return CELL_EINVAL;
}
switch (attr->type.ToBE())
{
case se32(SYS_SYNC_WAITER_SINGLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_SINGLE type"); break;
case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break;
default: return CELL_EINVAL;
}
eflag_id = sys_event_flag.GetNewId(new event_flag(init, (u32)attr->protocol, (int)attr->type));
sys_event_flag.Warning("*** event_flag created[%s] (protocol=%d, type=%d): id = %d", attr->name, (u32)attr->protocol, (int)attr->type, eflag_id.GetValue());
return CELL_OK;
}
int sys_event_flag_destroy(u32 eflag_id)
{
sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=0x%x)", eflag_id);
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
Emu.GetIdManager().RemoveID(eflag_id);
return CELL_OK;
}
int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u32 timeout)
{
sys_event_flag.Error("sys_event_flag_wait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=0x%x)",
eflag_id, bitptn, mode, result.GetAddr(), timeout);
return CELL_OK;
}
int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result)
{
sys_event_flag.Error("sys_event_flag_trywait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)",
eflag_id, bitptn, mode, result.GetAddr());
return CELL_OK;
}
int sys_event_flag_set(u32 eflag_id, u64 bitptn)
{
sys_event_flag.Warning("sys_event_flag_set(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn);
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
ef->flags |= bitptn;
return CELL_OK;
}
int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
{
sys_event_flag.Warning("sys_event_flag_clear(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn);
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
ef->flags &= bitptn;
return CELL_OK;
}
int sys_event_flag_cancel(u32 eflag_id, mem32_t num)
{
sys_event_flag.Error("sys_event_flag_cancel(eflag_id=0x%x, num_addr=0x%x)", eflag_id, num.GetAddr());
return CELL_OK;
}
int sys_event_flag_get(u32 eflag_id, mem64_t flags)
{
sys_event_flag.Warning("sys_event_flag_get(eflag_id=0x%x, flags_addr=0x%x)", eflag_id, flags.GetAddr());
if (!flags.IsGood())
{
return CELL_EFAULT;
}
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
flags = ef->flags;
return CELL_OK;
}

View file

@ -0,0 +1,31 @@
#pragma once
enum
{
SYS_SYNC_WAITER_SINGLE = 0x10000,
SYS_SYNC_WAITER_MULTIPLE = 0x20000,
};
struct sys_event_flag_attr
{
be_t<u32> protocol;
be_t<u32> pshared;
be_t<u64> ipc_key;
be_t<int> flags;
be_t<int> type;
char name[8];
};
struct event_flag
{
std::atomic<u64> flags;
const u32 m_protocol;
const int m_type;
event_flag(u64 pattern, u32 protocol, int type)
: flags(pattern)
, m_protocol(protocol)
, m_type(type)
{
}
};

View file

@ -7,7 +7,7 @@ extern gcmInfo gcm_info;
int cellGcmCallback(u32 context_addr, u32 count) int cellGcmCallback(u32 context_addr, u32 count)
{ {
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); // could stall on exit
CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr]; CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr];
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr]; CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];

View file

@ -20,7 +20,10 @@ struct HeapInfo
int sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size) int sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size)
{ {
sc_heap.Warning("sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size); sc_heap.Warning("sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size);
return sc_heap.GetNewId(new HeapInfo(heap_addr, align, size));
u32 heap_id = sc_heap.GetNewId(new HeapInfo(heap_addr, align, size));
sc_heap.Warning("*** sys_heap created(): id=0x%x", heap_id);
return heap_id;
} }
int sys_heap_malloc(const u32 heap_id, const u32 size) int sys_heap_malloc(const u32 heap_id, const u32 size)
@ -30,5 +33,15 @@ int sys_heap_malloc(const u32 heap_id, const u32 size)
HeapInfo* heap; HeapInfo* heap;
if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH; if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH;
return Memory.Alloc(size, heap->align); return Memory.Alloc(size, 1);
}
int _sys_heap_memalign(u32 heap_id, u32 align, u32 size, u64 p4)
{
sc_heap.Warning("_sys_heap_memalign(heap_id=0x%x, align=0x%x, size=0x%x, p4=0x%llx, ... ???)", heap_id, align, size, p4);
HeapInfo* heap;
if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH;
return Memory.Alloc(size, align);
} }

View file

@ -7,25 +7,16 @@ SysCallBase sys_lwcond("sys_lwcond");
int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwcond_attribute_t> attr) int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwcond_attribute_t> attr)
{ {
sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)", sys_lwcond.Log("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)",
lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr()); lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr());
if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
u32 protocol = (u32)lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK; lwcond->lwmutex = lwmutex.GetAddr();
switch (protocol) lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(attr->name_u64));
{
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_RETRY: sys_lwcond.Error("Invalid SYS_SYNC_RETRY attr"); break;
case SYS_SYNC_PRIORITY_INHERIT: sys_lwcond.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case SYS_SYNC_FIFO: break;
default: sys_lwcond.Error("Invalid lwmutex protocol(%d)", protocol); break;
}
lwcond->lwmutex_addr = lwmutex.GetAddr(); sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id=0x%x",
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(protocol, *(u64*)&attr->name)); attr->name, (u32)lwmutex->attribute, (u32)lwmutex->sleep_queue, (u32)lwcond->lwcond_queue);
sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x): id=%d", attr->name, protocol, (u32)lwcond->lwcond_queue);
return CELL_OK; return CELL_OK;
} }
@ -44,21 +35,21 @@ int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond)
int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond) int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
{ {
sys_lwcond.Warning("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.GetAddr()); sys_lwcond.Log("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.GetAddr());
if (!lwcond.IsGood()) return CELL_EFAULT; if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc; LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue; u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
lwc->signal(); lwc->signal(mem_ptr_t<sys_lwmutex_t>(lwcond->lwmutex)->attribute);
return CELL_OK; return CELL_OK;
} }
int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond) int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
{ {
sys_lwcond.Warning("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.GetAddr()); sys_lwcond.Log("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.GetAddr());
if (!lwcond.IsGood()) return CELL_EFAULT; if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc; LWCond* lwc;
@ -72,7 +63,7 @@ int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id) int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
{ {
sys_lwcond.Warning("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.GetAddr(), ppu_thread_id); sys_lwcond.Log("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.GetAddr(), ppu_thread_id);
if (!lwcond.IsGood()) return CELL_EFAULT; if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc; LWCond* lwc;
@ -86,16 +77,17 @@ int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout) int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
{ {
sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%llu)", lwcond.GetAddr(), timeout); sys_lwcond.Log("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%llu)", lwcond.GetAddr(), timeout);
if (!lwcond.IsGood()) return CELL_EFAULT; if (!lwcond.IsGood()) return CELL_EFAULT;
LWCond* lwc; LWCond* lwc;
u32 id = (u32)lwcond->lwcond_queue; u32 id = (u32)lwcond->lwcond_queue;
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
const u32 tid = GetCurrentPPUThread().GetId(); const u32 tid = GetCurrentPPUThread().GetId();
mem_ptr_t<sys_lwmutex_t> lwmutex((u32)lwcond->lwmutex_addr);
if ((u32)lwmutex->owner != tid) return CELL_EPERM; // caller must own this lwmutex mem_ptr_t<sys_lwmutex_t> lwmutex(lwcond->lwmutex);
if ((u32)lwmutex->owner.GetOwner() != tid) return CELL_EPERM; // caller must own this lwmutex
lwc->begin_waiting(tid); lwc->begin_waiting(tid);
u32 counter = 0; u32 counter = 0;

View file

@ -2,12 +2,16 @@
struct sys_lwcond_attribute_t struct sys_lwcond_attribute_t
{ {
union
{
char name[8]; char name[8];
u64 name_u64;
};
}; };
struct sys_lwcond_t struct sys_lwcond_t
{ {
be_t<u32> lwmutex_addr; be_t<u32> lwmutex;
be_t<u32> lwcond_queue; be_t<u32> lwcond_queue;
}; };
@ -18,22 +22,20 @@ struct LWCond
std::mutex m_lock; std::mutex m_lock;
Array<u32> waiters; // list of waiting threads Array<u32> waiters; // list of waiting threads
Array<u32> signaled; // list of signaled threads Array<u32> signaled; // list of signaled threads
u32 m_protocol; // protocol
u64 m_name; // not used u64 m_name; // not used
LWCond(u32 prot, u64 name) LWCond(u64 name)
: m_name(name) : m_name(name)
, m_protocol(prot)
{ {
} }
void signal() void signal(u32 _protocol)
{ {
std::lock_guard<std::mutex> lock(m_lock); std::lock_guard<std::mutex> lock(m_lock);
if (waiters.GetCount()) if (waiters.GetCount())
{ {
if (m_protocol == SYS_SYNC_PRIORITY) if ((_protocol & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_PRIORITY)
{ {
u64 max_prio = 0; u64 max_prio = 0;
u32 sel = 0; u32 sel = 0;

View file

@ -5,125 +5,87 @@
SysCallBase sc_lwmutex("sys_lwmutex"); SysCallBase sc_lwmutex("sys_lwmutex");
std::mutex g_lwmutex;
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr) int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr)
{ {
sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)", sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
lwmutex.GetAddr(), attr.GetAddr()); lwmutex.GetAddr(), attr.GetAddr());
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
switch ((u32)attr->attr_recursive) switch (attr->attr_recursive.ToBE())
{ {
case SYS_SYNC_RECURSIVE: break; case se32(SYS_SYNC_RECURSIVE): break;
case SYS_SYNC_NOT_RECURSIVE: break; case se32(SYS_SYNC_NOT_RECURSIVE): break;
default: return CELL_EINVAL; default: sc_lwmutex.Error("Unknown 0x%x recursive attr", (u32)attr->attr_recursive); return CELL_EINVAL;
} }
switch ((u32)attr->attr_protocol) switch (attr->attr_protocol.ToBE())
{ {
case SYS_SYNC_PRIORITY: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY attr"); break; case se32(SYS_SYNC_PRIORITY): break;
case SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break; case se32(SYS_SYNC_RETRY): break;
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; case se32(SYS_SYNC_PRIORITY_INHERIT): sc_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL;
case SYS_SYNC_FIFO: sc_lwmutex.Warning("TODO: SYS_SYNC_FIFO attr"); break; case se32(SYS_SYNC_FIFO): break;
default: return CELL_EINVAL; default: sc_lwmutex.Error("Unknown 0x%x protocol attr", (u32)attr->attr_protocol); return CELL_EINVAL;
} }
lwmutex->attribute = (u32)attr->attr_protocol | (u32)attr->attr_recursive; lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
lwmutex->all_info = 0; lwmutex->all_info = 0;
lwmutex->pad = 0; lwmutex->pad = 0;
lwmutex->recursive_count = 0; lwmutex->recursive_count = 0;
lwmutex->sleep_queue = 0;
sc_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): id=???", attr->name, (u32)lwmutex->attribute); u32 sq_id = sc_lwmutex.GetNewId(new SleepQueue(attr->name_u64));
lwmutex->sleep_queue = sq_id;
sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x): sleep_queue=0x%x",
attr->name, (u32)lwmutex->attribute, sq_id);
return CELL_OK; return CELL_OK;
} }
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex) int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
{ {
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
if (!lwmutex.IsGood()) return CELL_EFAULT; if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->attribute) return CELL_EINVAL; u32 sq_id = lwmutex->sleep_queue;
if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH;
{ // global lock // try to make it unable to lock
std::lock_guard<std::mutex> lock(g_lwmutex); switch (int res = lwmutex->trylock(~0))
if (!lwmutex->owner)
{ {
lwmutex->owner = ~0; // make it unable to lock case CELL_OK:
lwmutex->attribute = 0; lwmutex->attribute = 0;
lwmutex->sleep_queue = 0;
Emu.GetIdManager().RemoveID(sq_id);
default: return res;
} }
else
{
return CELL_EBUSY;
}
}
return CELL_OK;
} }
int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout) int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
{ {
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout); sc_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout);
if (!lwmutex.IsGood()) return CELL_EFAULT; if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->attribute) return CELL_EINVAL; return lwmutex->lock(GetCurrentPPUThread().GetId(), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
const u32 tid = GetCurrentPPUThread().GetId();
int res = lwmutex->trylock(tid);
if (res != CELL_EBUSY) return res;
u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do // waiting
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
Sleep(1);
res = lwmutex->trylock(tid);
if (res != CELL_EBUSY) return res;
if (!lwmutex->attribute) return CELL_EINVAL;
if (counter++ > max_counter)
{
if (!timeout)
{
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
counter = 0;
}
else
{
return CELL_ETIMEDOUT;
}
}
} while (true);
} }
int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex) int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex)
{ {
sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); sc_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
if (!lwmutex.IsGood()) return CELL_EFAULT; if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->attribute) return CELL_EINVAL;
return lwmutex->trylock(GetCurrentPPUThread().GetId()); return lwmutex->trylock(GetCurrentPPUThread().GetId());
} }
int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex) int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex)
{ {
sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); sc_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
if (!lwmutex.IsGood()) return CELL_EFAULT; if (!lwmutex.IsGood()) return CELL_EFAULT;
if (!lwmutex->unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM; return lwmutex->unlock(GetCurrentPPUThread().GetId());
return CELL_OK;
} }

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <Utilities/SMutex.h>
// attr_protocol (waiting scheduling policy) // attr_protocol (waiting scheduling policy)
enum enum
@ -9,7 +10,7 @@ enum
SYS_SYNC_PRIORITY = 2, SYS_SYNC_PRIORITY = 2,
// Basic Priority Inheritance Protocol // Basic Priority Inheritance Protocol
SYS_SYNC_PRIORITY_INHERIT = 3, SYS_SYNC_PRIORITY_INHERIT = 3,
// ???? // Not selected while unlocking
SYS_SYNC_RETRY = 4, SYS_SYNC_RETRY = 4,
// //
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF, SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
@ -30,10 +31,104 @@ struct sys_lwmutex_attribute_t
{ {
be_t<u32> attr_protocol; be_t<u32> attr_protocol;
be_t<u32> attr_recursive; be_t<u32> attr_recursive;
union
{
char name[8]; char name[8];
u64 name_u64;
};
}; };
extern std::mutex g_lwmutex; class SleepQueue
{
/* struct q_rec
{
u32 tid;
u64 prio;
q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {}
}; */
SMutex m_mutex;
Array<u32> list;
u64 m_name;
public:
SleepQueue(u64 name)
: m_name(name)
{
}
void push(u32 tid)
{
SMutexLocker lock(m_mutex);
list.AddCpy(tid);
}
u32 pop() // SYS_SYNC_FIFO
{
SMutexLocker lock(m_mutex);
while (true)
{
if (list.GetCount())
{
u32 res = list[0];
list.RemoveAt(0);
if (Emu.GetIdManager().CheckID(res))
// check thread
{
return res;
}
}
return 0;
};
}
u32 pop_prio() // SYS_SYNC_PRIORITY
{
SMutexLocker lock(m_mutex);
while (true)
{
if (list.GetCount())
{
u64 max_prio = 0;
u32 sel = 0;
for (u32 i = 0; i < list.GetCount(); i++)
{
CPUThread* t = Emu.GetCPU().GetThread(list[i]);
if (!t)
{
list[i] = 0;
sel = i;
break;
}
u64 prio = t->GetPrio();
if (prio > max_prio)
{
max_prio = prio;
sel = i;
}
}
u32 res = list[sel];
list.RemoveAt(sel);
/* if (Emu.GetIdManager().CheckID(res)) */
if (res)
// check thread
{
return res;
}
}
return 0;
}
}
u32 pop_prio_inherit() // (TODO)
{
ConLog.Error("TODO: SleepQueue::pop_prio_inherit()");
Emu.Pause();
}
};
struct sys_lwmutex_t struct sys_lwmutex_t
{ {
@ -41,8 +136,8 @@ struct sys_lwmutex_t
{ {
struct // sys_lwmutex_lock_info_t struct // sys_lwmutex_lock_info_t
{ {
/* volatile */ be_t<u32> owner; /* volatile */ SMutexBE owner;
/* volatile */ be_t<u32> waiter; /* volatile */ be_t<u32> waiter; // not used
}; };
struct struct
{ {
@ -54,77 +149,103 @@ struct sys_lwmutex_t
be_t<u32> sleep_queue; be_t<u32> sleep_queue;
be_t<u32> pad; be_t<u32> pad;
int trylock(u32 tid) int trylock(be_t<u32> tid)
{ {
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock if (!attribute.ToBE()) return CELL_EINVAL;
if ((u32)attribute & SYS_SYNC_RECURSIVE) if (tid == owner.GetOwner())
{ {
if (tid == (u32)owner) if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
{ {
recursive_count = (u32)recursive_count + 1; recursive_count += 1;
if ((u32)recursive_count == 0xffffffff) return CELL_EKRESOURCE; if (!recursive_count.ToBE()) return CELL_EKRESOURCE;
return CELL_OK; return CELL_OK;
} }
} else
else // recursive not allowed
{
if (tid == (u32)owner)
{ {
return CELL_EDEADLK; return CELL_EDEADLK;
} }
} }
if (!(u32)owner) // try lock switch (owner.trylock(tid))
{ {
owner = tid; case SMR_OK: recursive_count = 1; return CELL_OK;
recursive_count = 1; case SMR_FAILED: return CELL_EBUSY;
default: return CELL_EINVAL;
}
}
int unlock(be_t<u32> tid)
{
if (tid != owner.GetOwner())
{
return CELL_EPERM;
}
else
{
recursive_count -= 1;
if (!recursive_count.ToBE())
{
be_t<u32> target = 0;
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
{
case se32(SYS_SYNC_FIFO):
case se32(SYS_SYNC_PRIORITY):
SleepQueue* sq;
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
target = attribute.ToBE() & se32(SYS_SYNC_FIFO) ? sq->pop() : sq->pop_prio();
case se32(SYS_SYNC_RETRY): default: owner.unlock(tid, target); break;
}
}
return CELL_OK; return CELL_OK;
} }
else
{
return CELL_EBUSY;
}
} }
bool unlock(u32 tid) int lock(be_t<u32> tid, u64 timeout)
{ {
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock switch (int res = trylock(tid))
{
case CELL_EBUSY: break;
default: return res;
}
if (tid != (u32)owner) switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
{ {
return false; case se32(SYS_SYNC_PRIORITY):
case se32(SYS_SYNC_FIFO):
SleepQueue* sq;
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
sq->push(tid);
default: break;
} }
else
switch (owner.lock(tid, timeout))
{ {
recursive_count = (u32)recursive_count - 1; case SMR_OK: case SMR_SIGNAL: recursive_count = 1; return CELL_OK;
if (!(u32)recursive_count) case SMR_TIMEOUT: return CELL_ETIMEDOUT;
{ default: return CELL_EINVAL;
waiter = 0; // not used yet
owner = 0; // release
}
return true;
} }
} }
}; };
struct lwmutex_locker class lwmutex_locker
{ {
private:
mem_ptr_t<sys_lwmutex_t> m_mutex; mem_ptr_t<sys_lwmutex_t> m_mutex;
u32 m_id; be_t<u32> m_id;
public:
const int res;
lwmutex_locker(u32 lwmutex_addr, u32 tid) lwmutex_locker(mem_ptr_t<sys_lwmutex_t> lwmutex, be_t<u32> tid, u64 timeout = 0)
: m_id(tid) : m_id(tid)
, m_mutex(lwmutex_addr) , m_mutex(lwmutex)
, res(m_mutex->trylock(m_id))
{ {
if (int res = m_mutex->lock(m_id, timeout))
{
ConLog.Error("lwmutex_locker: m_mutex->lock failed(res=0x%x)", res);
Emu.Pause();
}
} }
~lwmutex_locker() ~lwmutex_locker()
{ {
if (res == CELL_OK) m_mutex->unlock(m_id); m_mutex->unlock(m_id);
} }
}; };

View file

@ -6,7 +6,7 @@ SysCallBase sc_mem("memory");
int sys_memory_container_create(u32 cid_addr, u32 yield_size) int sys_memory_container_create(u32 cid_addr, u32 yield_size)
{ {
sc_mem.Warning("(HACK!) sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size); sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
if(!Memory.IsGoodAddr(cid_addr, 4)) if(!Memory.IsGoodAddr(cid_addr, 4))
{ {
@ -15,17 +15,13 @@ int sys_memory_container_create(u32 cid_addr, u32 yield_size)
yield_size &= ~0xfffff; //round down to 1 MB granularity yield_size &= ~0xfffff; //round down to 1 MB granularity
//alignment hack (Memory.Alloc does not support alignment yet): alloc size is increased u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment
u64 addr = Memory.Alloc(yield_size + 0x100000, 0x100000); //1 MB alignment (???)
if(!addr) if(!addr)
{ {
return CELL_ENOMEM; return CELL_ENOMEM;
} }
//fix alignment:
addr = (addr + 0x100000) & ~0xfffff;
Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size))); Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)));
return CELL_OK; return CELL_OK;
} }
@ -49,20 +45,18 @@ int sys_memory_container_destroy(u32 cid)
int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
{ {
//0x30000100; //0x30000100;
sc_mem.Warning("(HACK!) sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags); sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
u32 addr; u32 addr;
switch(flags) switch(flags)
{ {
case SYS_MEMORY_PAGE_SIZE_1M: case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN; if(size & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size + 0x100000, 0x100000); addr = Memory.Alloc(size, 1);
addr = (addr + 0x100000) & ~0xfffff;
break; break;
case SYS_MEMORY_PAGE_SIZE_64K: case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN; if(size & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size + 0x10000, 0x10000); addr = Memory.Alloc(size, 1);
addr = (addr + 0x10000) & ~0xffff;
break; break;
default: return CELL_EINVAL; default: return CELL_EINVAL;

View file

@ -1,12 +1,13 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "SC_Mutex.h" #include "SC_Mutex.h"
#include "Utilities/SMutex.h"
SysCallBase sys_mtx("sys_mutex"); SysCallBase sys_mtx("sys_mutex");
int sys_mutex_create(u32 mutex_id_addr, u32 attr_addr) int sys_mutex_create(u32 mutex_id_addr, u32 attr_addr)
{ {
sys_mtx.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", sys_mtx.Warning("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)",
mutex_id_addr, attr_addr); mutex_id_addr, attr_addr);
if(!Memory.IsGoodAddr(mutex_id_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT; if(!Memory.IsGoodAddr(mutex_id_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT;
@ -48,9 +49,28 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
mutex* mtx_data = nullptr; mutex* mtx_data = nullptr;
if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH; if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH;
mtx_data->mtx.Lock(); u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
do
{
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
return CELL_OK; if (mtx_data->mtx.TryLock() == wxMUTEX_NO_ERROR) return CELL_OK;
Sleep(1);
if (counter++ > max_counter)
{
if (!timeout)
{
sys_mtx.Warning("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx): TIMEOUT", mutex_id, timeout);
counter = 0;
}
else
{
return CELL_ETIMEDOUT;
}
}
} while (true);
} }
int sys_mutex_trylock(u32 mutex_id) int sys_mutex_trylock(u32 mutex_id)
@ -60,7 +80,7 @@ int sys_mutex_trylock(u32 mutex_id)
mutex* mtx_data = nullptr; mutex* mtx_data = nullptr;
if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH; if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH;
if(mtx_data->mtx.TryLock()) return 1; if (mtx_data->mtx.TryLock() != wxMUTEX_NO_ERROR) return CELL_EBUSY;
return CELL_OK; return CELL_OK;
} }

View file

@ -131,7 +131,7 @@ int sys_ppu_thread_restart(u32 thread_id)
return CELL_OK; return CELL_OK;
} }
int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr) int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr)
{ {
sysPrxForUser.Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", sysPrxForUser.Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr).mb_str()); thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr).mb_str());

View file

@ -40,11 +40,8 @@ int sys_process_getppid()
int sys_process_exit(int errorcode) int sys_process_exit(int errorcode)
{ {
sc_p.Warning("sys_process_exit(%d)", errorcode); sc_p.Warning("sys_process_exit(%d)", errorcode);
#ifdef _DEBUG Emu.Pause(); // Emu.Stop() does crash
Emu.Pause(); ConLog.Success("Process finished");
#else
Emu.Stop();
#endif
return CELL_OK; return CELL_OK;
} }

View file

@ -10,23 +10,22 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr
if (!rw_lock_id.IsGood() || !attr.IsGood()) return CELL_EFAULT; if (!rw_lock_id.IsGood() || !attr.IsGood()) return CELL_EFAULT;
switch ((u32)attr->attr_protocol) switch (attr->attr_protocol.ToBE())
{ {
case SYS_SYNC_PRIORITY: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY attr"); break; case se32(SYS_SYNC_PRIORITY): sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
case SYS_SYNC_RETRY: sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break; case se32(SYS_SYNC_RETRY): sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break;
case SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case SYS_SYNC_FIFO: break; case se32(SYS_SYNC_FIFO): break;
default: return CELL_EINVAL; default: return CELL_EINVAL;
} }
if ((u32)attr->attr_pshared != 0x200) if (attr->attr_pshared.ToBE() != se32(0x200))
{ {
sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared); sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared);
return CELL_EINVAL; return CELL_EINVAL;
} }
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared, rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, attr->name_u64));
(u64)attr->key, (s32)attr->flags, *(u64*)&attr->name));
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d", sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d",
attr->name, (u32)attr->attr_protocol, rw_lock_id.GetValue()); attr->name, (u32)attr->attr_protocol, rw_lock_id.GetValue());
@ -52,7 +51,7 @@ int sys_rwlock_destroy(u32 rw_lock_id)
int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
{ {
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); sys_rwlock.Log("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
RWLock* rw; RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
@ -86,7 +85,7 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
int sys_rwlock_tryrlock(u32 rw_lock_id) int sys_rwlock_tryrlock(u32 rw_lock_id)
{ {
sys_rwlock.Warning("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id); sys_rwlock.Log("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw; RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
@ -98,7 +97,7 @@ int sys_rwlock_tryrlock(u32 rw_lock_id)
int sys_rwlock_runlock(u32 rw_lock_id) int sys_rwlock_runlock(u32 rw_lock_id)
{ {
sys_rwlock.Warning("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id); sys_rwlock.Log("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw; RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
@ -110,7 +109,7 @@ int sys_rwlock_runlock(u32 rw_lock_id)
int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
{ {
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
RWLock* rw; RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
@ -146,7 +145,7 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
int sys_rwlock_trywlock(u32 rw_lock_id) int sys_rwlock_trywlock(u32 rw_lock_id)
{ {
sys_rwlock.Warning("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id); sys_rwlock.Log("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw; RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
@ -161,7 +160,7 @@ int sys_rwlock_trywlock(u32 rw_lock_id)
int sys_rwlock_wunlock(u32 rw_lock_id) int sys_rwlock_wunlock(u32 rw_lock_id)
{ {
sys_rwlock.Warning("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id); sys_rwlock.Log("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
RWLock* rw; RWLock* rw;
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;

View file

@ -6,8 +6,12 @@ struct sys_rwlock_attribute_t
be_t<u32> attr_pshared; // == 0x200 (NOT SHARED) be_t<u32> attr_pshared; // == 0x200 (NOT SHARED)
be_t<u64> key; // process-shared key (not used) be_t<u64> key; // process-shared key (not used)
be_t<s32> flags; // process-shared flags (not used) be_t<s32> flags; // process-shared flags (not used)
be_t<u32> pad; be_t<u32> pad; // not used
union
{
char name[8]; char name[8];
u64 name_u64;
};
}; };
#pragma pack() #pragma pack()
@ -20,21 +24,15 @@ struct RWLock
Array<u32> rlock_list; // read lock list Array<u32> rlock_list; // read lock list
u32 m_protocol; // TODO u32 m_protocol; // TODO
u32 m_pshared; // not used
u64 m_key; // not used
s32 m_flags; // not used
union union
{ {
u64 m_name_data; // not used u64 m_name_u64;
char m_name[8]; char m_name[8];
}; };
RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name) RWLock(u32 protocol, u64 name)
: m_protocol(protocol) : m_protocol(protocol)
, m_pshared(pshared) , m_name_u64(name)
, m_key(key)
, m_flags(flags)
, m_name_data(name)
, wlock_thread(0) , wlock_thread(0)
{ {
} }

View file

@ -40,7 +40,7 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
ELFLoader l(stream); ELFLoader l(stream);
l.LoadInfo(); l.LoadInfo();
const u32 alloc_size = 256 * 1024 /*0x1000000 - stream.GetSize()*/; const u32 alloc_size = 256 * 1024 /*0x1000000 - stream.GetSize()*/;
u32 spu_offset = Memory.MainMem.Alloc(alloc_size); u32 spu_offset = Memory.MainMem.AllocAlign(alloc_size);
l.LoadData(spu_offset); l.LoadData(spu_offset);
spu_ep = l.GetEntry(); spu_ep = l.GetEntry();
return spu_offset; return spu_offset;
@ -104,7 +104,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
return CELL_ESRCH; return CELL_ESRCH;
} }
if(!thread.IsGood() || !img.IsGood() || !attr.IsGood() || !attr.IsGood()) if(!thread.IsGood() || !img.IsGood() || !attr.IsGood() || !arg.IsGood())
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
@ -133,7 +133,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU); CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
//copy SPU image: //copy SPU image:
u32 spu_offset = Memory.MainMem.Alloc(256 * 1024); u32 spu_offset = Memory.MainMem.AllocAlign(256 * 1024);
memcpy(Memory + spu_offset, Memory + (u32)img->segs_addr, 256 * 1024); memcpy(Memory + spu_offset, Memory + (u32)img->segs_addr, 256 * 1024);
//initialize from new place: //initialize from new place:
new_thread.SetOffset(spu_offset); new_thread.SetOffset(spu_offset);
@ -177,24 +177,70 @@ int sys_spu_thread_set_argument(u32 id, mem_ptr_t<sys_spu_thread_argument> arg)
return CELL_OK; return CELL_OK;
} }
//173 //165
int sys_spu_thread_group_start(u32 id) int sys_spu_thread_get_exit_status(u32 id, mem32_t status)
{ {
sc_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id); sc_spu.Warning("sys_spu_thread_get_exit_status(id=0x%x, status_addr=0x%x)", id, status.GetAddr());
if(!Emu.GetIdManager().CheckID(id)) if (!status.IsGood())
{
return CELL_EFAULT;
}
CPUThread* thr = Emu.GetCPU().GetThread(id);
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
u32 res;
if (!(*(SPUThread*)thr).SPU.Out_MBox.Pop(res) || !thr->IsStopped())
{
return CELL_ESTAT;
}
status = res;
return CELL_OK;
}
//171
int sys_spu_thread_group_destroy(u32 id)
{
sc_spu.Warning("sys_spu_thread_group_destroy(id=0x%x)", id);
SpuGroupInfo* group_info; SpuGroupInfo* group_info;
if(!Emu.GetIdManager().GetIDData(id, group_info)) if(!Emu.GetIdManager().GetIDData(id, group_info))
{ {
return CELL_ESRCH; return CELL_ESRCH;
} }
//Emu.Pause(); if (group_info->lock) // ???
for (int i = 0; i < group_info->list.GetCount(); i++) {
return CELL_EBUSY;
}
for (u32 i = 0; i < group_info->list.GetCount(); i++)
{
Emu.GetCPU().RemoveThread(group_info->list[i]);
}
Emu.GetIdManager().RemoveID(id);
return CELL_OK;
}
//173
int sys_spu_thread_group_start(u32 id)
{
sc_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id);
SpuGroupInfo* group_info;
if(!Emu.GetIdManager().GetIDData(id, group_info))
{
return CELL_ESRCH;
}
for (u32 i = 0; i < group_info->list.GetCount(); i++)
{ {
CPUThread* t; CPUThread* t;
if (t = Emu.GetCPU().GetThread(group_info->list[i])) if (t = Emu.GetCPU().GetThread(group_info->list[i]))
@ -218,10 +264,9 @@ int sys_spu_thread_group_suspend(u32 id)
} }
//Emu.Pause(); //Emu.Pause();
for (int i = 0; i < group_info->list.GetCount(); i++) for (u32 i = 0; i < group_info->list.GetCount(); i++)
{ {
CPUThread* t; if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
if (t = Emu.GetCPU().GetThread(group_info->list[i]))
{ {
t->Pause(); t->Pause();
} }
@ -273,14 +318,17 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT; cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT;
status = 0; //unspecified because of ALL_THREADS_EXIT status = 0; //unspecified because of ALL_THREADS_EXIT
for (int i = 0; i < group_info->list.GetCount(); i++) for (u32 i = 0; i < group_info->list.GetCount(); i++)
{ {
while (Emu.GetCPU().GetThread(group_info->list[i])) while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
{ {
Sleep(1); if (!t->IsRunning())
if (Emu.IsStopped()) return CELL_OK; {
break;
}
if (Emu.IsStopped()) return CELL_OK;
Sleep(1);
} }
group_info->list[i] = 0;
} }
group_info->lock = 0; // release lock group_info->lock = 0; // release lock
@ -514,7 +562,7 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32
return CELL_ESRCH; return CELL_ESRCH;
} }
for(int i=0; i<group->list.GetCount(); ++i) for(u32 i=0; i<group->list.GetCount(); ++i)
{ {
CPUThread* t; CPUThread* t;
if(t = Emu.GetCPU().GetThread(group->list[i])) if(t = Emu.GetCPU().GetThread(group->list[i]))
@ -537,3 +585,10 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32
} }
return CELL_OK; return CELL_OK;
} }
int sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num)
{
sc_spu.Error("sys_spu_thread_bind_queue(id=0x%x, spuq=0x%x, spuq_num=0x%x)", id, spuq, spuq_num);
return CELL_OK;
}

View file

@ -11,7 +11,7 @@ int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr)
int sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr) int sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr)
{ {
if(ch < 0 || ch > 15 || len <= 0) return CELL_EINVAL; if(ch < 0 || ch > 15 || (s32)len <= 0) return CELL_EINVAL;
if(!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT; if(!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT;
Emu.GetDbgCon().Write(ch, Memory.ReadString(buf_addr, len)); Emu.GetDbgCon().Write(ch, Memory.ReadString(buf_addr, len));

View file

@ -108,7 +108,7 @@ int sys_vm_return_memory(u32 addr, u32 size)
} }
// The memory size to return should not be superior to the virtual size in use minus 1MB. // The memory size to return should not be superior to the virtual size in use minus 1MB.
if((current_ct->size - size - 0x100000) < 0) if(current_ct->size < (size + 0x100000))
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }
@ -130,7 +130,7 @@ int sys_vm_lock(u32 addr, u32 size)
} }
// The memory size to return should not be superior to the virtual size to lock minus 1MB. // The memory size to return should not be superior to the virtual size to lock minus 1MB.
if((current_ct->size - size - 0x100000) < 0) if(current_ct->size < (size + 0x100000))
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }

View file

@ -305,7 +305,7 @@ void Emulator::Load()
ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr()); ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr());
ConLog.Write("max addr = 0x%x", l.GetMaxAddr()); ConLog.Write("max addr = 0x%x", l.GetMaxAddr());
thread.SetOffset(Memory.MainMem.GetStartAddr()); thread.SetOffset(Memory.MainMem.GetStartAddr());
Memory.MainMem.Alloc(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr()); Memory.MainMem.AllocFixed(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr());
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr()); thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
break; break;
@ -314,12 +314,12 @@ void Emulator::Load()
m_ppu_callback_thr = &GetCPU().AddThread(CPU_THREAD_PPU); m_ppu_callback_thr = &GetCPU().AddThread(CPU_THREAD_PPU);
thread.SetEntry(l.GetEntry()); thread.SetEntry(l.GetEntry());
Memory.StackMem.Alloc(0x1000); Memory.StackMem.AllocAlign(0x1000);
thread.InitStack(); thread.InitStack();
thread.AddArgv(m_elf_path); thread.AddArgv(m_elf_path);
//thread.AddArgv("-emu"); //thread.AddArgv("-emu");
m_rsx_callback = Memory.MainMem.Alloc(4 * 4) + 4; m_rsx_callback = Memory.MainMem.AllocAlign(4 * 4) + 4;
Memory.Write32(m_rsx_callback - 4, m_rsx_callback); Memory.Write32(m_rsx_callback - 4, m_rsx_callback);
mem32_ptr_t callback_data(m_rsx_callback); mem32_ptr_t callback_data(m_rsx_callback);
@ -327,7 +327,7 @@ void Emulator::Load()
callback_data += SC(2); callback_data += SC(2);
callback_data += BCLR(0x10 | 0x04, 0, 0, 0); callback_data += BCLR(0x10 | 0x04, 0, 0, 0);
m_ppu_thr_exit = Memory.MainMem.Alloc(4 * 4); m_ppu_thr_exit = Memory.MainMem.AllocAlign(4 * 4);
mem32_ptr_t ppu_thr_exit_data(m_ppu_thr_exit); mem32_ptr_t ppu_thr_exit_data(m_ppu_thr_exit);
ppu_thr_exit_data += ADDI(3, 0, 0); ppu_thr_exit_data += ADDI(3, 0, 0);

View file

@ -1,40 +1,28 @@
#pragma once #pragma once
struct sys_event_flag_attr enum EventQueueType
{ {
u32 protocol; SYS_PPU_QUEUE = 1,
u32 pshared; SYS_SPU_QUEUE = 2,
u64 ipc_key;
int flags;
int type;
char name[8];
};
struct event_flag
{
sys_event_flag_attr attr;
u64 pattern;
event_flag(u64 pattern, sys_event_flag_attr attr)
: pattern(pattern)
, attr(attr)
{
}
}; };
struct sys_event_queue_attr struct sys_event_queue_attr
{ {
u32 attr_protocol; be_t<u32> protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO
int type; be_t<int> type;
union
{
char name[8]; char name[8];
u64 name_u64;
};
}; };
struct sys_event_data struct sys_event_data
{ {
u64 source; be_t<u64> source;
u64 data1; be_t<u64> data1;
u64 data2; be_t<u64> data2;
u64 data3; be_t<u64> data3;
}; };
struct EventQueue; struct EventQueue;
@ -56,6 +44,19 @@ struct EventQueue
EventPort* ports[127]; EventPort* ports[127];
int size; int size;
int pos; int pos;
int type;
char name[8]; u32 m_protocol;
int m_type;
u64 m_name;
u64 m_key;
EventQueue(u32 protocol, int type, u64 name, u64 key, int size)
: m_type(type)
, m_protocol(protocol)
, m_name(name)
, m_key(key)
, size(size)
, pos(0)
{
}
}; };

View file

@ -181,9 +181,9 @@ bool ELF32Loader::LoadPhdrData(u64 _offset)
switch(machine) switch(machine)
{ {
case MACHINE_SPU: Memory.MainMem.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break; case MACHINE_SPU: Memory.MainMem.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
case MACHINE_MIPS: Memory.PSPMemory.RAM.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break; case MACHINE_MIPS: Memory.PSPMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
case MACHINE_ARM: Memory.PSVMemory.RAM.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break; case MACHINE_ARM: Memory.PSVMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
default: default:
continue; continue;

View file

@ -240,7 +240,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
case 0x00000001: //LOAD case 0x00000001: //LOAD
if(phdr_arr[i].p_memsz) if(phdr_arr[i].p_memsz)
{ {
Memory.MainMem.Alloc(offset + phdr_arr[i].p_vaddr, phdr_arr[i].p_memsz); Memory.MainMem.AllocFixed(offset + phdr_arr[i].p_vaddr, phdr_arr[i].p_memsz);
if(phdr_arr[i].p_filesz) if(phdr_arr[i].p_filesz)
{ {
@ -358,8 +358,8 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
ConLog.Write("*** text: 0x%x", stub.s_text); ConLog.Write("*** text: 0x%x", stub.s_text);
#endif #endif
static const u32 section = 4 * 3; static const u32 section = 4 * 3;
u64 tbl = Memory.MainMem.Alloc(stub.s_imports * 4 * 2); u64 tbl = Memory.MainMem.AllocAlign(stub.s_imports * 4 * 2);
u64 dst = Memory.MainMem.Alloc(stub.s_imports * section); u64 dst = Memory.MainMem.AllocAlign(stub.s_imports * section);
for(u32 i=0; i<stub.s_imports; ++i) for(u32 i=0; i<stub.s_imports; ++i)
{ {

View file

@ -197,7 +197,7 @@ public:
u32 GetEntry() { return entry; } u32 GetEntry() { return entry; }
u32 GetMinAddr() { return min_addr; } u32 GetMinAddr() { return min_addr; }
u32 GetMaxAddr() { return min_addr; } u32 GetMaxAddr() { return max_addr; }
}; };
class Loader : public LoaderBase class Loader : public LoaderBase

View file

@ -69,20 +69,20 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;$(IncludePath)</IncludePath> <IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;..\..\ffmpeg;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)bin\</OutDir> <OutDir>$(SolutionDir)bin\</OutDir>
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath> <LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
<TargetName>$(ProjectName)-$(PlatformShortName)-dbg</TargetName> <TargetName>$(ProjectName)-$(PlatformShortName)-dbg</TargetName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;$(IncludePath)</IncludePath> <IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;..\..\ffmpeg;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)bin\</OutDir> <OutDir>$(SolutionDir)bin\</OutDir>
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath> <LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
<TargetName>$(ProjectName)-$(PlatformShortName)-dbg</TargetName> <TargetName>$(ProjectName)-$(PlatformShortName)-dbg</TargetName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;$(IncludePath)</IncludePath> <IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;..\..\ffmpeg;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)bin\</OutDir> <OutDir>$(SolutionDir)bin\</OutDir>
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath> <LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
@ -91,7 +91,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;$(IncludePath)</IncludePath> <IncludePath>.\;..\wxWidgets\include;..\SDL-1.3.0-5538\include;..\SDL_image-1.2.10;..\pthreads-2.8.0;..\;..\..\ffmpeg;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)bin\</OutDir> <OutDir>$(SolutionDir)bin\</OutDir>
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath> <LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
@ -205,6 +205,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="..\Utilities\SMutex.cpp" />
<ClCompile Include="..\Utilities\Thread.cpp" /> <ClCompile Include="..\Utilities\Thread.cpp" />
<ClCompile Include="AppConnector.cpp" /> <ClCompile Include="AppConnector.cpp" />
<ClCompile Include="Emu\Audio\AudioManager.cpp" /> <ClCompile Include="Emu\Audio\AudioManager.cpp" />
@ -247,6 +248,7 @@
<ClCompile Include="Emu\SysCalls\FuncList.cpp" /> <ClCompile Include="Emu\SysCalls\FuncList.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Condition.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Condition.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Event.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Event.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Event_flag.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_FileSystem.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_FileSystem.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" /> <ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
@ -324,6 +326,7 @@
<ClInclude Include="..\Utilities\BEType.h" /> <ClInclude Include="..\Utilities\BEType.h" />
<ClInclude Include="..\Utilities\IdManager.h" /> <ClInclude Include="..\Utilities\IdManager.h" />
<ClInclude Include="..\Utilities\MTProgressDialog.h" /> <ClInclude Include="..\Utilities\MTProgressDialog.h" />
<ClInclude Include="..\Utilities\SMutex.h" />
<ClInclude Include="..\Utilities\Thread.h" /> <ClInclude Include="..\Utilities\Thread.h" />
<ClInclude Include="..\Utilities\Timer.h" /> <ClInclude Include="..\Utilities\Timer.h" />
<ClInclude Include="Emu\Audio\AudioManager.h" /> <ClInclude Include="Emu\Audio\AudioManager.h" />

View file

@ -379,6 +379,12 @@
<ClCompile Include="Emu\FS\vfsLocalDir.cpp"> <ClCompile Include="Emu\FS\vfsLocalDir.cpp">
<Filter>Emu\FS</Filter> <Filter>Emu\FS</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Utilities\SMutex.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Event_flag.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="rpcs3.rc" /> <ResourceCompile Include="rpcs3.rc" />
@ -558,5 +564,8 @@
<ClInclude Include="Emu\Audio\AudioManager.h"> <ClInclude Include="Emu\Audio\AudioManager.h">
<Filter>Include</Filter> <Filter>Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Utilities\SMutex.h">
<Filter>Utilities</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>