Skip to content

Context Switch and Timer Interrupts

tebrown edited this page Nov 28, 2012 · 6 revisions

Task switches on blocking processes that do not voluntarily yield the processor require an interrupt to unblock the process. The ARM does not provide a native timer, but one there is a DS802/804 timer peripheral that can be used to provide the timer we need. In theory, this should fire every 1 or 10 mS. When this timer fires, clkhandler() is called. clkhandler() will check if the sleep queue is not empty, and if it wakeup any sleeping process who's alarm has fired. Otherwise, it will issue call resched(). resched() will perform a ctxsw() if a higher priority thread needs to run.

ISSUES

IRQ_Routine() is the function that is called to handle the timer interrupt, and any other interrupt, really. This function looks in the VIC controller and determines what function to call. After the function returns, we restore our pre-interrupt context and go on our merry way. In the case of the timer interrupt, it calls clkhandler(). clkhandler() will in turn call resched() which in-turn calls ctxsw(). Now, we have switched to a new thread which may block until a new timer interrupt fires. This is where things go south. We haven't officially left the context of the first interrupt that fired. We cleared the interrupt bit but we never restored the LR, stack and all that other happy jazz we are supposed to do after we call our C-interrupt-handler. Now, when we get another interrupt, we use the SAME stack pointer we used in the first instance and blow away all that was good with that. We could make this smarter and increment the stack pointer, but we would need a LOT of stack if we have a lot of threads running, so that's not ideal. What we need is a way to force the ctxsw() to happen from the null thread, or we need to restore the interrupt context BEFORE we do the ctxsw().

Clone this wiki locally