mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add a waittype registry to handle callbacks right.
This commit is contained in:
parent
afa21588d7
commit
d2abdf17be
2 changed files with 70 additions and 15 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue