From 384536ba4f122d96873e95c970b6474f25b284bb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 4 Mar 2014 23:18:17 +0400 Subject: [PATCH] prx_mem memory leak fixed CPUThread::ExecAsCallback (experimental) --- Utilities/SMutex.h | 10 ++++-- rpcs3/Emu/CPU/CPUThread.cpp | 41 +++++++++++++++++++++++++ rpcs3/Emu/CPU/CPUThread.h | 2 ++ rpcs3/Emu/Cell/PPUThread.cpp | 5 +-- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 35 ++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 3 ++ rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 31 ++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 2 ++ rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 36 ++++++++++++++++------ rpcs3/Emu/SysCalls/Modules/cellVdec.h | 5 ++- rpcs3/Emu/System.cpp | 2 ++ 11 files changed, 133 insertions(+), 39 deletions(-) diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index b92d67e614..5aa9a98f07 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -145,15 +145,19 @@ public: { if (!tid) { - ConLog.Error("SMutexLockerBase: thread id == 0"); - Emu.Pause(); + if (!Emu.IsStopped()) + { + ConLog.Error("SMutexLockerBase: thread id == 0"); + Emu.Pause(); + } + return; } sm.lock(tid); } ~SMutexLockerBase() { - sm.unlock(tid); + if (tid) sm.unlock(tid); } }; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 2d98e28e4b..e2ce343447 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -360,3 +360,44 @@ void CPUThread::Task() if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().wx_str()); } + +int CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe +{ + while (m_alive) + { + if (Emu.IsStopped()) + { + ConLog.Warning("ExecAsCallback() aborted"); + return CELL_ECANCELED; // doesn't mean anything + } + Sleep(1); + } + + Stop(); + Reset(); + + SetEntry(pc); + SetPrio(1001); + SetStackSize(0x10000); + SetExitStatus(CELL_OK); + + SetArg(0, a1); + SetArg(1, a2); + SetArg(2, a3); + SetArg(3, a4); + Run(); + + Exec(); + + while (wait && m_alive) + { + if (Emu.IsStopped()) + { + ConLog.Warning("ExecAsCallback() aborted"); + return CELL_EABORT; // doesn't mean anything + } + Sleep(1); + } + + return wait * m_exit_status; +} \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 88470283bc..4c0e94ed01 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -234,6 +234,8 @@ public: return pc + 4; } + int ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); + protected: virtual void DoReset()=0; virtual void DoRun()=0; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 91dce7d6a8..1c1c903b50 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -118,14 +118,11 @@ void PPUThread::InitRegs() GPR[6] = m_args[3]; } - u32 prx_mem = Memory.PRXMem.AllocAlign(0x10000); - Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE); - GPR[0] = pc; GPR[8] = entry; GPR[11] = 0x80; GPR[12] = Emu.GetMallocPageSize(); - GPR[13] = prx_mem + 0x7060; + GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; GPR[28] = GPR[4]; GPR[29] = GPR[3]; GPR[31] = GPR[5]; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index d784a9524d..d616ce0c82 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -47,6 +47,8 @@ u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; + adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + u32 adec_id = cellAdec.GetNewId(data); adec.id = adec_id; @@ -70,11 +72,11 @@ u32 adecOpen(AudioDecoder* data) continue; } - if (adec.frames.GetCount() >= 50) + /*if (adec.frames.GetCount() >= 50) { Sleep(1); continue; - } + }*/ if (!adec.job.Pop(task)) { @@ -100,10 +102,11 @@ u32 adecOpen(AudioDecoder* data) // TODO: finalize ConLog.Warning("adecEndSeq:"); - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); - cb.Branch(true); // ??? + cb.Branch(true); // ???*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); avcodec_close(adec.ctx); avformat_close_input(&adec.fmt); @@ -214,14 +217,15 @@ u32 adecOpen(AudioDecoder* data) frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; - frame.size = 2048; + frame.size = 4096; frame.data = nullptr; adec.frames.Push(frame); - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; } @@ -273,17 +277,19 @@ u32 adecOpen(AudioDecoder* data) adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); } } - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); } break; @@ -408,6 +414,7 @@ int cellAdecClose(u32 handle) Sleep(1); } + if (adec->adecCb) Emu.GetCPU().RemoveThread(adec->adecCb->GetId()); Emu.GetIdManager().RemoveID(handle); return CELL_OK; } @@ -506,6 +513,10 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) // copy data if (!af.data) // fake: empty data { + u8* buf = (u8*)malloc(4096); + memset(buf, 0, 4096); + Memory.CopyFromReal(outBuffer_addr, buf, 4096); + free(buf); return CELL_OK; } } @@ -546,7 +557,9 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) adec->memBias += 512; if (adec->memBias + 512 > adec->memSize) + { adec->memBias = 0; + } pcm->pcmHandle = 0; // ??? pcm->pcmAttr.bsiInfo_addr = pcm.GetAddr() + sizeof(CellAdecPcmItem); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 50ace2eb07..63b355bc68 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1064,6 +1064,8 @@ public: const u32 cbArg; u32 memBias; + CPUThread* adecCb; + AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) : type(type) , memAddr(addr) @@ -1071,6 +1073,7 @@ public: , memBias(0) , cbFunc(func) , cbArg(arg) + , adecCb(nullptr) , is_running(false) , is_finished(false) , just_started(false) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 326f2923c9..29f3d83424 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -20,7 +20,7 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_tfilterIdMajor >= 0xe0) attr->memSize = 0x2000000; // 0x45fa49 from ps3 else - attr->memSize = 0x400000; // 0x73d9 from ps3 + attr->memSize = 0x100000; // 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); @@ -30,6 +30,8 @@ u32 dmuxOpen(Demuxer* data) { Demuxer& dmux = *data; + dmux.dmuxCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + u32 dmux_id = cellDmux.GetNewId(data); dmux.id = dmux_id; @@ -138,10 +140,11 @@ u32 dmuxOpen(Demuxer* data) mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } else { @@ -184,10 +187,11 @@ u32 dmuxOpen(Demuxer* data) mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } if (pes.new_au) @@ -292,10 +296,12 @@ task: mem_ptr_t dmuxMsg(a128(dmux.memAddr) + (cb_add ^= 16)); dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(dmux.cbFunc); cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); - cb.Branch(task.type == dmuxResetStreamAndWaitDone); + cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ + dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, task.type == dmuxResetStreamAndWaitDone, + dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); dmux.is_running = false; } break; @@ -370,20 +376,22 @@ task: mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } // callback mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } break; @@ -549,6 +557,7 @@ int cellDmuxClose(u32 demuxerHandle) Sleep(1); } + if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId()); Emu.GetIdManager().RemoveID(demuxerHandle); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index d03b4e7e00..5da56f721e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -470,6 +470,7 @@ public: volatile bool is_finished; volatile bool is_running; + CPUThread* dmuxCb; Demuxer(u32 addr, u32 size, u32 func, u32 arg) : is_finished(false) @@ -478,6 +479,7 @@ public: , memSize(size) , cbFunc(func) , cbArg(arg) + , dmuxCb(nullptr) { } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index f325f3faa3..daad045b0f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -55,10 +55,11 @@ int vdecRead(void* opaque, u8* buf, int buf_size) buf_size -= vdec.reader.size; res += vdec.reader.size; - Callback cb; + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); vdec.job.Pop(vdec.task); @@ -73,6 +74,7 @@ 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; } if (!buf_size) @@ -115,6 +117,8 @@ u32 vdecOpen(VideoDecoder* data) { VideoDecoder& vdec = *data; + vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + u32 vdec_id = cellVdec.GetNewId(data); vdec.id = vdec_id; @@ -168,10 +172,11 @@ u32 vdecOpen(VideoDecoder* data) // TODO: finalize ConLog.Warning("vdecEndSeq:"); - Callback cb; + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); - cb.Branch(true); // ??? + cb.Branch(true); // ???*/ avcodec_close(vdec.ctx); avformat_close_input(&vdec.fmt); @@ -268,6 +273,8 @@ u32 vdecOpen(VideoDecoder* data) Emu.Pause(); break; } + //vdec.ctx->flags |= CODEC_FLAG_TRUNCATED; + //vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS; vdec.just_started = false; } @@ -275,9 +282,15 @@ u32 vdecOpen(VideoDecoder* data) while (true) { + if (Emu.IsStopped()) + { + ConLog.Warning("vdecDecodeAu aborted"); + return; + } last_frame = av_read_frame(vdec.fmt, &au) < 0; if (last_frame) { + //break; av_free(au.data); au.data = NULL; au.size = 0; @@ -329,20 +342,22 @@ u32 vdecOpen(VideoDecoder* data) frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration??? frame.pts = vdec.last_pts; vdec.last_pts += 3003; frame.userdata = task.userData; - vdec.frames.Push(frame); + vdec.frames.Push(frame); // !!!!!!!! frame.data = nullptr; // to prevent destruction - Callback cb; + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ } } - Callback cb; + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ } break; @@ -459,6 +474,7 @@ int cellVdecClose(u32 handle) Sleep(1); } + if (vdec->vdecCb) Emu.GetCPU().RemoveThread(vdec->vdecCb->GetId()); Emu.GetIdManager().RemoveID(handle); return CELL_OK; } @@ -638,7 +654,9 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) vdec->memBias += 512; if (vdec->memBias + 512 > vdec->memSize) + { vdec->memBias = 0; + } info->codecType = vdec->type; info->startAddr = 0x00000123; // invalid value (no address for picture) diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index 7542607d59..96534cdbe2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -718,9 +718,11 @@ public: const u32 cbArg; u32 memBias; - VdecTask task; // reference to current task variable + VdecTask task; // current task variable u64 last_pts, last_dts; + CPUThread* vdecCb; + VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) : type(type) , profile(profile) @@ -733,6 +735,7 @@ public: , is_running(false) , just_started(false) , ctx(nullptr) + , vdecCb(nullptr) { AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); if (!codec) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e910413c66..08f356707e 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -267,6 +267,8 @@ void Emulator::Load() ppu_thr_exit_data += ADDI(11, 0, 41); ppu_thr_exit_data += SC(2); ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); + + Memory.Write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); } break;