Ensure interrupts don't run on real threads.

If a thread waits on a sema, and an interrupt (such as an alarm) happens,
and the interrupt signals or deletes the sema, it needs to return the
value correctly.

For callbacks, it's injected, since they run on thread.  But interrupts
aren't supposed to run on thread anyway, so this switches to idle.
This commit is contained in:
Unknown W. Brackets 2012-12-18 00:58:46 -08:00
parent c75f37fdb6
commit 35a38ac6b9
3 changed files with 32 additions and 0 deletions

View File

@ -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();

View File

@ -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<Thread>(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();

View File

@ -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;