I have been trying to understand how context switching works in Linux Kernel. It appears to me that there is a situation (explained later) which results in no invocation of IRET instruction after the interrupt (I am sure that there is something that I am missing!). I am assuming that invocation of IRET after the interrupt is extremely necessary, since you can't get the same interrupt until you invoke IRET. I am only worried about uni-processor kernel running on x86 arch.
The situation that I think might result in the described behavior is as follows:
Process A running in kernel mode calls
schedule()voluntarily (for example while trying to acquire an already locked mutex).schedule()decides to perform a context switch to process B and hence callscontext_switch()context_switch()switches virtual memory from A to B by callingswitch_mm()context_switch()runs macroswitch_to()to switch stacks and actually change the running process from A to B. Note that process A is now stuck insideswitch_to()and the stack of process A looks like (stack growing downwards):
...
[mutex_lock()]
[schedule()]
[context_switch()] (Stack Top)
Process B starts running. At some later time, it receives a timer interrupt and the timer interrupt handler decides that process B needs a reschedule.
On return from timer interrupt (but before invoking IRET)
preempt_schedule_irq()is invoked.preempt_schedule_irq()callsschedule().schedule()decides to context switch to process A and callscontext_switch().context_switch()callsswitch_mm()to switch the virtual memory.context_switch()callsswitch_to()to switch stacks. At this point, stack of process B looks like following:
...
[IRET return frame]
[ret_from_interrupt()]
[preempt_schedule_irq()]
[schedule()]
[context_switch()] (Stack top)
Now process A is running with its stack resumed. Since, context_switch() function in A was not invoked due to a timer interrupt, process A does not call IRET and it continues execution of mutex_lock(). This scenario may lead to blocking of timer interrupt forever.
What am I missing here?