Page 1 of 1

Context switch within Interrupt Service Routine

Posted: Tue Jul 22, 2014 9:43 pm
by xnr
I'm currently porting ChibiOS 2.6.4 to a new platform. But I think this question is more general os related and port independent.

(This paragraph may be skipped.)
After I managed to implement port_switch(), I ran the TestThread. All tests until delayed threading passed. I figured out I must have missed enabling interrupts in PORT_IRQ_EPILOGUE(). Mutex priority inversion was the next test to fail. It was locked inside the loop of test_cpu_pulse(). I thought must be a missing interrupt enabling again, so for test purposes I directly inserted the according code right before the loop. But nothing happened. I figured out that no new timer interrupts were taking place because the old interrupt handler didn't return.

This brings me to my actual question: What should happen if chSysSwitch() is called from withing an interrupt handler?

Let me explain my problem. Assume there are two threads with same priority and TIME_QUANTUM is > 0 (so round robin scheduling is enabled). Thread A is currently running. A timer interrupt occures, chSysTimerHandler is called. In the IRQ_PORT_EPILOGUE doReschedule functions switch from thread A to thread B. Thread B does its thing, e.g. while(1);. No other interrupts will occure because the Interrupt Service Routine didn't return yet.

Re: Context switch within Interrupt Service Routine

Posted: Tue Jul 22, 2014 10:06 pm
by Giovanni
It depends on the architecture, does your CPU have a dedicated stack for IRQs? if so you should only switch after the IRQ stack has been emptied and the ISR has returned (see all the tricks in the ARMCMx port, it switches after the ISR return by using a fake return frame).

If your CPU has a single stack then it is much simples, just follow the lines of the MSP or AVR ports.

Note that after the switch, it is guaranteed that the switched-in thread re-enables the interrupt.

It is a good idea to have the state checker enabled while testing, it could reveal something.

Giovanni

Re: Context switch within Interrupt Service Routine

Posted: Tue Jul 22, 2014 10:22 pm
by xnr
The CPU has one stack and I also tried to follow the MSP430 port. And before the Interrupt Service Routine is called all registers are saved (including link register). I still don't see how the Interrupt Service Routine should return after thread B switched in.

Re: Context switch within Interrupt Service Routine

Posted: Wed Jul 23, 2014 8:06 am
by Giovanni
If you do the context switch from *within* the ISR then it is the thread B that re-enables the interrupts and continues the execution, the ISR returns when thread A is executed again.

Of course this assumes that re-enabling interrupts is sufficient to exit the ISR state without having to execute a dedicated instruction.

If this assumption is not true then you should follow the ARMCMx model where the switch is done after the ISR return.

Giovanni

Re: Context switch within Interrupt Service Routine

Posted: Wed Jul 23, 2014 9:13 am
by xnr
Giovanni wrote:If you do the context switch from *within* the ISR then it is the thread B that re-enables the interrupts and continues the execution, the ISR returns when thread A is executed again.

Yes, this is what I observed.
Giovanni wrote:Of course this assumes that re-enabling interrupts is sufficient to exit the ISR state without having to execute a dedicated instruction.

Unfortunately, re-enabling isn't sufficient. ISR has to return, otherwise the Interrupt Controller states that the (Timer) Interrupt is still In-Service and blocks all other succeeding (Timer) Interrupts.

Thanks a lot for your great support! :)