diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index bf298e4d40..7d38ff6802 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -278,6 +278,10 @@ bool __RunOnePendingInterrupt() // Can easily prioritize between different kinds of interrupts if necessary. if (pendingInterrupts.size()) { + // If we came from CoreTiming::Advance(), we might've come from a waiting thread's callback. + // To avoid "injecting" return values into our saved state, we context switch here. + __KernelSwitchOffThread("interrupt"); + PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); intState.save(); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index b6ad2c7a00..a35a984362 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -395,6 +395,30 @@ void __KernelStartIdleThreads() } } +bool __KernelSwitchOffThread(const char *reason) +{ + if (!reason) + reason = "switch off thread"; + + SceUID threadID = currentThread->GetUID(); + + if (threadID != threadIdleID[0] && threadID != threadIdleID[1]) + { + u32 error; + // Idle 0 chosen entirely arbitrarily. + Thread *t = kernelObjects.Get(threadIdleID[0], error); + if (t) + { + __KernelSwitchContext(t, reason); + return true; + } + else + ERROR_LOG(HLE, "Unable to switch to idle thread."); + } + + return false; +} + void __KernelIdle() { CoreTiming::Idle(); diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index eb99e239e4..913511fe65 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -175,6 +175,10 @@ void __KernelSwitchContext(Thread *target, const char *reason); bool __KernelExecutePendingMipsCalls(bool reschedAfter); void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg); +// Switch to an idle / non-user thread, if not already on one. +// Returns whether a switch occurred. +bool __KernelSwitchOffThread(const char *reason); + // A call into game code. These can be pending on a thread. // Similar to Callback-s (NOT CallbackInfos) in JPCSP. class Action;