mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
commit
4ebd974f5e
@ -2,6 +2,10 @@
|
||||
|
||||
#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> 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); } };
|
||||
|
26
Utilities/SMutex.cpp
Normal file
26
Utilities/SMutex.cpp
Normal 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
155
Utilities/SMutex.h
Normal 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;
|
@ -1,6 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "CPUThread.h"
|
||||
|
||||
reservation_struct reservation;
|
||||
|
||||
CPUThread* GetCurrentCPUThread()
|
||||
{
|
||||
return (CPUThread*)GetCurrentNamedThread();
|
||||
@ -89,14 +91,12 @@ void CPUThread::Wait(const CPUThread& thr)
|
||||
|
||||
bool CPUThread::Sync()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_cs_sync);
|
||||
|
||||
return m_sync_wait;
|
||||
}
|
||||
|
||||
int CPUThread::ThreadStatus()
|
||||
{
|
||||
if(Emu.IsStopped())
|
||||
if(Emu.IsStopped() || IsStopped() || IsPaused())
|
||||
{
|
||||
return CPUThread_Stopped;
|
||||
}
|
||||
@ -236,7 +236,7 @@ void CPUThread::Pause()
|
||||
DoPause();
|
||||
Emu.CheckStatus();
|
||||
|
||||
ThreadBase::Stop();
|
||||
// ThreadBase::Stop(); // "Abort() called" exception
|
||||
#ifndef QT_UI
|
||||
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
|
||||
#endif
|
||||
|
@ -1,6 +1,25 @@
|
||||
#pragma once
|
||||
#include "Emu/Memory/MemoryBlock.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
|
||||
{
|
||||
|
@ -76,6 +76,8 @@ void CPUThreadManager::RemoveThread(const u32 id)
|
||||
|
||||
s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
||||
s32 num = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
for(u32 i=0; i<m_threads.GetCount(); ++i)
|
||||
{
|
||||
if(m_threads[i].GetId() == id) return &m_threads[i];
|
||||
}
|
||||
CPUThread* res;
|
||||
|
||||
return nullptr;
|
||||
if (!Emu.GetIdManager().GetIDData(id, res)) return nullptr;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void CPUThreadManager::Exec()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
||||
for(u32 i=0; i<m_threads.GetCount(); ++i)
|
||||
{
|
||||
m_threads[i].Exec();
|
||||
|
@ -16,6 +16,7 @@ PPCThread* GetCurrentPPCThread()
|
||||
|
||||
PPCThread::PPCThread(CPUThreadType type) : CPUThread(type)
|
||||
{
|
||||
memset(m_args, 0, sizeof(m_args));
|
||||
}
|
||||
|
||||
PPCThread::~PPCThread()
|
||||
@ -24,14 +25,13 @@ PPCThread::~PPCThread()
|
||||
|
||||
void PPCThread::DoReset()
|
||||
{
|
||||
memset(m_args, 0, sizeof(u64) * 4);
|
||||
}
|
||||
|
||||
void PPCThread::InitStack()
|
||||
{
|
||||
if(m_stack_addr) return;
|
||||
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;
|
||||
/*
|
||||
|
@ -1656,7 +1656,7 @@ private:
|
||||
{
|
||||
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));
|
||||
}
|
||||
@ -2362,9 +2362,12 @@ private:
|
||||
void LWARX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.reserve_addr = addr;
|
||||
CPU.reserve = true;
|
||||
CPU.GPR[rd] = Memory.Read32(addr);
|
||||
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
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)
|
||||
{
|
||||
@ -2535,9 +2538,12 @@ private:
|
||||
void LDARX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.reserve_addr = addr;
|
||||
CPU.reserve = true;
|
||||
CPU.GPR[rd] = Memory.Read64(addr);
|
||||
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
reservation.owner = lock.tid;
|
||||
reservation.addr = addr;
|
||||
reservation.size = 8;
|
||||
reservation.data64 = CPU.GPR[rd] = Memory.Read64(addr);
|
||||
}
|
||||
void DCBF(u32 ra, u32 rb)
|
||||
{
|
||||
@ -2650,25 +2656,19 @@ private:
|
||||
}
|
||||
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)
|
||||
{
|
||||
Memory.Write32(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, true);
|
||||
CPU.reserve = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const bool u = 0;
|
||||
if(u) Memory.Write32(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, u);
|
||||
CPU.reserve = false;
|
||||
}
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4)
|
||||
{
|
||||
// Memory.Write32(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile long*)(Memory + addr), (u32)CPU.GPR[rs], reservation.data32) == reservation.data32);
|
||||
reservation.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU.SetCR_EQ(0, false);
|
||||
if (lock.tid == reservation.owner) reservation.clear();
|
||||
}
|
||||
}
|
||||
void STWX(u32 rs, u32 ra, u32 rb)
|
||||
@ -2709,23 +2709,19 @@ private:
|
||||
}
|
||||
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)
|
||||
{
|
||||
Memory.Write64(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const bool u = 0;
|
||||
if(u) Memory.Write64(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, u);
|
||||
CPU.reserve = false;
|
||||
}
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8)
|
||||
{
|
||||
// Memory.Write64(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, InterlockedCompareExchange64((volatile long long*)(Memory + addr), CPU.GPR[rs], reservation.data64) == reservation.data64);
|
||||
reservation.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU.SetCR_EQ(0, false);
|
||||
if (lock.tid == reservation.owner) reservation.clear();
|
||||
}
|
||||
}
|
||||
void STBX(u32 rs, u32 ra, u32 rb)
|
||||
|
@ -44,9 +44,6 @@ void PPUThread::DoReset()
|
||||
VSCR.VSCR = 0;
|
||||
|
||||
cycle = 0;
|
||||
|
||||
reserve = false;
|
||||
reserve_addr = 0;
|
||||
}
|
||||
|
||||
void PPUThread::AddArgv(const wxString& arg)
|
||||
@ -67,14 +64,16 @@ void PPUThread::InitRegs()
|
||||
|
||||
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)
|
||||
{
|
||||
ConLog.Error("GetThreadNumById failed.");
|
||||
ConLog.Error("GetThread NumById failed.");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
const s32 tls_size = Emu.GetTLSFilesz() * thread_num;
|
||||
@ -119,7 +118,7 @@ void PPUThread::InitRegs()
|
||||
GPR[6] = m_args[3];
|
||||
}
|
||||
|
||||
u32 prx_mem = Memory.PRXMem.Alloc(0x10000);
|
||||
u32 prx_mem = Memory.PRXMem.AllocAlign(0x10000);
|
||||
Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE);
|
||||
|
||||
GPR[0] = pc;
|
||||
|
@ -602,9 +602,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
u64 reserve_addr;
|
||||
bool reserve;
|
||||
|
||||
u64 cycle;
|
||||
|
||||
public:
|
||||
|
@ -32,15 +32,8 @@ private:
|
||||
//0 - 10
|
||||
void STOP(u32 code)
|
||||
{
|
||||
if(code & 0x2000)
|
||||
{
|
||||
CPU.SetExitStatus(code & 0xfff);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Warning("STOP: 0x%x", code);
|
||||
//Emu.Pause();
|
||||
}
|
||||
ConLog.Warning("STOP: 0x%x (m_exit_status -> 0)", code);
|
||||
CPU.SetExitStatus(0);
|
||||
CPU.Stop();
|
||||
}
|
||||
void LNOP()
|
||||
@ -146,7 +139,7 @@ private:
|
||||
void ROTH(u32 rt, u32 ra, u32 rb)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ void SPUThread::InitRegs()
|
||||
|
||||
u64 SPUThread::GetFreeStackSize() const
|
||||
{
|
||||
return (GetStackAddr() + GetStackSize()) - GPR[1]._u64[3];
|
||||
return (GetStackAddr() + GetStackSize()) - GPR[1]._u32[3];
|
||||
}
|
||||
|
||||
void SPUThread::DoRun()
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include "MFC.h"
|
||||
#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] =
|
||||
{
|
||||
"$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7",
|
||||
@ -391,7 +389,7 @@ public:
|
||||
else
|
||||
{
|
||||
#ifdef _M_X64
|
||||
_InterlockedOr64((volatile __int64*)m_indval, ((u64)value << 32) | 1);
|
||||
InterlockedOr64((volatile __int64*)m_indval, ((u64)value << 32) | 1);
|
||||
#else
|
||||
ConLog.Error("PushUncond_OR(): no code compiled");
|
||||
#endif
|
||||
@ -516,34 +514,80 @@ public:
|
||||
case MFC_PUT_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_BARRIER_MASK ? "B" : "",
|
||||
op & MFC_FENCE_MASK ? "F" : "",
|
||||
lsa, ea, tag, size, cmd);
|
||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||
lsa, ea, tag, size, cmd); */
|
||||
if (op & MFC_PUT_CMD)
|
||||
{
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
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;
|
||||
|
||||
case MFC_GETLLAR_CMD:
|
||||
case MFC_PUTLLC_CMD:
|
||||
case MFC_PUTLLUC_CMD:
|
||||
case MFC_PUTQLLUC_CMD:
|
||||
{
|
||||
if (op == MFC_GETLLAR_CMD)
|
||||
{
|
||||
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",
|
||||
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",
|
||||
lsa, ea, tag, size, cmd);
|
||||
|
||||
dmac.ProcessCmd(op == MFC_GETLLAR_CMD ? MFC_GET_CMD : MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
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)
|
||||
if (op == MFC_GETLLAR_CMD) // get reservation
|
||||
{
|
||||
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;
|
||||
|
@ -10,11 +10,13 @@ DynamicMemoryBlockBase<PT>::DynamicMemoryBlockBase()
|
||||
template<typename PT>
|
||||
const u32 DynamicMemoryBlockBase<PT>::GetUsedSize() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
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;
|
||||
@ -35,38 +37,51 @@ bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr, const u32 size)
|
||||
template<typename PT>
|
||||
bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr)
|
||||
{
|
||||
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
|
||||
{
|
||||
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!IsInMyRange(addr)) return false;
|
||||
|
||||
return false;
|
||||
const u32 index = MemoryBlock::FixAddr(addr) >> 12;
|
||||
|
||||
return m_pages[index] && !m_locked[index];
|
||||
}
|
||||
|
||||
template<typename PT>
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<typename PT>
|
||||
void DynamicMemoryBlockBase<PT>::Delete()
|
||||
{
|
||||
m_used_mem.Clear();
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
m_allocated.Clear();
|
||||
m_max_size = 0;
|
||||
|
||||
m_pages.Clear();
|
||||
m_locked.Clear();
|
||||
|
||||
MemoryBlock::Delete();
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
assert(0);
|
||||
@ -78,43 +93,77 @@ bool DynamicMemoryBlockBase<PT>::Alloc(u64 addr, u32 size)
|
||||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
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;
|
||||
|
||||
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) ||
|
||||
(m_used_mem[i].addr >= addr && m_used_mem[i].addr < addr + size))
|
||||
if((addr >= m_allocated[i].addr && addr < m_allocated[i].addr + m_allocated[i].size) ||
|
||||
(m_allocated[i].addr >= addr && m_allocated[i].addr < addr + exsize))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(!is_good_addr) continue;
|
||||
|
||||
AppendUsedMem(addr, size);
|
||||
if (align)
|
||||
{
|
||||
addr = (addr + (align - 1)) & ~(align - 1);
|
||||
}
|
||||
|
||||
AppendMem(addr, size);
|
||||
|
||||
return addr;
|
||||
}
|
||||
@ -125,18 +174,38 @@ u64 DynamicMemoryBlockBase<PT>::Alloc(u32 size)
|
||||
template<typename PT>
|
||||
bool DynamicMemoryBlockBase<PT>::Alloc()
|
||||
{
|
||||
return Alloc(GetSize() - GetUsedSize()) != 0;
|
||||
return AllocAlign(GetSize() - GetUsedSize()) != 0;
|
||||
}
|
||||
|
||||
template<typename PT>
|
||||
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;
|
||||
m_used_mem.RemoveAt(i);
|
||||
/* if(IsLocked(m_allocated[num].addr)) return false; */
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -145,15 +214,15 @@ bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u64 _addr = MemoryBlock::FixAddr(m_used_mem[i].addr);
|
||||
const u32 index = addr >> 12;
|
||||
|
||||
if(addr >= _addr && addr < _addr + m_used_mem[i].size)
|
||||
if (index < m_pages.GetCount())
|
||||
{
|
||||
if (u8* res = m_pages[index])
|
||||
{
|
||||
return (u8*)m_used_mem[i].mem + addr - _addr;
|
||||
return res + (addr & 4095);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,28 +232,28 @@ u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<typename PT>
|
||||
void DynamicMemoryBlockBase<PT>::AppendLockedMem(u64 addr, u32 size)
|
||||
{
|
||||
m_locked_mem.Move(new MemBlockInfo(addr, size));
|
||||
}
|
||||
|
||||
template<typename PT>
|
||||
bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
|
||||
{
|
||||
size = PAGE_4K(size); // align size
|
||||
|
||||
addr &= ~4095; // align start address
|
||||
|
||||
if(!IsInMyRange(addr, size))
|
||||
{
|
||||
assert(0);
|
||||
@ -196,33 +265,58 @@ bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
|
||||
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;
|
||||
}
|
||||
|
||||
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(IsMyAddress(addr) || IsMyAddress(addr + size - 1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if(m_locked_mem.Get(i).size > size)
|
||||
{
|
||||
m_locked_mem.Get(i).size -= size;
|
||||
}
|
||||
else if(m_locked_mem.Get(i).size == size)
|
||||
{
|
||||
m_locked_mem.RemoveAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ public:
|
||||
|
||||
u64 Alloc(const u32 size, const u32 align)
|
||||
{
|
||||
return UserMemory->Alloc(AlignAddr(size, align));
|
||||
return UserMemory->AllocAlign(size, align);
|
||||
}
|
||||
|
||||
bool Free(const u64 addr)
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define PAGE_4K(x) (x + 4095) & ~(4095)
|
||||
|
||||
struct MemInfo
|
||||
{
|
||||
u64 addr;
|
||||
@ -21,8 +23,8 @@ struct MemBlockInfo : public MemInfo
|
||||
void* mem;
|
||||
|
||||
MemBlockInfo(u64 _addr, u32 _size)
|
||||
: MemInfo(_addr, _size)
|
||||
, mem(malloc(_size))
|
||||
: MemInfo(_addr, PAGE_4K(_size))
|
||||
, mem(_aligned_malloc(PAGE_4K(_size), 128))
|
||||
{
|
||||
if(!mem)
|
||||
{
|
||||
@ -35,7 +37,7 @@ struct MemBlockInfo : public MemInfo
|
||||
|
||||
~MemBlockInfo()
|
||||
{
|
||||
free(mem);
|
||||
_aligned_free(mem);
|
||||
mem = nullptr;
|
||||
}
|
||||
};
|
||||
@ -120,8 +122,8 @@ public:
|
||||
u8* GetMem() const { return mem; }
|
||||
virtual u8* GetMem(u64 addr) const { return mem + addr; }
|
||||
|
||||
virtual bool Alloc(u64 addr, u32 size) { return false; }
|
||||
virtual u64 Alloc(u32 size) { return 0; }
|
||||
virtual bool AllocFixed(u64 addr, u32 size) { return false; }
|
||||
virtual u64 AllocAlign(u32 size, u32 align = 1) { return 0; }
|
||||
virtual bool Alloc() { return false; }
|
||||
virtual bool Free(u64 addr) { return false; }
|
||||
virtual bool Lock(u64 addr, u32 size) { return false; }
|
||||
@ -190,8 +192,11 @@ class NullMemoryBlock : public MemoryBlock
|
||||
template<typename PT>
|
||||
class DynamicMemoryBlockBase : public PT
|
||||
{
|
||||
Array<MemBlockInfo> m_used_mem;
|
||||
Array<MemBlockInfo> m_locked_mem;
|
||||
mutable std::mutex m_lock;
|
||||
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;
|
||||
|
||||
public:
|
||||
@ -209,8 +214,8 @@ public:
|
||||
|
||||
virtual void Delete();
|
||||
|
||||
virtual bool Alloc(u64 addr, u32 size);
|
||||
virtual u64 Alloc(u32 size);
|
||||
virtual bool AllocFixed(u64 addr, u32 size);
|
||||
virtual u64 AllocAlign(u32 size, u32 align = 1);
|
||||
virtual bool Alloc();
|
||||
virtual bool Free(u64 addr);
|
||||
virtual bool Lock(u64 addr, u32 size);
|
||||
@ -219,8 +224,7 @@ public:
|
||||
virtual u8* GetMem(u64 addr) const;
|
||||
|
||||
private:
|
||||
void AppendUsedMem(u64 addr, u32 size);
|
||||
void AppendLockedMem(u64 addr, u32 size);
|
||||
void AppendMem(u64 addr, u32 size);
|
||||
};
|
||||
|
||||
class VirtualMemoryBlock : public MemoryBlock
|
||||
|
@ -83,7 +83,7 @@ struct CellAudioPortConfig
|
||||
struct CellAudioConfig //custom structure
|
||||
{
|
||||
bool m_is_audio_initialized;
|
||||
bool m_is_audio_port_open;
|
||||
bool m_is_audio_port_opened;
|
||||
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());
|
||||
|
||||
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->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(m_config->m_is_audio_port_open == false)
|
||||
if(!m_config->m_is_audio_port_opened)
|
||||
{
|
||||
portConfig->status = CELL_AUDIO_STATUS_CLOSE;
|
||||
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;
|
||||
}
|
||||
@ -268,7 +268,7 @@ int cellAudioPortStart(u32 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;
|
||||
|
||||
m_config->m_is_audio_port_started = true;
|
||||
@ -279,10 +279,10 @@ int cellAudioPortClose(u32 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;
|
||||
|
||||
m_config->m_is_audio_port_open = false;
|
||||
m_config->m_is_audio_port_opened = false;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -1016,6 +1016,6 @@ void cellAudio_init()
|
||||
void cellAudio_unload()
|
||||
{
|
||||
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;
|
||||
}
|
@ -63,7 +63,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||
{
|
||||
local_size = 0xf900000; //TODO
|
||||
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);
|
||||
@ -78,7 +78,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||
current_config.coreFrequency = re32(500000000);
|
||||
|
||||
InitOffsetTable();
|
||||
Memory.RSXCMDMem.Alloc(cmdSize);
|
||||
Memory.RSXCMDMem.AllocAlign(cmdSize);
|
||||
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
|
||||
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.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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
|
||||
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); // could stall on exit
|
||||
|
||||
u32 current = re(ctxt->current);
|
||||
u32 end = re(ctxt->end);
|
||||
@ -682,7 +682,7 @@ int32_t cellGcmMapLocalMemory(u64 address, u64 size)
|
||||
{
|
||||
local_size = 0xf900000; //TODO
|
||||
local_addr = Memory.RSXFBMem.GetStartAddr();
|
||||
Memory.RSXFBMem.Alloc(local_size);
|
||||
Memory.RSXFBMem.AllocAlign(local_size);
|
||||
Memory.Write32(address, local_addr);
|
||||
Memory.Write32(size, local_size);
|
||||
}
|
||||
@ -749,7 +749,7 @@ int32_t cellGcmUnmapEaIoAddress(u64 ea)
|
||||
ea = ea >> 20;
|
||||
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.ea + ((io+i)*sizeof(u16)), 0xFFFF);
|
||||
@ -772,7 +772,7 @@ int32_t cellGcmUnmapIoAddress(u64 io)
|
||||
io = io >> 20;
|
||||
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.ea + ((io+i)*sizeof(u16)), 0xFFFF);
|
||||
|
@ -480,7 +480,7 @@ int cellPamfReaderGetStreamInfo(mem_ptr_t<CellPamfReader> pSelf, u32 pInfo_addr,
|
||||
pInfo->numberOfChannels = pAudio->channels;
|
||||
pInfo->samplingFrequency = CELL_PAMF_FS_48kHz;
|
||||
|
||||
if (pAudio->bps = 0x40)
|
||||
if (pAudio->bps == 0x40)
|
||||
pInfo->bitsPerSample = CELL_PAMF_BIT_LENGTH_16;
|
||||
else
|
||||
//TODO: CELL_PAMF_BIT_LENGTH_24
|
||||
|
@ -4,9 +4,7 @@
|
||||
#include <mutex>
|
||||
|
||||
void cellSync_init();
|
||||
void cellSync_unload();
|
||||
Module cellSync("cellSync", cellSync_init, nullptr, cellSync_unload);
|
||||
std::mutex g_SyncMutex;
|
||||
Module cellSync("cellSync", cellSync_init);
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -56,8 +54,13 @@ int cellSyncMutexInitialize(mem_ptr_t<CellSyncMutex> mutex)
|
||||
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;
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -77,8 +80,13 @@ int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
|
||||
}
|
||||
|
||||
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;
|
||||
mutex->m_order = mutex->m_order + 1;
|
||||
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);
|
||||
}
|
||||
}
|
||||
//while (_InterlockedExchange((volatile long*)&mutex->m_data, 1)) Sleep(1);
|
||||
_mm_mfence();
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -115,8 +122,13 @@ int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return CELL_SYNC_ERROR_BUSY;
|
||||
@ -140,7 +152,12 @@ int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> 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;
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -152,9 +169,4 @@ void cellSync_init()
|
||||
cellSync.AddFunc(0x1bb675c2, cellSyncMutexLock);
|
||||
cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock);
|
||||
cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock);
|
||||
}
|
||||
|
||||
void cellSync_unload()
|
||||
{
|
||||
g_SyncMutex.unlock();
|
||||
}
|
@ -460,6 +460,11 @@ int cellSysutilCheckCallback()
|
||||
cellSysutil.Log("cellSysutilCheckCallback()");
|
||||
Emu.GetCallbackManager().m_exit_callback.Check();
|
||||
|
||||
CPUThread& thr = Emu.GetCallbackThread();
|
||||
|
||||
while(Emu.IsRunning() && thr.IsAlive())
|
||||
Sleep(1);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,7 @@ void sysPrxForUser_init()
|
||||
//sysPrxForUser.AddFunc(0xaede4b03, sys_heap_free);
|
||||
//sysPrxForUser.AddFunc(0x8a561d92, sys_heap_delete_heap);
|
||||
sysPrxForUser.AddFunc(0xb2fcf2c8, sys_heap_create_heap);
|
||||
sysPrxForUser.AddFunc(0x44265c08, _sys_heap_memalign);
|
||||
|
||||
sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory);
|
||||
sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory);
|
||||
|
@ -176,8 +176,8 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
||||
}
|
||||
|
||||
//start callback thread
|
||||
//if(func)
|
||||
//func.async(aio, error, xid, res);
|
||||
if(func)
|
||||
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])",
|
||||
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));
|
||||
t.detach();
|
||||
//fsAioRead(fd, aio, xid, func);
|
||||
|
||||
aio_id = xid;
|
||||
|
||||
|
@ -87,20 +87,20 @@ static func_caller* sc_table[1024] =
|
||||
bind_func(sys_rwlock_wunlock), //127 (0x07F)
|
||||
bind_func(sys_event_queue_create), //128 (0x080)
|
||||
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_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
|
||||
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
|
||||
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_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), //172
|
||||
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_group_destroy), bind_func(sys_spu_thread_initialize), //172
|
||||
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, 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
|
||||
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, //204
|
||||
null_func, null_func, null_func, null_func, null_func, //209
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "lv2/SC_SPU_Thread.h"
|
||||
#include "lv2/SC_Lwmutex.h"
|
||||
#include "lv2/SC_Lwcond.h"
|
||||
#include "lv2/SC_Event_flag.h"
|
||||
#include "Emu/event.h"
|
||||
//#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 );
|
||||
|
||||
//sys_event
|
||||
extern int sys_event_flag_create(u32 eflag_id_addr, u32 attr_addr, u64 init);
|
||||
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_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size);
|
||||
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_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_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
|
||||
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_stop(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 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
|
||||
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
|
||||
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_memalign(u32 heap_id, u32 align, u32 size, u64 p4);
|
||||
|
||||
//sys_spu
|
||||
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_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_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_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_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_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);
|
||||
@ -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_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_bind_queue(u32 id, u32 spuq, u32 spuq_num);
|
||||
extern int sys_spu_thread_get_exit_status(u32 id, mem32_t status);
|
||||
|
||||
//sys_time
|
||||
extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime);
|
||||
|
@ -27,7 +27,7 @@ struct condition
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
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)
|
||||
|
@ -5,128 +5,25 @@
|
||||
|
||||
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
|
||||
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)",
|
||||
equeue_id_addr, attr_addr, event_queue_key, size);
|
||||
equeue_id.GetAddr(), attr.GetAddr(), event_queue_key, size);
|
||||
|
||||
if(size <= 0 || size > 127)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
auto& attr = (sys_event_queue_attr&)Memory[attr_addr];
|
||||
sys_event.Warning("name = %s", attr.name);
|
||||
sys_event.Warning("type = %d", re(attr.type));
|
||||
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));
|
||||
equeue_id = sys_event.GetNewId(new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size));
|
||||
sys_event.Warning("*** event_queue created[%s] (protocol=0x%x, type=0x%x): id = %d",
|
||||
attr->name, (u32)attr->protocol, (int)attr->type, equeue_id.GetValue());
|
||||
|
||||
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];
|
||||
|
||||
re(dst.source, equeue->ports[i]->name);
|
||||
re(dst.data1, equeue->ports[i]->data1);
|
||||
re(dst.data2, equeue->ports[i]->data2);
|
||||
re(dst.data3, equeue->ports[i]->data3);
|
||||
dst.source = equeue->ports[i]->name;
|
||||
dst.data1 = equeue->ports[i]->data1;
|
||||
dst.data2 = equeue->ports[i]->data2;
|
||||
dst.data3 = equeue->ports[i]->data3;
|
||||
|
||||
equeue->ports[i]->has_data = false;
|
||||
|
||||
@ -264,5 +161,12 @@ int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3)
|
||||
eport->data2 = data2;
|
||||
eport->data3 = data3;
|
||||
|
||||
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;
|
||||
}
|
115
rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp
Normal file
115
rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp
Normal 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;
|
||||
}
|
31
rpcs3/Emu/SysCalls/lv2/SC_Event_flag.h
Normal file
31
rpcs3/Emu/SysCalls/lv2/SC_Event_flag.h
Normal 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)
|
||||
{
|
||||
}
|
||||
};
|
@ -7,7 +7,7 @@ extern gcmInfo gcm_info;
|
||||
|
||||
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];
|
||||
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
|
||||
|
@ -18,9 +18,12 @@ struct HeapInfo
|
||||
};
|
||||
|
||||
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);
|
||||
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)
|
||||
@ -30,5 +33,15 @@ int sys_heap_malloc(const u32 heap_id, const u32 size)
|
||||
HeapInfo* heap;
|
||||
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);
|
||||
}
|
@ -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)
|
||||
{
|
||||
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());
|
||||
|
||||
if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||
|
||||
u32 protocol = (u32)lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK;
|
||||
switch (protocol)
|
||||
{
|
||||
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 = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(attr->name_u64));
|
||||
|
||||
lwcond->lwmutex_addr = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(protocol, *(u64*)&attr->name));
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x): id=%d", attr->name, protocol, (u32)lwcond->lwcond_queue);
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id=0x%x",
|
||||
attr->name, (u32)lwmutex->attribute, (u32)lwmutex->sleep_queue, (u32)lwcond->lwcond_queue);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
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);
|
||||
|
||||
u32 counter = 0;
|
||||
|
@ -2,12 +2,16 @@
|
||||
|
||||
struct sys_lwcond_attribute_t
|
||||
{
|
||||
char name[8];
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct sys_lwcond_t
|
||||
{
|
||||
be_t<u32> lwmutex_addr;
|
||||
be_t<u32> lwmutex;
|
||||
be_t<u32> lwcond_queue;
|
||||
};
|
||||
|
||||
@ -18,22 +22,20 @@ struct LWCond
|
||||
std::mutex m_lock;
|
||||
Array<u32> waiters; // list of waiting threads
|
||||
Array<u32> signaled; // list of signaled threads
|
||||
u32 m_protocol; // protocol
|
||||
u64 m_name; // not used
|
||||
|
||||
LWCond(u32 prot, u64 name)
|
||||
LWCond(u64 name)
|
||||
: m_name(name)
|
||||
, m_protocol(prot)
|
||||
{
|
||||
}
|
||||
|
||||
void signal()
|
||||
void signal(u32 _protocol)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (waiters.GetCount())
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
if ((_protocol & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
u64 max_prio = 0;
|
||||
u32 sel = 0;
|
||||
|
@ -5,125 +5,87 @@
|
||||
|
||||
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)
|
||||
{
|
||||
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());
|
||||
|
||||
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||
|
||||
switch ((u32)attr->attr_recursive)
|
||||
switch (attr->attr_recursive.ToBE())
|
||||
{
|
||||
case SYS_SYNC_RECURSIVE: break;
|
||||
case SYS_SYNC_NOT_RECURSIVE: break;
|
||||
default: return CELL_EINVAL;
|
||||
case se32(SYS_SYNC_RECURSIVE): break;
|
||||
case se32(SYS_SYNC_NOT_RECURSIVE): break;
|
||||
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 SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break;
|
||||
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case SYS_SYNC_FIFO: sc_lwmutex.Warning("TODO: SYS_SYNC_FIFO attr"); break;
|
||||
default: return CELL_EINVAL;
|
||||
case se32(SYS_SYNC_PRIORITY): break;
|
||||
case se32(SYS_SYNC_RETRY): break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sc_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL;
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
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->pad = 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;
|
||||
}
|
||||
|
||||
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->attribute) return CELL_EINVAL;
|
||||
u32 sq_id = lwmutex->sleep_queue;
|
||||
if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH;
|
||||
|
||||
{ // global lock
|
||||
std::lock_guard<std::mutex> lock(g_lwmutex);
|
||||
|
||||
if (!lwmutex->owner)
|
||||
{
|
||||
lwmutex->owner = ~0; // make it unable to lock
|
||||
lwmutex->attribute = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
// try to make it unable to lock
|
||||
switch (int res = lwmutex->trylock(~0))
|
||||
{
|
||||
case CELL_OK:
|
||||
lwmutex->attribute = 0;
|
||||
lwmutex->sleep_queue = 0;
|
||||
Emu.GetIdManager().RemoveID(sq_id);
|
||||
default: return res;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
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->attribute) return CELL_EINVAL;
|
||||
|
||||
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);
|
||||
return lwmutex->lock(GetCurrentPPUThread().GetId(), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
|
||||
}
|
||||
|
||||
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->attribute) return CELL_EINVAL;
|
||||
|
||||
return lwmutex->trylock(GetCurrentPPUThread().GetId());
|
||||
}
|
||||
|
||||
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->unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
|
||||
|
||||
return CELL_OK;
|
||||
return lwmutex->unlock(GetCurrentPPUThread().GetId());
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <Utilities/SMutex.h>
|
||||
|
||||
// attr_protocol (waiting scheduling policy)
|
||||
enum
|
||||
@ -9,7 +10,7 @@ enum
|
||||
SYS_SYNC_PRIORITY = 2,
|
||||
// Basic Priority Inheritance Protocol
|
||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
||||
// ????
|
||||
// Not selected while unlocking
|
||||
SYS_SYNC_RETRY = 4,
|
||||
//
|
||||
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
|
||||
@ -30,10 +31,104 @@ struct sys_lwmutex_attribute_t
|
||||
{
|
||||
be_t<u32> attr_protocol;
|
||||
be_t<u32> attr_recursive;
|
||||
char name[8];
|
||||
union
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -41,8 +136,8 @@ struct sys_lwmutex_t
|
||||
{
|
||||
struct // sys_lwmutex_lock_info_t
|
||||
{
|
||||
/* volatile */ be_t<u32> owner;
|
||||
/* volatile */ be_t<u32> waiter;
|
||||
/* volatile */ SMutexBE owner;
|
||||
/* volatile */ be_t<u32> waiter; // not used
|
||||
};
|
||||
struct
|
||||
{
|
||||
@ -54,77 +149,103 @@ struct sys_lwmutex_t
|
||||
be_t<u32> sleep_queue;
|
||||
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;
|
||||
if ((u32)recursive_count == 0xffffffff) return CELL_EKRESOURCE;
|
||||
recursive_count += 1;
|
||||
if (!recursive_count.ToBE()) return CELL_EKRESOURCE;
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
else // recursive not allowed
|
||||
{
|
||||
if (tid == (u32)owner)
|
||||
else
|
||||
{
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(u32)owner) // try lock
|
||||
switch (owner.trylock(tid))
|
||||
{
|
||||
owner = tid;
|
||||
recursive_count = 1;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
||||
case SMR_FAILED: return CELL_EBUSY;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
bool unlock(u32 tid)
|
||||
int unlock(be_t<u32> tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock
|
||||
|
||||
if (tid != (u32)owner)
|
||||
if (tid != owner.GetOwner())
|
||||
{
|
||||
return false;
|
||||
return CELL_EPERM;
|
||||
}
|
||||
else
|
||||
{
|
||||
recursive_count = (u32)recursive_count - 1;
|
||||
if (!(u32)recursive_count)
|
||||
recursive_count -= 1;
|
||||
if (!recursive_count.ToBE())
|
||||
{
|
||||
waiter = 0; // not used yet
|
||||
owner = 0; // release
|
||||
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 true;
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int lock(be_t<u32> tid, u64 timeout)
|
||||
{
|
||||
switch (int res = trylock(tid))
|
||||
{
|
||||
case CELL_EBUSY: break;
|
||||
default: return res;
|
||||
}
|
||||
|
||||
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
switch (owner.lock(tid, timeout))
|
||||
{
|
||||
case SMR_OK: case SMR_SIGNAL: recursive_count = 1; return CELL_OK;
|
||||
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct lwmutex_locker
|
||||
class lwmutex_locker
|
||||
{
|
||||
private:
|
||||
mem_ptr_t<sys_lwmutex_t> m_mutex;
|
||||
u32 m_id;
|
||||
public:
|
||||
const int res;
|
||||
be_t<u32> m_id;
|
||||
|
||||
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_mutex(lwmutex_addr)
|
||||
, res(m_mutex->trylock(m_id))
|
||||
, m_mutex(lwmutex)
|
||||
{
|
||||
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()
|
||||
{
|
||||
if (res == CELL_OK) m_mutex->unlock(m_id);
|
||||
m_mutex->unlock(m_id);
|
||||
}
|
||||
};
|
@ -6,7 +6,7 @@ SysCallBase sc_mem("memory");
|
||||
|
||||
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))
|
||||
{
|
||||
@ -15,17 +15,13 @@ int sys_memory_container_create(u32 cid_addr, u32 yield_size)
|
||||
|
||||
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, 0x100000); //1 MB alignment (???)
|
||||
u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment
|
||||
|
||||
if(!addr)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
//fix alignment:
|
||||
addr = (addr + 0x100000) & ~0xfffff;
|
||||
|
||||
Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)));
|
||||
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)
|
||||
{
|
||||
//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;
|
||||
switch(flags)
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size + 0x100000, 0x100000);
|
||||
addr = (addr + 0x100000) & ~0xfffff;
|
||||
addr = Memory.Alloc(size, 1);
|
||||
break;
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size + 0x10000, 0x10000);
|
||||
addr = (addr + 0x10000) & ~0xffff;
|
||||
addr = Memory.Alloc(size, 1);
|
||||
break;
|
||||
|
||||
default: return CELL_EINVAL;
|
||||
|
@ -1,12 +1,13 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "SC_Mutex.h"
|
||||
#include "Utilities/SMutex.h"
|
||||
|
||||
SysCallBase sys_mtx("sys_mutex");
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
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)
|
||||
@ -60,7 +80,7 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||
mutex* mtx_data = nullptr;
|
||||
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;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ int sys_ppu_thread_restart(u32 thread_id)
|
||||
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'))",
|
||||
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr).mb_str());
|
||||
|
@ -40,11 +40,8 @@ int sys_process_getppid()
|
||||
int sys_process_exit(int errorcode)
|
||||
{
|
||||
sc_p.Warning("sys_process_exit(%d)", errorcode);
|
||||
#ifdef _DEBUG
|
||||
Emu.Pause();
|
||||
#else
|
||||
Emu.Stop();
|
||||
#endif
|
||||
Emu.Pause(); // Emu.Stop() does crash
|
||||
ConLog.Success("Process finished");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
switch ((u32)attr->attr_protocol)
|
||||
switch (attr->attr_protocol.ToBE())
|
||||
{
|
||||
case 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 SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case SYS_SYNC_FIFO: break;
|
||||
case se32(SYS_SYNC_PRIORITY): sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||
case se32(SYS_SYNC_RETRY): sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
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);
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared,
|
||||
(u64)attr->key, (s32)attr->flags, *(u64*)&attr->name));
|
||||
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, attr->name_u64));
|
||||
|
||||
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d",
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
|
@ -6,8 +6,12 @@ struct sys_rwlock_attribute_t
|
||||
be_t<u32> attr_pshared; // == 0x200 (NOT SHARED)
|
||||
be_t<u64> key; // process-shared key (not used)
|
||||
be_t<s32> flags; // process-shared flags (not used)
|
||||
be_t<u32> pad;
|
||||
char name[8];
|
||||
be_t<u32> pad; // not used
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
@ -20,21 +24,15 @@ struct RWLock
|
||||
Array<u32> rlock_list; // read lock list
|
||||
u32 m_protocol; // TODO
|
||||
|
||||
u32 m_pshared; // not used
|
||||
u64 m_key; // not used
|
||||
s32 m_flags; // not used
|
||||
union
|
||||
{
|
||||
u64 m_name_data; // not used
|
||||
u64 m_name_u64;
|
||||
char m_name[8];
|
||||
};
|
||||
|
||||
RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name)
|
||||
RWLock(u32 protocol, u64 name)
|
||||
: m_protocol(protocol)
|
||||
, m_pshared(pshared)
|
||||
, m_key(key)
|
||||
, m_flags(flags)
|
||||
, m_name_data(name)
|
||||
, m_name_u64(name)
|
||||
, wlock_thread(0)
|
||||
{
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
|
||||
ELFLoader l(stream);
|
||||
l.LoadInfo();
|
||||
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);
|
||||
spu_ep = l.GetEntry();
|
||||
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;
|
||||
}
|
||||
|
||||
if(!thread.IsGood() || !img.IsGood() || !attr.IsGood() || !attr.IsGood())
|
||||
if(!thread.IsGood() || !img.IsGood() || !attr.IsGood() || !arg.IsGood())
|
||||
{
|
||||
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);
|
||||
//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);
|
||||
//initialize from new place:
|
||||
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;
|
||||
}
|
||||
|
||||
//173
|
||||
int sys_spu_thread_group_start(u32 id)
|
||||
//165
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
//Emu.Pause();
|
||||
for (int i = 0; i < group_info->list.GetCount(); i++)
|
||||
if (group_info->lock) // ???
|
||||
{
|
||||
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;
|
||||
if (t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
@ -218,10 +264,9 @@ int sys_spu_thread_group_suspend(u32 id)
|
||||
}
|
||||
|
||||
//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 (t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
{
|
||||
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;
|
||||
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())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (Emu.IsStopped()) return CELL_OK;
|
||||
Sleep(1);
|
||||
}
|
||||
group_info->list[i] = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for(int i=0; i<group->list.GetCount(); ++i)
|
||||
for(u32 i=0; i<group->list.GetCount(); ++i)
|
||||
{
|
||||
CPUThread* t;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
|
||||
Emu.GetDbgCon().Write(ch, Memory.ReadString(buf_addr, len));
|
||||
|
@ -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.
|
||||
if((current_ct->size - size - 0x100000) < 0)
|
||||
if(current_ct->size < (size + 0x100000))
|
||||
{
|
||||
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.
|
||||
if((current_ct->size - size - 0x100000) < 0)
|
||||
if(current_ct->size < (size + 0x100000))
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ void Emulator::Load()
|
||||
ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr());
|
||||
ConLog.Write("max addr = 0x%x", l.GetMaxAddr());
|
||||
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());
|
||||
break;
|
||||
|
||||
@ -314,12 +314,12 @@ void Emulator::Load()
|
||||
m_ppu_callback_thr = &GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
|
||||
thread.SetEntry(l.GetEntry());
|
||||
Memory.StackMem.Alloc(0x1000);
|
||||
Memory.StackMem.AllocAlign(0x1000);
|
||||
thread.InitStack();
|
||||
thread.AddArgv(m_elf_path);
|
||||
//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);
|
||||
|
||||
mem32_ptr_t callback_data(m_rsx_callback);
|
||||
@ -327,7 +327,7 @@ void Emulator::Load()
|
||||
callback_data += SC(2);
|
||||
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);
|
||||
ppu_thr_exit_data += ADDI(3, 0, 0);
|
||||
|
@ -1,61 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
struct sys_event_flag_attr
|
||||
{
|
||||
u32 protocol;
|
||||
u32 pshared;
|
||||
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
|
||||
{
|
||||
u32 attr_protocol;
|
||||
int type;
|
||||
char name[8];
|
||||
};
|
||||
|
||||
struct sys_event_data
|
||||
{
|
||||
u64 source;
|
||||
u64 data1;
|
||||
u64 data2;
|
||||
u64 data3;
|
||||
};
|
||||
|
||||
struct EventQueue;
|
||||
|
||||
struct EventPort
|
||||
{
|
||||
u64 name;
|
||||
u64 data1;
|
||||
u64 data2;
|
||||
u64 data3;
|
||||
bool has_data;
|
||||
CPUThread* thread;
|
||||
EventQueue* queue[127];
|
||||
int pos;
|
||||
};
|
||||
|
||||
struct EventQueue
|
||||
{
|
||||
EventPort* ports[127];
|
||||
int size;
|
||||
int pos;
|
||||
int type;
|
||||
char name[8];
|
||||
#pragma once
|
||||
|
||||
enum EventQueueType
|
||||
{
|
||||
SYS_PPU_QUEUE = 1,
|
||||
SYS_SPU_QUEUE = 2,
|
||||
};
|
||||
|
||||
struct sys_event_queue_attr
|
||||
{
|
||||
be_t<u32> protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO
|
||||
be_t<int> type;
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct sys_event_data
|
||||
{
|
||||
be_t<u64> source;
|
||||
be_t<u64> data1;
|
||||
be_t<u64> data2;
|
||||
be_t<u64> data3;
|
||||
};
|
||||
|
||||
struct EventQueue;
|
||||
|
||||
struct EventPort
|
||||
{
|
||||
u64 name;
|
||||
u64 data1;
|
||||
u64 data2;
|
||||
u64 data3;
|
||||
bool has_data;
|
||||
CPUThread* thread;
|
||||
EventQueue* queue[127];
|
||||
int pos;
|
||||
};
|
||||
|
||||
struct EventQueue
|
||||
{
|
||||
EventPort* ports[127];
|
||||
int size;
|
||||
int pos;
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
};
|
@ -181,9 +181,9 @@ bool ELF32Loader::LoadPhdrData(u64 _offset)
|
||||
|
||||
switch(machine)
|
||||
{
|
||||
case MACHINE_SPU: Memory.MainMem.Alloc(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_ARM: Memory.PSVMemory.RAM.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.AllocFixed(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:
|
||||
continue;
|
||||
|
@ -240,7 +240,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
case 0x00000001: //LOAD
|
||||
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)
|
||||
{
|
||||
@ -358,8 +358,8 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
ConLog.Write("*** text: 0x%x", stub.s_text);
|
||||
#endif
|
||||
static const u32 section = 4 * 3;
|
||||
u64 tbl = Memory.MainMem.Alloc(stub.s_imports * 4 * 2);
|
||||
u64 dst = Memory.MainMem.Alloc(stub.s_imports * section);
|
||||
u64 tbl = Memory.MainMem.AllocAlign(stub.s_imports * 4 * 2);
|
||||
u64 dst = Memory.MainMem.AllocAlign(stub.s_imports * section);
|
||||
|
||||
for(u32 i=0; i<stub.s_imports; ++i)
|
||||
{
|
||||
|
@ -197,7 +197,7 @@ public:
|
||||
|
||||
u32 GetEntry() { return entry; }
|
||||
u32 GetMinAddr() { return min_addr; }
|
||||
u32 GetMaxAddr() { return min_addr; }
|
||||
u32 GetMaxAddr() { return max_addr; }
|
||||
};
|
||||
|
||||
class Loader : public LoaderBase
|
||||
|
@ -69,20 +69,20 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<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>
|
||||
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
|
||||
<TargetName>$(ProjectName)-$(PlatformShortName)-dbg</TargetName>
|
||||
</PropertyGroup>
|
||||
<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>
|
||||
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
|
||||
<TargetName>$(ProjectName)-$(PlatformShortName)-dbg</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<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>
|
||||
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@ -91,7 +91,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<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>
|
||||
<LibraryPath>..\libs\$(Configuration)\;$(LibraryPath)</LibraryPath>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@ -205,6 +205,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Utilities\SMutex.cpp" />
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="AppConnector.cpp" />
|
||||
<ClCompile Include="Emu\Audio\AudioManager.cpp" />
|
||||
@ -247,6 +248,7 @@
|
||||
<ClCompile Include="Emu\SysCalls\FuncList.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Condition.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_GCM.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
|
||||
@ -324,6 +326,7 @@
|
||||
<ClInclude Include="..\Utilities\BEType.h" />
|
||||
<ClInclude Include="..\Utilities\IdManager.h" />
|
||||
<ClInclude Include="..\Utilities\MTProgressDialog.h" />
|
||||
<ClInclude Include="..\Utilities\SMutex.h" />
|
||||
<ClInclude Include="..\Utilities\Thread.h" />
|
||||
<ClInclude Include="..\Utilities\Timer.h" />
|
||||
<ClInclude Include="Emu\Audio\AudioManager.h" />
|
||||
|
@ -379,6 +379,12 @@
|
||||
<ClCompile Include="Emu\FS\vfsLocalDir.cpp">
|
||||
<Filter>Emu\FS</Filter>
|
||||
</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>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
@ -558,5 +564,8 @@
|
||||
<ClInclude Include="Emu\Audio\AudioManager.h">
|
||||
<Filter>Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Utilities\SMutex.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user