1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-24 11:43:05 +01:00

cellSpurs draft added

This commit is contained in:
Nekotekina 2014-03-08 01:31:08 +04:00
parent 3a00ec7682
commit 1c302433af
14 changed files with 696 additions and 70 deletions

View File

@ -53,6 +53,8 @@ u32 adecOpen(AudioDecoder* data)
adec.id = adec_id;
adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback");
thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]()
{
ConLog.Write("Audio Decoder enter()");

View File

@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFi
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
{
if (esFilterId->filterIdMajor >= 0xe0)
attr->memSize = 0x2000000; // 0x45fa49 from ps3
attr->memSize = 0x1000000; // 0x45fa49 from ps3
else
attr->memSize = 0x100000; // 0x73d9 from ps3
attr->memSize = 0x200000; // 0x73d9 from ps3
cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor,
(u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2);
@ -36,6 +36,8 @@ u32 dmuxOpen(Demuxer* data)
dmux.id = dmux_id;
dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback");
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]()
{
ConLog.Write("Demuxer enter (mem=0x%x, size=0x%x, cb=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc, dmux.cbArg);
@ -80,8 +82,8 @@ u32 dmuxOpen(Demuxer* data)
cb.SetAddr(dmux.cbFunc);
cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/
//dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
//updates_signaled++;
dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
updates_signaled++;
}
else switch (code.ToLE())
{
@ -146,6 +148,12 @@ u32 dmuxOpen(Demuxer* data)
Sleep(1);
}
/*if (es.hasunseen()) // hack, probably useless
{
stream = backup;
continue;
}*/
//ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
es.push(stream, len - pes.size - 3, pes);
@ -365,11 +373,11 @@ u32 dmuxOpen(Demuxer* data)
}
break;
case dmuxReleaseAu:
/*case dmuxReleaseAu:
{
task.es.es_ptr->release();
}
break;
break;*/
case dmuxFlushEs:
{
@ -584,18 +592,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
return CELL_DMUX_ERROR_FATAL;
}
if (dmux->is_running) // maximum hack
{
mem_ptr_t<CellDmuxMsg> dmuxMsg(a128(dmux->memAddr) + 128);
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = 0; // !!!
Callback cb;
cb.SetAddr(dmux->cbFunc);
cb.Handle(dmux->id, dmuxMsg.GetAddr(), dmux->cbArg);
cb.Branch(true);
}
while (dmux->is_running) // hack
while (dmux->is_running) // !!!
{
if (Emu.IsStopped())
{
@ -603,7 +600,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
break;
}
Sleep(1);
//return CELL_DMUX_ERROR_BUSY;
return CELL_DMUX_ERROR_BUSY;
}
DemuxerTask task(dmuxSetStream);
@ -938,14 +935,19 @@ int cellDmuxReleaseAu(u32 esHandle)
{
cellDmux.Error("cellDmuxReleaseAu: no AU");
return CELL_DMUX_ERROR_SEQ;
//return CELL_OK;
}
DemuxerTask task(dmuxReleaseAu);
/*DemuxerTask task(dmuxReleaseAu);
task.es.es = esHandle;
task.es.es_ptr = es;
es->dmux->job.Push(task);
es->dmux->job.Push(task);*/
if (!es->release())
{
cellDmux.Error("cellDmuxReleaseAu failed");
return CELL_DMUX_ERROR_SEQ;
}
return CELL_OK;
}

View File

@ -426,7 +426,6 @@ enum DemuxerJobType
dmuxEnableEs,
dmuxDisableEs,
dmuxResetEs,
dmuxReleaseAu,
dmuxFlushEs,
dmuxClose,
};
@ -534,8 +533,9 @@ public:
return last_size;
}
bool isfull() // not multithread-safe
bool isfull()
{
SMutexLocker lock(mutex);
if (first_addr)
{
if (first_addr > last_addr)
@ -581,7 +581,24 @@ public:
{
SMutexLocker lock(mutex);
//ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
if (isfull())
bool is_full;
if (first_addr)
{
if (first_addr > last_addr)
{
is_full = (first_addr - last_addr) < MAX_AU;
}
else
{
is_full = (first_addr + MAX_AU) > (memAddr + memSize);
}
}
else
{
is_full = false;
}
if (is_full)
{
ConLog.Error("ElementaryStream::push(): buffer is full");
Emu.Pause();
@ -634,20 +651,26 @@ public:
return first_addr;
}
void release()
bool release()
{
SMutexLocker lock(mutex);
ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
//ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
if (!canrelease())
{
ConLog.Error("ElementaryStream::release(): buffer is empty");
Emu.Pause();
return;
return false;
}
u32 size = a128(Memory.Read32(first_addr + 4) + 128);
u32 new_addr = first_addr + size;
if (peek_addr <= first_addr) peek_addr = new_addr;
if (peek_addr == first_addr)
{
ConLog.Error("ElementaryStream::release(): buffer has not been seen yet");
return false;
}
//if (peek_addr <= first_addr) peek_addr = new_addr;
if (new_addr == last_addr)
{
first_addr = 0;
@ -660,6 +683,8 @@ public:
{
first_addr = new_addr;
}
return true;
}
bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)

View File

@ -0,0 +1,235 @@
#include "stdafx.h"
#include "cellSpurs.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
void cellSpurs_init();
Module cellSpurs(0x000a, cellSpurs_init);
int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus, int spuPriority,
int ppuPriority, bool exitIfNoWork)
{
cellSpurs.Warning("cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
attr.GetAddr(), nSpus, spuPriority, ppuPriority, exitIfNoWork);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribute> attr, u32 container)
{
cellSpurs.Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)",
attr.GetAddr(), container);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const mem8_t prefix, u32 size)
{
cellSpurs.Warning("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)",
attr.GetAddr(), prefix.GetAddr(), size);
if(!attr.IsGood() || !prefix.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(size > 15) return CELL_SPURS_CORE_ERROR_INVAL;
return CELL_OK;
}
int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> attr)
{
cellSpurs.Warning("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr());
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr, int type)
{
cellSpurs.Warning("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, const u8 priority[8],
uint maxSpu, const bool isPreemptible[8])
{
cellSpurs.Warning("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority[%u], maxSpu=%u, isPreemptible[%u])",
attr.GetAddr(), priority, maxSpu, isPreemptible);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
for (int i=0; i<9; i++)
if(priority[i] != 1 || maxSpu == 0) return CELL_SPURS_CORE_ERROR_INVAL;
return CELL_OK;
}
int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr_t<CellSpursAttribute> attr)
{
cellSpurs.Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)",
spurs.GetAddr(), attr.GetAddr());
if(!attr.IsGood() || !spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group)
{
cellSpurs.Warning("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)",
spurs.GetAddr(), group.GetAddr());
if(!spurs.IsGood() || group.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads)
{
cellSpurs.Warning("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)",
spurs.GetAddr(), nThreads.GetAddr());
if(!spurs.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t nThreads)
{
cellSpurs.Warning("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)",
spurs.GetAddr(), thread.GetAddr(), nThreads.GetAddr());
if(!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint maxContention)
{
cellSpurs.Warning("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)",
spurs.GetAddr(), workloadId, maxContention);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU])
{
cellSpurs.Warning("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])",
spurs.GetAddr(), workloadId, priorities);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId, uint priority)
{
cellSpurs.Warning("cellSpursSetPriority(spurs_addr=0x%x, workloadId=%u, spuId=%u, priority=%u)",
spurs.GetAddr(), workloadId, spuId, priority);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isPreemptible[8])
{
cellSpurs.Warning("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])",
spurs.GetAddr(), isPreemptible);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t port, int isDynamic)
{
cellSpurs.Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%u)",
spurs.GetAddr(), queue, port.GetAddr(), isDynamic);
if(!spurs.IsGood() || !port.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
{
cellSpurs.Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag)
{
cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
mem_func_ptr_t<CellSpursGlobalExceptionEventHandler> eaHandler, mem_ptr_t<void> arg)
{
cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)",
spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr());
if(!spurs.IsGood() || eaHandler.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info)
{
cellSpurs.Warning("cellSpursGetInfo(spurs_addr=0x%x, info_addr=0x%x)", spurs.GetAddr(), info.GetAddr());
if(!spurs.IsGood() || !info.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
// Task functions
int cellSpursGetTasksetId(mem_ptr_t<CellSpursTaskset> taskset, mem32_t workloadId)
{
cellSpurs.Warning("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr());
if(!taskset.IsGood() || !taskset.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK;
}
void cellSpurs_init()
{
//libspurs core functions
cellSpurs.AddFunc(0x95180230, _cellSpursAttributeInitialize);
cellSpurs.AddFunc(0x82275c1c, cellSpursAttributeSetMemoryContainerForSpuThread);
cellSpurs.AddFunc(0x07529113, cellSpursAttributeSetNamePrefix);
cellSpurs.AddFunc(0x1051d134, cellSpursAttributeEnableSpuPrintfIfAvailable);
cellSpurs.AddFunc(0xa839a4d9, cellSpursAttributeSetSpuThreadGroupType);
cellSpurs.AddFunc(0x9dcbcb5d, cellSpursAttributeEnableSystemWorkload);
cellSpurs.AddFunc(0x30aa96c4, cellSpursInitializeWithAttribute2);
cellSpurs.AddFunc(0xca4c4600, cellSpursFinalize);
cellSpurs.AddFunc(0x39c173fb, cellSpursGetSpuThreadGroupId);
cellSpurs.AddFunc(0xc56defb5, cellSpursGetNumSpuThread);
cellSpurs.AddFunc(0x6c960f6d, cellSpursGetSpuThreadId);
cellSpurs.AddFunc(0x84d2f6d5,cellSpursSetMaxContention);
cellSpurs.AddFunc(0x80a29e27,cellSpursSetPriorities);
//cellSpurs.AddFunc(,cellSpursSetPriority);
cellSpurs.AddFunc(0x4de203e2, cellSpursSetPreemptionVictimHints);
cellSpurs.AddFunc(0xb9bc6207, cellSpursAttachLv2EventQueue);
cellSpurs.AddFunc(0x4e66d483, cellSpursDetachLv2EventQueue);
cellSpurs.AddFunc(0x32b94add, cellSpursEnableExceptionEventHandler);
cellSpurs.AddFunc(0x7517724a, cellSpursSetGlobalExceptionEventHandler);
cellSpurs.AddFunc(0x861237f8, cellSpursUnsetGlobalExceptionEventHandler);
cellSpurs.AddFunc(0x1f402f8f, cellSpursGetInfo);
//libspurs task functions
}

View File

@ -0,0 +1,296 @@
#pragma once
// return codes
enum
{
CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701,
CELL_SPURS_CORE_ERROR_INVAL = 0x80410702,
CELL_SPURS_CORE_ERROR_NOMEM = 0x80410704,
CELL_SPURS_CORE_ERROR_SRCH = 0x80410705,
CELL_SPURS_CORE_ERROR_PERM = 0x80410709,
CELL_SPURS_CORE_ERROR_BUSY = 0x8041070A,
CELL_SPURS_CORE_ERROR_STAT = 0x8041070F,
CELL_SPURS_CORE_ERROR_ALIGN = 0x80410710,
CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711,
};
//defines
enum SPURSKernelInterfaces
{
CELL_SPURS_MAX_SPU = 8,
CELL_SPURS_MAX_WORKLOAD = 16,
CELL_SPURS_MAX_WORKLOAD2 = 32,
CELL_SPURS_MAX_PRIORITY = 16,
CELL_SPURS_NAME_MAX_LENGTH = 15,
CELL_SPURS_SIZE = 4096,
CELL_SPURS_SIZE2 = 8192,
CELL_SPURS_ALIGN = 128,
CELL_SPURS_ATTRIBUTE_SIZE = 512,
CELL_SPURS_ATTRIBUTE_ALIGN = 8,
CELL_SPURS_INTERRUPT_VECTOR = 0x0,
CELL_SPURS_LOCK_LINE = 0x80,
CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
};
enum RangeofEventQueuePortNumbers
{
CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15,
CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16,
CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63,
};
enum SPURSTraceTypes
{
CELL_SPURS_TRACE_TAG_LOAD = 0x2a,
CELL_SPURS_TRACE_TAG_MAP = 0x2b,
CELL_SPURS_TRACE_TAG_START = 0x2c,
CELL_SPURS_TRACE_TAG_STOP = 0x2d,
CELL_SPURS_TRACE_TAG_USER = 0x2e,
CELL_SPURS_TRACE_TAG_GUID = 0x2f,
};
struct CellSpursInfo
{
be_t<int> nSpus;
be_t<int> spuThreadGroupPriority;
be_t<int> ppuThreadPriority;
bool exitIfNoWork;
bool spurs2;
be_t<u32> traceBuffer_addr; //void *traceBuffer;
be_t<u64> traceBufferSize;
be_t<u32> traceMode;
be_t<u32> spuThreadGroup; //typedef u32 sys_spu_thread_group_t;
be_t<u32> spuThreads[8]; //typedef u32 sys_spu_thread_t;
be_t<u32> spursHandlerThread0;
be_t<u32> spursHandlerThread1;
char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1];
be_t<u64> namePrefixLength;
be_t<u32> deadlineMissCounter;
be_t<u32> deadlineMeetCounter;
//u8 padding[];
};
struct CellSpursExceptionInfo
{
be_t<u32> spu_thread;
be_t<u32> spu_npc;
be_t<u32> cause;
be_t<u64> option;
};
struct CellSpursTraceInfo
{
be_t<u32> spu_thread[8];
be_t<u32> count[8];
be_t<u32> spu_thread_grp;
be_t<u32> nspu;
//u8 padding[];
};
__declspec(align(8)) struct CellTraceHeader
{
u8 tag;
u8 length;
u8 cpu;
u8 thread;
be_t<u32> time;
};
struct CellSpursTracePacket
{
struct header_struct
{
u8 tag;
u8 length;
u8 spu;
u8 workload;
be_t<u32> time;
} header;
struct data_struct
{
struct load_struct
{
be_t<u32> ea;
be_t<u16> ls;
be_t<u16> size;
} load;
struct map_struct
{
be_t<u32> offset;
be_t<u16> ls;
be_t<u16> size;
} map;
struct start_struct
{
char module[4];
be_t<u16> level;
be_t<u16> ls;
} start;
be_t<u64> user;
be_t<u64> guid;
} data;
};
__declspec(align(128)) struct CellSpurs
{
u8 skip[CELL_SPURS_SIZE];
};
__declspec(align(128)) struct CellSpurs2
{
u8 skip[CELL_SPURS_SIZE2 - CELL_SPURS_SIZE];
};
__declspec(align(8)) struct CellSpursAttribute
{
u8 skip[CELL_SPURS_ATTRIBUTE_SIZE];
};
//typedef unsigned CellSpursWorkloadId;
typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, const mem_ptr_t<CellSpursExceptionInfo> info,
uint id, mem_ptr_t<void> arg);
// task datatypes and constans
enum TaskConstants
{
CELL_SPURS_MAX_TASK = 128,
CELL_SPURS_TASK_TOP = 0x3000,
CELL_SPURS_TASK_BOTTOM = 0x40000,
CELL_SPURS_MAX_TASK_NAME_LENGTH = 32,
};
enum
{
CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901,
CELL_SPURS_TASK_ERROR_INVAL = 0x80410902,
CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904,
CELL_SPURS_TASK_ERROR_SRCH = 0x80410905,
CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907,
CELL_SPURS_TASK_ERROR_PERM = 0x80410909,
CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A,
CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D,
CELL_SPURS_TASK_ERROR_STAT = 0x8041090F,
CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910,
CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911,
CELL_SPURS_TASK_ERROR_FATAL = 0x80410914,
CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920,
};
__declspec(align(128)) struct CellSpursTaskset
{
u8 skip[6400];
};
typedef void(*CellSpursTasksetExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
uint idTask, const mem_ptr_t<CellSpursExceptionInfo> info, mem_ptr_t<void> arg);
struct CellSpursTasksetInfo
{
//CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK];
be_t<u64> argument;
be_t<uint> idWorkload;
be_t<uint> idLastScheduledTask; //typedef unsigned CellSpursTaskId
be_t<u32> name_addr;
CellSpursTasksetExceptionEventHandler exceptionEventHandler;
be_t<u32> exceptionEventHandlerArgument_addr; //void *exceptionEventHandlerArgument
be_t<u64> sizeTaskset;
//be_t<u8> reserved[];
};
/*
#define CELL_SPURS_TASKSET_CLASS0_SIZE (128 * 50)
#define _CELL_SPURS_TASKSET_CLASS1_EXTENDED_SIZE (128 + 128 * 16 + 128 * 15)
#define CELL_SPURS_TASKSET_CLASS1_SIZE (CELL_SPURS_TASKSET_CLASS0_SIZE + _CELL_SPURS_TASKSET_CLASS1_EXTENDED_SIZE)
#define CELL_SPURS_TASKSET2_SIZE (CELL_SPURS_TASKSET_CLASS1_SIZE)
#define CELL_SPURS_TASKSET2_ALIGN 128
#define CELL_SPURS_TASKSET_ALIGN 128
#define CELL_SPURS_TASKSET_SIZE CELL_SPURS_TASKSET_CLASS0_SIZE
*/
__declspec(align(128)) struct CellSpursTaskset2
{
be_t<u8> skip[10496];
};
struct CellSpursTasksetAttribute2
{
be_t<u32> revision;
be_t<u32> name_addr;
be_t<u64> argTaskset;
u8 priority[8];
be_t<u32> maxContention;
be_t<s32> enableClearLs;
be_t<s32> CellSpursTaskNameBuffer_addr; //??? *taskNameBuffer
//be_t<u32> __reserved__[];
};
struct CellSpursTaskNameBuffer
{
char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH];
};
struct CellSpursTraceTaskData
{
be_t<u32> incident;
be_t<u32> task;
};
struct CellSpursTaskArgument
{
be_t<u32> u32[4];
be_t<u64> u64[2];
};
struct CellSpursTaskLsPattern
{
be_t<u32> u32[4];
be_t<u64> u64[2];
};
struct CellSpursTaskAttribute2
{
be_t<u32> revision;
be_t<u32> sizeContext;
be_t<u64> eaContext;
CellSpursTaskLsPattern lsPattern; //???
be_t<u32> name_addr;
//be_t<u32> __reserved__[];
};
__declspec(align(128)) struct CellSpursTaskExitCode
{
unsigned char skip[128];
};
struct CellSpursTaskInfo
{
CellSpursTaskLsPattern lsPattern;
CellSpursTaskArgument argument;
const be_t<u32> eaElf_addr; //void *eaElf
const be_t<u32> eaContext_addr; //void *eaContext
be_t<u32> sizeContext;
be_t<u8> state;
be_t<u8> hasSignal;
const be_t<u32> CellSpursTaskExitCode_addr;
u8 guid[8];
//be_t<u8> reserved[];
};
struct CellSpursTaskBinInfo
{
be_t<u64> eaElf;
be_t<u32> sizeContext;
be_t<u32> __reserved__;
CellSpursTaskLsPattern lsPattern;
};

View File

@ -23,7 +23,7 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
int res = 0;
if (vdec.reader.size < (u32)buf_size)
if (vdec.reader.size < (u32)buf_size && !vdec.just_started)
{
while (vdec.job.IsEmpty())
{
@ -74,7 +74,10 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type);
return 0;
}
//buf_size = vdec.reader.size;
}
else if (vdec.reader.size < (u32)buf_size)
{
buf_size = vdec.reader.size;
}
if (!buf_size)
@ -123,6 +126,8 @@ u32 vdecOpen(VideoDecoder* data)
vdec.id = vdec_id;
vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback");
thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]()
{
ConLog.Write("Video Decoder enter()");

View File

@ -77,8 +77,26 @@ int sys_cond_signal(u32 cond_id)
if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
{
CPUThread* tt = Emu.GetCPU().GetThread(target);
bool valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal(%d): signal to invalid thread(%d)", cond_id, target);
return CELL_OK;
}
if (!was_locked) // mutex hasn't been locked (don't care about mutex state)
{
if (u32 owner = mutex->m_mutex.GetOwner())
{
tt = Emu.GetCPU().GetThread(owner);
valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal(%d): deadlock on invalid thread(%d)", cond_id, owner);
return CELL_OK;
}
}
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
@ -117,8 +135,26 @@ int sys_cond_signal_all(u32 cond_id)
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
{
CPUThread* tt = Emu.GetCPU().GetThread(target);
bool valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal_all(%d): signal to invalid thread(%d)", cond_id, target);
return CELL_OK;
}
if (!was_locked)
{
if (u32 owner = mutex->m_mutex.GetOwner())
{
tt = Emu.GetCPU().GetThread(owner);
valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal_all(%d): deadlock on invalid thread(%d)", cond_id, owner);
return CELL_OK;
}
}
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);
@ -130,11 +166,11 @@ int sys_cond_signal_all(u32 cond_id)
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
}
}
if (Emu.IsStopped())
{
ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id);
if (Emu.IsStopped())
{
ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id);
}
}
return CELL_OK;
@ -169,6 +205,16 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id)
{
if (!was_locked)
{
if (u32 owner = mutex->m_mutex.GetOwner())
{
CPUThread* tt = Emu.GetCPU().GetThread(owner);
bool valid = tt && tt->IsAlive();
if (!valid)
{
sys_cond.Error("sys_cond_signal_to(%d): deadlock on invalid thread(%d)", cond_id, owner);
return CELL_OK;
}
}
mutex->m_mutex.lock(tid);
mutex->recursive = 1;
mutex->m_mutex.unlock(tid, target);

View File

@ -74,17 +74,17 @@ int sys_event_queue_destroy(u32 equeue_id, int mode)
u32 tid = GetCurrentPPUThread().GetId();
eq->sq.m_mutex.lock(tid);
eq->sq.m_mutex.lock();
eq->owner.lock(tid);
// check if some threads are waiting for an event
if (!mode && eq->sq.list.GetCount())
{
eq->owner.unlock(tid);
eq->sq.m_mutex.unlock(tid);
eq->sq.m_mutex.unlock();
return CELL_EBUSY;
}
eq->owner.unlock(tid, ~0);
eq->sq.m_mutex.unlock(tid);
eq->sq.m_mutex.unlock();
while (eq->sq.list.GetCount())
{
Sleep(1);
@ -136,18 +136,18 @@ int sys_event_queue_tryreceive(u32 equeue_id, mem_ptr_t<sys_event_data> event_ar
u32 tid = GetCurrentPPUThread().GetId();
eq->sq.m_mutex.lock(tid);
eq->sq.m_mutex.lock();
eq->owner.lock(tid);
if (eq->sq.list.GetCount())
{
number = 0;
eq->owner.unlock(tid);
eq->sq.m_mutex.unlock(tid);
eq->sq.m_mutex.unlock();
return CELL_OK;
}
number = eq->events.pop_all((sys_event_data*)(Memory + event_array.GetAddr()), size);
eq->owner.unlock(tid);
eq->sq.m_mutex.unlock(tid);
eq->sq.m_mutex.unlock();
return CELL_OK;
}

View File

@ -99,13 +99,13 @@ int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex)
void SleepQueue::push(u32 tid)
{
SMutexLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
list.AddCpy(tid);
}
u32 SleepQueue::pop() // SYS_SYNC_FIFO
{
SMutexLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
while (true)
{
@ -125,7 +125,7 @@ u32 SleepQueue::pop() // SYS_SYNC_FIFO
u32 SleepQueue::pop_prio() // SYS_SYNC_PRIORITY
{
SMutexLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
while (true)
{
@ -171,7 +171,7 @@ u32 SleepQueue::pop_prio_inherit() // (TODO)
bool SleepQueue::invalidate(u32 tid)
{
SMutexLocker lock(m_mutex);
std::lock_guard<std::mutex> lock(m_mutex);
if (tid) for (u32 i = 0; i < list.GetCount(); i++)
{
@ -187,15 +187,13 @@ bool SleepQueue::invalidate(u32 tid)
bool SleepQueue::finalize()
{
u32 tid = GetCurrentPPUThread().GetId();
m_mutex.lock(tid);
if (!m_mutex.try_lock()) return false;
for (u32 i = 0; i < list.GetCount(); i++)
{
if (list[i])
{
m_mutex.unlock(tid);
m_mutex.unlock();
return false;
}
}
@ -230,7 +228,7 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
}
}
while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
/*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
{
if (Emu.IsStopped())
{
@ -238,7 +236,7 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
return CELL_ESRCH;
}
Sleep(1);
}
}*/
if (tid == owner_tid)
{

View File

@ -47,7 +47,7 @@ struct SleepQueue
q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {}
}; */
Array<u32> list;
SMutex m_mutex;
std::mutex m_mutex;
u64 m_name;
SleepQueue(u64 name = 0)

View File

@ -41,6 +41,7 @@ int sys_mutex_create(mem32_t mutex_id, mem_ptr_t<sys_mutex_attribute> attr)
Mutex* mutex = new Mutex((u32)attr->protocol, is_recursive, attr->name_u64);
u32 id = sys_mtx.GetNewId(mutex);
mutex->m_mutex.lock(tid);
mutex->id = id;
mutex_id = id;
mutex->m_mutex.unlock(tid);
sys_mtx.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d",
@ -120,20 +121,20 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
{
if (!tt->IsAlive())
{
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
mutex->m_mutex.unlock(owner, tid);
if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;
return CELL_OK;*/
}
}
else
{
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
mutex->m_mutex.unlock(owner, tid);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;
return CELL_OK;*/
}
}
@ -202,20 +203,20 @@ int sys_mutex_trylock(u32 mutex_id)
{
if (!tt->IsAlive())
{
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
mutex->m_mutex.unlock(owner, tid);
if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;
return CELL_OK;*/
}
}
else
{
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
mutex->m_mutex.unlock(owner, tid);
/*mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
t.owned_mutexes++;
return CELL_OK;
return CELL_OK;*/
}
}
@ -244,7 +245,7 @@ int sys_mutex_unlock(u32 mutex_id)
{
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
{
sys_mtx.Error("sys_mutex_unlock(%d): wrong recursive value (%d)", mutex_id, mutex->recursive);
sys_mtx.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive);
mutex->recursive = 1;
}
mutex->recursive--;

View File

@ -18,6 +18,7 @@ struct sys_mutex_attribute
struct Mutex
{
u32 id;
SMutex m_mutex;
SleepQueue m_queue;
u32 recursive; // recursive locks count
@ -33,4 +34,21 @@ struct Mutex
, cond_count(0)
{
}
~Mutex()
{
if (u32 owner = m_mutex.GetOwner())
{
ConLog.Write("Mutex(%d) was owned by thread %d (recursive=%d)", id, owner, recursive);
}
if (!m_queue.m_mutex.try_lock()) return;
for (u32 i = 0; i < m_queue.list.GetCount(); i++)
{
if (u32 owner = m_queue.list[i]) ConLog.Write("Mutex(%d) was waited by thread %d", id, owner);
}
m_queue.m_mutex.unlock();
}
};

View File

@ -297,6 +297,7 @@
<ClCompile Include="Emu\SysCalls\Modules\cellPngDec.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellResc.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellRtc.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellSpurs.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellSync.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellSysmodule.cpp" />
<ClCompile Include="Emu\SysCalls\Modules\cellSysutil.cpp" />

View File

@ -436,22 +436,19 @@
<ClCompile Include="Crypto\utils.cpp">
<Filter>Crypto</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Static.cpp">
<Filter>Emu\SysCalls</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\cellNetCtl.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\cellL10n.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\libmixer.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\Modules\cellSpurs.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
</ItemGroup>