Clean up sceKernelFreeVpl(), not waking yet.

This commit is contained in:
Unknown W. Brackets 2013-01-16 00:47:06 -08:00
parent c8bb837996
commit 4c510b5649
5 changed files with 50 additions and 15 deletions

View File

@ -627,7 +627,7 @@ const HLEFunction ThreadManForUser[] =
{0xBED27435,WrapI_IUUU<sceKernelAllocateVpl>,"sceKernelAllocateVpl"}, {0xBED27435,WrapI_IUUU<sceKernelAllocateVpl>,"sceKernelAllocateVpl"},
{0xEC0A693F,WrapI_IUUU<sceKernelAllocateVplCB>,"sceKernelAllocateVplCB"}, {0xEC0A693F,WrapI_IUUU<sceKernelAllocateVplCB>,"sceKernelAllocateVplCB"},
{0xAF36D708,WrapI_IUU<sceKernelTryAllocateVpl>,"sceKernelTryAllocateVpl"}, {0xAF36D708,WrapI_IUU<sceKernelTryAllocateVpl>,"sceKernelTryAllocateVpl"},
{0xB736E9FF,sceKernelFreeVpl,"sceKernelFreeVpl"}, {0xB736E9FF,WrapI_IU<sceKernelFreeVpl>,"sceKernelFreeVpl"},
{0x1D371B8A,sceKernelCancelVpl,"sceKernelCancelVpl"}, {0x1D371B8A,sceKernelCancelVpl,"sceKernelCancelVpl"},
{0x39810265,sceKernelReferVplStatus,"sceKernelReferVplStatus"}, {0x39810265,sceKernelReferVplStatus,"sceKernelReferVplStatus"},

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at // Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include "HLE.h" #include "HLE.h"
#include "../System.h" #include "../System.h"
#include "../MIPS/MIPS.h" #include "../MIPS/MIPS.h"
@ -130,12 +131,15 @@ struct VPL : public KernelObject
{ {
p.Do(nv); p.Do(nv);
p.Do(address); p.Do(address);
SceUID dv = 0;
p.Do(waitingThreads, dv);
alloc.DoState(p); alloc.DoState(p);
p.DoMarker("VPL"); p.DoMarker("VPL");
} }
SceKernelVplInfo nv; SceKernelVplInfo nv;
u32 address; u32 address;
std::vector<SceUID> waitingThreads;
BlockAllocator alloc; BlockAllocator alloc;
}; };
@ -894,8 +898,14 @@ int sceKernelAllocateVpl(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr)
{ {
VPL *vpl = kernelObjects.Get<VPL>(uid, error); VPL *vpl = kernelObjects.Get<VPL>(uid, error);
if (vpl) if (vpl)
{
vpl->nv.numWaitThreads++; vpl->nv.numWaitThreads++;
SceUID threadID = __KernelGetCurThread();
if (std::find(vpl->waitingThreads.begin(), vpl->waitingThreads.end(), threadID) == vpl->waitingThreads.end())
vpl->waitingThreads.push_back(threadID);
}
__KernelSetVplTimeout(timeoutPtr); __KernelSetVplTimeout(timeoutPtr);
__KernelWaitCurThread(WAITTYPE_VPL, uid, size, timeoutPtr, false); __KernelWaitCurThread(WAITTYPE_VPL, uid, size, timeoutPtr, false);
} }
@ -914,8 +924,14 @@ int sceKernelAllocateVplCB(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr)
{ {
VPL *vpl = kernelObjects.Get<VPL>(uid, error); VPL *vpl = kernelObjects.Get<VPL>(uid, error);
if (vpl) if (vpl)
{
vpl->nv.numWaitThreads++; vpl->nv.numWaitThreads++;
SceUID threadID = __KernelGetCurThread();
if (std::find(vpl->waitingThreads.begin(), vpl->waitingThreads.end(), threadID) == vpl->waitingThreads.end())
vpl->waitingThreads.push_back(threadID);
}
__KernelSetVplTimeout(timeoutPtr); __KernelSetVplTimeout(timeoutPtr);
__KernelWaitCurThread(WAITTYPE_VPL, uid, size, timeoutPtr, true); __KernelWaitCurThread(WAITTYPE_VPL, uid, size, timeoutPtr, true);
} }
@ -930,26 +946,32 @@ int sceKernelTryAllocateVpl(SceUID uid, u32 size, u32 addrPtr)
return error; return error;
} }
void sceKernelFreeVpl() int sceKernelFreeVpl(SceUID uid, u32 addr)
{ {
SceUID id = PARAM(0); if (addr && !Memory::IsValidAddress(addr))
u32 blockPtr = PARAM(1); {
DEBUG_LOG(HLE,"sceKernelFreeVpl(%i, %08x)", id, blockPtr); WARN_LOG(HLE, "%08x=sceKernelFreeVpl(%i, %08x): Invalid address", SCE_KERNEL_ERROR_ILLEGAL_ADDR, uid, addr);
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
}
DEBUG_LOG(HLE, "sceKernelFreeVpl(%i, %08x)", uid, addr);
u32 error; u32 error;
VPL *vpl = kernelObjects.Get<VPL>(id, error); VPL *vpl = kernelObjects.Get<VPL>(uid, error);
if (vpl) if (vpl)
{ {
if (vpl->alloc.Free(blockPtr)) { if (vpl->alloc.FreeExact(addr))
RETURN(0); {
// Should trigger waiting threads // Should trigger waiting threads
} else { return 0;
ERROR_LOG(HLE, "sceKernelFreeVpl: Error freeing %08x", blockPtr); }
RETURN(-1); else
{
WARN_LOG(HLE, "%08x=sceKernelFreeVpl(%i, %08x): Unable to free", SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK, uid, addr);
return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK;
} }
} }
else { else
RETURN(error); return error;
}
} }
void sceKernelCancelVpl() void sceKernelCancelVpl()

View File

@ -41,7 +41,7 @@ void sceKernelDeleteVpl();
int sceKernelAllocateVpl(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr); int sceKernelAllocateVpl(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr);
int sceKernelAllocateVplCB(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr); int sceKernelAllocateVplCB(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr);
int sceKernelTryAllocateVpl(SceUID uid, u32 size, u32 addrPtr); int sceKernelTryAllocateVpl(SceUID uid, u32 size, u32 addrPtr);
void sceKernelFreeVpl(); int sceKernelFreeVpl(SceUID uid, u32 addr);
void sceKernelCancelVpl(); void sceKernelCancelVpl();
void sceKernelReferVplStatus(); void sceKernelReferVplStatus();

View File

@ -219,6 +219,18 @@ bool BlockAllocator::Free(u32 position)
} }
} }
bool BlockAllocator::FreeExact(u32 position)
{
BlockAllocator::Block *b = GetBlockFromAddress(position);
if (b && b->taken && b->start == position)
return Free(position);
else
{
ERROR_LOG(HLE, "BlockAllocator : invalid free %08x", position);
return false;
}
}
void BlockAllocator::CheckBlocks() void BlockAllocator::CheckBlocks()
{ {
for (std::list<Block>::iterator iter = blocks.begin(); iter != blocks.end(); iter++) for (std::list<Block>::iterator iter = blocks.begin(); iter != blocks.end(); iter++)

View File

@ -29,6 +29,7 @@ public:
u32 AllocAt(u32 position, u32 size, const char *tag = 0); u32 AllocAt(u32 position, u32 size, const char *tag = 0);
bool Free(u32 position); bool Free(u32 position);
bool FreeExact(u32 position);
bool IsBlockFree(u32 position) { bool IsBlockFree(u32 position) {
Block *b = GetBlockFromAddress(position); Block *b = GetBlockFromAddress(position);
if (b) if (b)