diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 76550a38e3..94a754d8e4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -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()"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 96ad7083a6..36b8ffef44 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t 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 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; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index 5da56f721e..cc504fe2f0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -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) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp new file mode 100644 index 0000000000..e6e9bbd98e --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -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 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 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 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 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 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 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 spurs, const mem_ptr_t 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 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 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 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 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 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 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 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 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 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 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 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 spurs, + mem_func_ptr_t eaHandler, mem_ptr_t 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 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 spurs, mem_ptr_t 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 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 +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h new file mode 100644 index 0000000000..af9f4c4e6c --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -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 nSpus; + be_t spuThreadGroupPriority; + be_t ppuThreadPriority; + bool exitIfNoWork; + bool spurs2; + be_t traceBuffer_addr; //void *traceBuffer; + be_t traceBufferSize; + be_t traceMode; + be_t spuThreadGroup; //typedef u32 sys_spu_thread_group_t; + be_t spuThreads[8]; //typedef u32 sys_spu_thread_t; + be_t spursHandlerThread0; + be_t spursHandlerThread1; + char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1]; + be_t namePrefixLength; + be_t deadlineMissCounter; + be_t deadlineMeetCounter; + //u8 padding[]; +}; + +struct CellSpursExceptionInfo +{ + be_t spu_thread; + be_t spu_npc; + be_t cause; + be_t option; +}; + +struct CellSpursTraceInfo +{ + be_t spu_thread[8]; + be_t count[8]; + be_t spu_thread_grp; + be_t nspu; + //u8 padding[]; +}; + +__declspec(align(8)) struct CellTraceHeader +{ + u8 tag; + u8 length; + u8 cpu; + u8 thread; + be_t time; +}; + +struct CellSpursTracePacket +{ + struct header_struct + { + u8 tag; + u8 length; + u8 spu; + u8 workload; + be_t time; + } header; + + struct data_struct + { + struct load_struct + { + be_t ea; + be_t ls; + be_t size; + } load; + + struct map_struct + { + be_t offset; + be_t ls; + be_t size; + } map; + + struct start_struct + { + char module[4]; + be_t level; + be_t ls; + } start; + + be_t user; + be_t 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 spurs, const mem_ptr_t info, + uint id, mem_ptr_t 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 spurs, mem_ptr_t taskset, + uint idTask, const mem_ptr_t info, mem_ptr_t arg); + + +struct CellSpursTasksetInfo +{ + //CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK]; + be_t argument; + be_t idWorkload; + be_t idLastScheduledTask; //typedef unsigned CellSpursTaskId + be_t name_addr; + CellSpursTasksetExceptionEventHandler exceptionEventHandler; + be_t exceptionEventHandlerArgument_addr; //void *exceptionEventHandlerArgument + be_t sizeTaskset; + //be_t 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 skip[10496]; +}; + +struct CellSpursTasksetAttribute2 +{ + be_t revision; + be_t name_addr; + be_t argTaskset; + u8 priority[8]; + be_t maxContention; + be_t enableClearLs; + be_t CellSpursTaskNameBuffer_addr; //??? *taskNameBuffer + //be_t __reserved__[]; +}; + +struct CellSpursTaskNameBuffer +{ + char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH]; +}; + +struct CellSpursTraceTaskData +{ + be_t incident; + be_t task; +}; + +struct CellSpursTaskArgument +{ + be_t u32[4]; + be_t u64[2]; +}; + +struct CellSpursTaskLsPattern +{ + be_t u32[4]; + be_t u64[2]; +}; + +struct CellSpursTaskAttribute2 +{ + be_t revision; + be_t sizeContext; + be_t eaContext; + CellSpursTaskLsPattern lsPattern; //??? + be_t name_addr; + //be_t __reserved__[]; +}; + +__declspec(align(128)) struct CellSpursTaskExitCode +{ + unsigned char skip[128]; +}; + +struct CellSpursTaskInfo +{ + CellSpursTaskLsPattern lsPattern; + CellSpursTaskArgument argument; + const be_t eaElf_addr; //void *eaElf + const be_t eaContext_addr; //void *eaContext + be_t sizeContext; + be_t state; + be_t hasSignal; + const be_t CellSpursTaskExitCode_addr; + u8 guid[8]; + //be_t reserved[]; +}; + +struct CellSpursTaskBinInfo +{ + be_t eaElf; + be_t sizeContext; + be_t __reserved__; + CellSpursTaskLsPattern lsPattern; +}; + diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 5eff43752a..31fab366d6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -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()"); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp index 97555928d8..8f0785ab96 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -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); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index 2e0e9abc2b..b662ee10c5 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -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 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; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 524c600033..10cd0af5ff 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -99,13 +99,13 @@ int sys_lwmutex_unlock(mem_ptr_t lwmutex) void SleepQueue::push(u32 tid) { - SMutexLocker lock(m_mutex); + std::lock_guard lock(m_mutex); list.AddCpy(tid); } u32 SleepQueue::pop() // SYS_SYNC_FIFO { - SMutexLocker lock(m_mutex); + std::lock_guard 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 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 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 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 tid) return CELL_ESRCH; } Sleep(1); - } + }*/ if (tid == owner_tid) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h index 4a5481d0ce..2fa724b52d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -47,7 +47,7 @@ struct SleepQueue q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {} }; */ Array list; - SMutex m_mutex; + std::mutex m_mutex; u64 m_name; SleepQueue(u64 name = 0) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index 90c64b963f..ce1b3f51d3 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -41,6 +41,7 @@ int sys_mutex_create(mem32_t mutex_id, mem_ptr_t 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--; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h index 2366d1656a..735f20a240 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h @@ -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(); + } }; \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 536f9ac22e..c9c01f1c6d 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -297,6 +297,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 6db42d3034..197dd9a6cc 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -436,22 +436,19 @@ Crypto - - Emu\SysCalls - Emu\SysCalls\Modules - - Emu\SysCalls\Modules - + Emu\SysCalls\Modules + + Emu\SysCalls\Modules