mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-14 22:24:05 +00:00
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:
parent
c75f37fdb6
commit
35a38ac6b9
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user