// Returns true if anything was executed. bool __RunOnePendingInterrupt() { if (inInterrupt) { // Already in an interrupt! We'll keep going when it's done. return false; } // Can easily prioritize between different kinds of interrupts if necessary. if (pendingInterrupts.size()) { PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); intState.save(); pend.handler->copyArgsToCPU(pend); currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress(); inInterrupt = true; return true; } else { // DEBUG_LOG(HLE, "No more interrupts!"); return false; } }
void __KernelReturnFromInterrupt() { DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc); // This is what we just ran. PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); intrHandlers[pend.intr]->handleResult(pend); inInterrupt = false; // Restore context after running the interrupt. intState.restore(); // All should now be back to normal, including PC. // Alright, let's see if there's any more interrupts queued... if (!__RunOnePendingInterrupt()) { // Otherwise, we reschedule when dispatch was enabled, or switch back otherwise. if (__KernelIsDispatchEnabled()) __KernelReSchedule("return from interrupt"); else __KernelSwitchToThread(threadBeforeInterrupt, "return from interrupt"); } }
void __InterruptsInit() { interruptsEnabled = 1; inInterrupt = false; for(int i = 0; i < ARRAY_SIZE(intrHandlers); ++i) intrHandlers[i] = new IntrHandler(i); intState.clear(); }
void __KernelReturnFromInterrupt() { DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc); inInterrupt = false; // Restore context after running the interrupt. intState.restore(); // All should now be back to normal, including PC. // Alright, let's see if there's any more interrupts queued... if (!__RunOnePendingInterrupt()) { // Hmmm... //__KernelReSchedule("return from interrupt"); } }
void __InterruptsDoState(PointerWrap &p) { int numInterrupts = PSP_NUMBER_INTERRUPTS; p.Do(numInterrupts); if (numInterrupts != PSP_NUMBER_INTERRUPTS) { ERROR_LOG(HLE, "Savestate failure: wrong number of interrupts, can't load."); return; } intState.DoState(p); PendingInterrupt pi(0, 0); p.Do(pendingInterrupts, pi); p.Do(interruptsEnabled); p.Do(inInterrupt); p.DoMarker("sceKernelInterrupt"); }
// Returns true if anything was executed. bool __RunOnePendingInterrupt() { 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()) { PendingInterrupt pend = pendingInterrupts.front(); IntrHandler* handler = intrHandlers[pend.intr]; 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)) { pendingInterrupts.pop_front(); inInterrupt = false; goto retry; } currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress(); return true; } else { if (needsThreadReturn) __KernelSwitchToThread(threadBeforeInterrupt, "left interrupt"); // DEBUG_LOG(SCEINTC, "No more interrupts!"); return false; } }
void __KernelReturnFromInterrupt() { DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc); // This is what we just ran. PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); intrHandlers[pend.intr]->handleResult(pend); inInterrupt = false; // Restore context after running the interrupt. intState.restore(); // All should now be back to normal, including PC. // Alright, let's see if there's any more interrupts queued... if (!__RunOnePendingInterrupt()) __KernelReSchedule("return from interrupt"); }
void __InterruptsDoState(PointerWrap &p) { auto s = p.Section("sceKernelInterrupt", 1); if (!s) return; int numInterrupts = PSP_NUMBER_INTERRUPTS; p.Do(numInterrupts); if (numInterrupts != PSP_NUMBER_INTERRUPTS) { p.SetError(p.ERROR_FAILURE); ERROR_LOG(SCEINTC, "Savestate failure: wrong number of interrupts, can't load."); return; } intState.DoState(p); PendingInterrupt pi(0, 0); p.Do(pendingInterrupts, pi); p.Do(interruptsEnabled); p.Do(inInterrupt); p.Do(threadBeforeInterrupt); }
void __KernelReturnFromInterrupt() { DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc); inInterrupt = false; // This is what we just ran. PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); SubIntrHandler *handler = intrHandlers[pend.intr].get(pend.subintr); if (handler != NULL) handler->handleResult(currentMIPS->r[MIPS_REG_V0]); else ERROR_LOG(HLE, "Interrupt released itself? Should not happen."); // Restore context after running the interrupt. intState.restore(); // All should now be back to normal, including PC. // Alright, let's see if there's any more interrupts queued... if (!__RunOnePendingInterrupt()) __KernelReSchedule("return from interrupt"); }
// Returns true if anything was executed. bool __RunOnePendingInterrupt() { 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.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(); SubIntrHandler *handler = intrHandlers[pend.intr].get(pend.subintr); if (handler == NULL) { WARN_LOG(HLE, "Ignoring interrupt, already been released."); pendingInterrupts.pop_front(); goto retry; } intState.save(); handler->copyArgsToCPU(pend); currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress(); inInterrupt = true; return true; } else { // DEBUG_LOG(HLE, "No more interrupts!"); return false; } }
void __InterruptsInit() { interruptsEnabled = 1; inInterrupt = false; intState.clear(); }