Esempio n. 1
0
// 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;
	}
}
Esempio n. 2
0
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");
    }
}
Esempio n. 3
0
void __InterruptsInit()
{
	interruptsEnabled = 1;
	inInterrupt = false;
	for(int i = 0; i < ARRAY_SIZE(intrHandlers); ++i)
		intrHandlers[i] = new IntrHandler(i);
	intState.clear();
}
Esempio n. 4
0
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");
	}
}
Esempio n. 5
0
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;
	}
}
Esempio n. 7
0
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);
}
Esempio n. 9
0
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");
}
Esempio n. 10
0
// 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;
	}
}
Esempio n. 11
0
void __InterruptsInit()
{
	interruptsEnabled = 1;
	inInterrupt = false;
	intState.clear();
}