Add a wait type for modules to handle return right.

This commit is contained in:
Unknown W. Brackets 2013-05-26 10:54:11 -07:00
parent 727b3b4127
commit 0d828554bc
2 changed files with 39 additions and 10 deletions

View file

@ -162,6 +162,11 @@ struct ModuleInfo {
char name[28]; char name[28];
}; };
struct ModuleWaitingThread
{
SceUID threadID;
u32 statusPtr;
};
class Module : public KernelObject class Module : public KernelObject
{ {
@ -191,10 +196,13 @@ public:
p.Do(nm); p.Do(nm);
p.Do(memoryBlockAddr); p.Do(memoryBlockAddr);
p.Do(memoryBlockSize); p.Do(memoryBlockSize);
ModuleWaitingThread mwt = {0};
p.Do(waitingThreads, mwt);
p.DoMarker("Module"); p.DoMarker("Module");
} }
NativeModule nm; NativeModule nm;
std::vector<ModuleWaitingThread> waitingThreads;
u32 memoryBlockAddr; u32 memoryBlockAddr;
u32 memoryBlockSize; u32 memoryBlockSize;
@ -1089,7 +1097,8 @@ void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValu
} }
else else
{ {
// TODO: Fix, check return value? Or do we call nothing? // TODO: Why are we just returning the module ID in this case?
ERROR_LOG_REPORT(HLE, "sceKernelStartModule(): doing nothing for some reason?");
RETURN(moduleId); RETURN(moduleId);
return; return;
} }
@ -1110,30 +1119,27 @@ void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValu
} }
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0); SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0);
sceKernelStartThread(threadID, argsize, argAddr); sceKernelStartThread(threadID, argsize, argAddr);
// TODO: This will probably return the wrong value? __KernelSetThreadRA(threadID, NID_MODULERETURN);
sceKernelWaitThreadEnd(threadID, 0); __KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "started module");
const ModuleWaitingThread mwt = {__KernelGetCurThread(), returnValueAddr};
module->waitingThreads.push_back(mwt);
} }
else if (entryAddr == 0) else if (entryAddr == 0)
{ {
INFO_LOG(HLE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x)", INFO_LOG(HLE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): no entry address",
moduleId,argsize,argAddr,returnValueAddr,optionAddr); moduleId,argsize,argAddr,returnValueAddr,optionAddr);
WARN_LOG(HLE, "No Entry Address");
} }
else else
{ {
ERROR_LOG(HLE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x)", ERROR_LOG(HLE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): invalid entry address",
moduleId,argsize,argAddr,returnValueAddr,optionAddr); moduleId,argsize,argAddr,returnValueAddr,optionAddr);
ERROR_LOG(HLE, "Invalid Entry Address");
RETURN(-1); RETURN(-1);
return; return;
} }
} }
// TODO: Is this the correct return value?
// JPCSP returns this value as well.
RETURN(moduleId); RETURN(moduleId);
} }
@ -1178,6 +1184,28 @@ void __KernelReturnFromModuleFunc()
// Reschedule immediately (to leave the thread) and delete it and its stack. // Reschedule immediately (to leave the thread) and delete it and its stack.
__KernelReSchedule("returned from module"); __KernelReSchedule("returned from module");
sceKernelDeleteThread(leftThreadID); sceKernelDeleteThread(leftThreadID);
u32 error;
Module *module = kernelObjects.Get<Module>(leftModuleID, error);
if (!module)
{
ERROR_LOG_REPORT(HLE, "Returned from deleted module start/stop func");
return;
}
// We can't be starting and stopping at the same time, so no need to differentiate.
for (auto it = module->waitingThreads.begin(), end = module->waitingThreads.end(); it < end; ++it)
{
// Still waiting?
SceUID waitingModuleID = __KernelGetWaitID(it->threadID, WAITTYPE_MODULE, error);
if (waitingModuleID == leftModuleID)
{
if (it->statusPtr != 0)
Memory::Write_U32(exitStatus, it->statusPtr);
__KernelResumeThreadFromWait(it->threadID, 0);
}
}
module->waitingThreads.clear();
} }
struct GetModuleIdByAddressArg struct GetModuleIdByAddressArg

View file

@ -89,6 +89,7 @@ enum WaitType
WAITTYPE_IO = 16, WAITTYPE_IO = 16,
WAITTYPE_GEDRAWSYNC = 17, WAITTYPE_GEDRAWSYNC = 17,
WAITTYPE_GELISTSYNC = 18, WAITTYPE_GELISTSYNC = 18,
WAITTYPE_MODULE = 19,
NUM_WAITTYPES NUM_WAITTYPES
}; };