Add a waittype registry to handle callbacks right.

This commit is contained in:
Unknown W. Brackets 2013-03-27 00:51:46 -07:00
parent afa21588d7
commit d2abdf17be
2 changed files with 70 additions and 15 deletions

View file

@ -234,6 +234,7 @@ public:
p.Do(waitID);
p.Do(waitInfo);
p.Do(isProcessingCallbacks);
p.Do(currentCallbackId);
p.DoMarker("ActionAfterMipsCall");
@ -258,6 +259,7 @@ public:
int waitID;
ThreadWaitInfo waitInfo;
bool isProcessingCallbacks;
SceUID currentCallbackId;
Action *chainedAction;
};
@ -391,9 +393,9 @@ public:
{
p.Do(nt);
p.Do(waitInfo);
p.Do(sleeping);
p.Do(moduleId);
p.Do(isProcessingCallbacks);
p.Do(currentMipscallId);
p.Do(currentCallbackId);
p.Do(context);
@ -417,11 +419,11 @@ public:
NativeThread nt;
ThreadWaitInfo waitInfo;
bool sleeping;
SceUID moduleId;
bool isProcessingCallbacks;
u32 currentCallbackId;
u32 currentMipscallId;
SceUID currentCallbackId;
ThreadContext context;
@ -496,8 +498,13 @@ struct ThreadList
}
};
void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter);
struct WaitTypeFuncs
{
WaitBeginCallbackFunc beginFunc;
WaitEndCallbackFunc endFunc;
};
void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter);
Thread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr);
void __KernelResetThread(Thread *t);
@ -539,6 +546,9 @@ int actionAfterMipsCall;
// This seems nasty
SceUID curModule;
// Doesn't need state saving.
WaitTypeFuncs waitTypeFuncs[NUM_WAITTYPES];
//////////////////////////////////////////////////////////////////////////
//STATE END
//////////////////////////////////////////////////////////////////////////
@ -623,6 +633,7 @@ void __KernelThreadingInit()
u32 blockSize = 4 * 4 + 4 * 2 * 3; // One 16-byte thread plus 3 8-byte "hacks"
dispatchEnabled = true;
memset(waitTypeFuncs, 0, sizeof(waitTypeFuncs));
currentThread = 0;
g_inCbCount = 0;
@ -896,6 +907,18 @@ SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error)
}
}
SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error)
{
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
return t->currentCallbackId;
else
{
ERROR_LOG(HLE, "__KernelGetCurrentCallbackID ERROR: thread %i", threadID);
return 0;
}
}
u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr)
{
if (threadID == 0)
@ -1405,7 +1428,8 @@ void __KernelResetThread(Thread *t)
t->nt.exitStatus = SCE_KERNEL_ERROR_NOT_DORMANT;
t->isProcessingCallbacks = false;
// TODO: Is this correct?
t->currentCallbackId = 0;
t->currentMipscallId = 0;
t->pendingMipsCalls.clear();
t->context.r[MIPS_REG_RA] = threadReturnHackAddr; //hack! TODO fix
@ -2283,6 +2307,7 @@ void ActionAfterMipsCall::run(MipsCall &call) {
thread->nt.waitID = waitID;
thread->waitInfo = waitInfo;
thread->isProcessingCallbacks = isProcessingCallbacks;
thread->currentCallbackId = currentCallbackId;
}
if (chainedAction) {
@ -2295,7 +2320,7 @@ ActionAfterMipsCall *Thread::getRunningCallbackAction()
{
if (this->GetUID() == currentThread && g_inCbCount > 0)
{
MipsCall *call = mipsCalls.get(this->currentCallbackId);
MipsCall *call = mipsCalls.get(this->currentMipscallId);
ActionAfterMipsCall *action = 0;
if (call)
action = dynamic_cast<ActionAfterMipsCall *>(call->doAfter);
@ -2316,7 +2341,7 @@ void Thread::setReturnValue(u32 retval)
{
if (this->GetUID() == currentThread) {
if (g_inCbCount) {
u32 callId = this->currentCallbackId;
u32 callId = this->currentMipscallId;
MipsCall *call = mipsCalls.get(callId);
if (call) {
call->setReturnValue(retval);
@ -2335,7 +2360,7 @@ void Thread::setReturnValue(u64 retval)
{
if (this->GetUID() == currentThread) {
if (g_inCbCount) {
u32 callId = this->currentCallbackId;
u32 callId = this->currentMipscallId;
MipsCall *call = mipsCalls.get(callId);
if (call) {
call->setReturnValue(retval);
@ -2516,11 +2541,19 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, co
after->waitID = thread->nt.waitID;
after->waitInfo = thread->waitInfo;
after->isProcessingCallbacks = thread->isProcessingCallbacks;
after->currentCallbackId = thread->currentCallbackId;
afterAction = after;
// Release thread from waiting
thread->nt.waitType = WAITTYPE_NONE;
if (thread->nt.waitType != WAITTYPE_NONE) {
// If it's a callback, tell the wait to stop.
if (waitTypeFuncs[thread->nt.waitType].beginFunc != NULL && cbId > 0) {
waitTypeFuncs[thread->nt.waitType].beginFunc(after->threadID, thread->currentCallbackId);
}
// Release thread from waiting
thread->nt.waitType = WAITTYPE_NONE;
}
__KernelChangeThreadState(thread, THREADSTATUS_READY);
}
@ -2583,7 +2616,7 @@ void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter)
call->savedV0 = currentMIPS->r[MIPS_REG_V0];
call->savedV1 = currentMIPS->r[MIPS_REG_V1];
call->savedIdRegister = currentMIPS->r[MIPS_REG_CALL_ID];
call->savedId = cur->currentCallbackId;
call->savedId = cur->currentMipscallId;
call->reschedAfter = reschedAfter;
// Set up the new state
@ -2592,7 +2625,7 @@ void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter)
// We put this two places in case the game overwrites it.
// We may want it later to "inject" return values.
currentMIPS->r[MIPS_REG_CALL_ID] = callId;
cur->currentCallbackId = callId;
cur->currentMipscallId = callId;
for (int i = 0; i < call->numArgs; i++) {
currentMIPS->r[MIPS_REG_A0 + i] = call->args[i];
}
@ -2611,7 +2644,7 @@ void __KernelReturnFromMipsCall()
return;
}
u32 callId = cur->currentCallbackId;
u32 callId = cur->currentMipscallId;
if (currentMIPS->r[MIPS_REG_CALL_ID] != callId)
WARN_LOG_REPORT(HLE, "__KernelReturnFromMipsCall(): s0 is %08x != %08x", currentMIPS->r[MIPS_REG_CALL_ID], callId);
@ -2633,12 +2666,18 @@ void __KernelReturnFromMipsCall()
currentMIPS->r[MIPS_REG_V0] = call->savedV0;
currentMIPS->r[MIPS_REG_V1] = call->savedV1;
currentMIPS->r[MIPS_REG_CALL_ID] = call->savedIdRegister;
cur->currentCallbackId = call->savedId;
cur->currentMipscallId = call->savedId;
if (call->cbId != 0)
g_inCbCount--;
currentCallbackThreadID = 0;
if (cur->nt.waitType != WAITTYPE_NONE)
{
if (waitTypeFuncs[cur->nt.waitType].endFunc != NULL && call->cbId > 0)
waitTypeFuncs[cur->nt.waitType].endFunc(cur->GetUID(), cur->currentCallbackId, currentMIPS->r[MIPS_REG_V0]);
}
// yeah! back in the real world, let's keep going. Should we process more callbacks?
if (!__KernelExecutePendingMipsCalls(cur, call->reschedAfter))
{
@ -2887,6 +2926,12 @@ u32 __KernelNotifyCallbackType(RegisteredCallbackType type, SceUID cbId, int not
return 0;
}
void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc)
{
waitTypeFuncs[type].beginFunc = beginFunc;
waitTypeFuncs[type].endFunc = endFunc;
}
std::vector<DebugThreadInfo> GetThreadsInfo()
{
std::vector<DebugThreadInfo> threadList;

View file

@ -65,7 +65,8 @@ struct SceKernelSysClock {
};
enum WaitType //probably not the real values
// TODO: Map these to PSP wait types.
enum WaitType
{
WAITTYPE_NONE = 0,
WAITTYPE_SLEEP = 1,
@ -84,8 +85,16 @@ enum WaitType //probably not the real values
WAITTYPE_LWMUTEX = 14,
WAITTYPE_CTRL = 15,
WAITTYPE_IO = 16,
NUM_WAITTYPES
};
// Suspend wait and timeout while a thread enters a callback.
typedef void (* WaitBeginCallbackFunc)(SceUID threadID, SceUID prevCallbackId);
// Resume wait and timeout as a thread exits a callback.
typedef void (* WaitEndCallbackFunc)(SceUID threadID, SceUID prevCallbackId, u32 &returnValue);
void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc);
struct ThreadContext
{
@ -144,6 +153,7 @@ inline u32 __KernelResumeThreadFromWait(SceUID threadID, s64 retval)
u32 __KernelGetWaitValue(SceUID threadID, u32 &error);
u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error);
SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error);
SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error);
void __KernelWaitCurThread(WaitType type, SceUID waitId, u32 waitValue, u32 timeoutPtr, bool processCallbacks, const char *reason);
void __KernelReSchedule(const char *reason = "no reason");
void __KernelReSchedule(bool doCallbacks, const char *reason);