Merge pull request #194 from unknownbrackets/alarm

Ensure interrupts don't run on real threads
This commit is contained in:
Henrik Rydgård 2012-12-18 02:56:29 -08:00
commit b37b557173
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;