Restore thread if there's no interrupt handler set.

If dispatch is disabled and we don't do this, it'll just hang, never
switching back to a thread that can re-enable dispatch.

Fixes #5172.
This commit is contained in:
Unknown W. Brackets 2014-01-21 22:47:18 -08:00
parent d6a2f52e47
commit 4da08f4f6e

View File

@ -328,35 +328,36 @@ void InterruptState::clear()
// Returns true if anything was executed.
bool __RunOnePendingInterrupt()
{
if (inInterrupt || !interruptsEnabled)
{
bool needsThreadReturn = false;
if (inInterrupt || !interruptsEnabled) {
// Already in an interrupt! We'll keep going when it's done.
return false;
}
// Can easily prioritize between different kinds of interrupts if necessary.
retry:
if (!pendingInterrupts.empty())
{
// 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.
SceUID savedThread = __KernelGetCurThread();
if (__KernelSwitchOffThread("interrupt"))
threadBeforeInterrupt = savedThread;
if (!pendingInterrupts.empty()) {
PendingInterrupt pend = pendingInterrupts.front();
IntrHandler* handler = intrHandlers[pend.intr];
if(handler == NULL)
{
if (handler == NULL) {
WARN_LOG(SCEINTC, "Ignoring interrupt");
pendingInterrupts.pop_front();
goto retry;
}
// 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.
SceUID savedThread = __KernelGetCurThread();
if (__KernelSwitchOffThread("interrupt")) {
threadBeforeInterrupt = savedThread;
needsThreadReturn = true;
}
intState.save();
inInterrupt = true;
if(!handler->run(pend)) {
if (!handler->run(pend)) {
pendingInterrupts.pop_front();
inInterrupt = false;
goto retry;
@ -364,9 +365,9 @@ retry:
currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress();
return true;
}
else
{
} else {
if (needsThreadReturn)
__KernelSwitchToThread(threadBeforeInterrupt, "left interrupt");
// DEBUG_LOG(SCEINTC, "No more interrupts!");
return false;
}