From aeadc80045d55e46fcb8c88ef5be727500ce5f68 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Jan 2013 18:43:38 -0800 Subject: [PATCH] Recover from an interrupt during a callback. --- Core/HLE/sceKernelThread.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 6b7a4a9e42..8193d0f93d 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -456,6 +456,8 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force); //STATE BEGIN ////////////////////////////////////////////////////////////////////////// int g_inCbCount = 0; +// Normally, the same as currentThread. In an interrupt, remembers the callback's thread id. +SceUID currentCallbackThreadID = 0; int readyCallbacksCount = 0; SceUID currentThread; u32 idleThreadHackAddr; @@ -563,6 +565,7 @@ void __KernelThreadingInit() dispatchEnabled = true; g_inCbCount = 0; + currentCallbackThreadID = 0; readyCallbacksCount = 0; idleThreadHackAddr = kernelMemory.Alloc(blockSize, false, "threadrethack"); // Make sure it got allocated where we expect it... at the very start of kernel RAM @@ -603,6 +606,7 @@ void __KernelThreadingInit() void __KernelThreadingDoState(PointerWrap &p) { p.Do(g_inCbCount); + p.Do(currentCallbackThreadID); p.Do(readyCallbacksCount); p.Do(idleThreadHackAddr); p.Do(threadReturnHackAddr); @@ -703,6 +707,21 @@ void __KernelIdle() // that was triggered at the end of the Idle period must get a chance to be scheduled. CoreTiming::Advance(); + // We must've exited a callback? + if (__KernelInCallback()) + { + u32 error; + Thread *t = kernelObjects.Get(currentCallbackThreadID, error); + if (t) + __KernelSwitchContext(t, "idle"); + else + { + WARN_LOG(HLE, "UNTESTED - Callback thread deleted during interrupt?"); + g_inCbCount = 0; + currentCallbackThreadID = 0; + } + } + // In Advance, we might trigger an interrupt such as vblank. // If we end up in an interrupt, we don't want to reschedule. // However, we have to reschedule... damn. @@ -1089,6 +1108,11 @@ u32 __KernelDeleteThread(SceUID threadID, int exitStatus, const char *reason, bo if (currentThread == threadID) currentThread = 0; + if (currentCallbackThreadID == threadID) + { + currentCallbackThreadID = 0; + g_inCbCount = 0; + } u32 error; Thread *t = kernelObjects.Get(threadID, error); @@ -2331,6 +2355,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) } g_inCbCount++; + currentCallbackThreadID = currentThread; } void __KernelReturnFromMipsCall() @@ -2367,6 +2392,7 @@ void __KernelReturnFromMipsCall() cur->currentCallbackId = call->savedId; g_inCbCount--; + currentCallbackThreadID = 0; // yeah! back in the real world, let's keep going. Should we process more callbacks? if (!__KernelExecutePendingMipsCalls(call->reschedAfter))