Context switch involves switching a machine from executing one process to executing another even before the former is completed. This involves saving the state of all volatile data like registers, PTBR, BP, etc. (in other words the "context") and, then loading the context of a new process or starting a new process from scratch which will have its own context. This technique allows the machine to concurrently execute multiple processes.
eXpOS maintains a kernel stack for each application process. Before a context switch, the context of the outgoing process must be saved into its kernel stack. The previously saved context of the incoming process must be restored from the kernel stack of that process.
This document specifies how stack management has to be performed during a context switch. There are two situations that can result in a context switch:
1. The time slice of a process executing in the user mode expires and a timer interrupt is raised. The timer interrupt routine invokes the scheduler module(MOD_5) to perform a context switch.
2. While executing in the kernel mode (inside a system call or the exception handler), a process has to wait for some event to happen (ex: wait for a resource like disk, terminal etc) and hence voluntarily invokes the scheduler(MOD_5) to schedule itself out.
The Timer ISR saves the user context of the process from which it was entered, into the kernel stack of that process. (see Kernel Stack Management during Interrupts for more details). The Timer ISR then calls the scheduler module. The scheduler module determines which process must be run next, and changes the machine's stack to the kernel stack of the new processes. This stack is expected to contain the previously saved context of the new process. The scheduler is reponsible for resuming execution of the new process.
If the new process was scheduled out earlier by the timer interrupt, then the scheduler will return to the instruction in the timer interrupt after the call to the scheduler. When the timer ISR returns to the user mode, the new process will resume execution because the execution context restored by the timer ISR at the time of return to user mode will be from the kernel stack of the new process. More details will be explained below.
Note: We will write the Timer ISR in such a way that it does not use any registers. So, we need not store and restore any additional kernel level context inside the timer ISR before or after invoking the scheduler module.
In this case, the scheduler modules was invoked from some other kernel code - typically some blocking system call, exception handler etc. Here, it is the responsibility of the calling module/handler to save its context (registers in use) in its kernel stack before invoking the scheduler module. Later, when the scheduler returns to this handler/module, the handler/module should restore the context and resume execution. See the Kernel Stack management during module calls for more details.
In spite of the above convention, the ExpL compiler fails to save the value of BP register before making a system call. To solve this problem, a patch is added to the scheduler so that the scheduler saves the current value of BP register to the kernel stack of the process being scheduled out.
The scheduler module is responsible for performing the actual context switch. Context switch happens by a change of SP, PTBR and PTLR registers. We store these register values of the old process to its Process Table and restore SP, PTBR and PTLR values from the Process Table of the new process.
Important Note: The offset of SP register within the user area page will be stored in the KPTR field of the process table(and not the physical address of the kernel stack pointer). The value of the offset can be calculated by the fomula offset = SP – (512 * USER AREA PAGE NUMBER). The purpose of storing the offset (instead of the physical address) is to allow the OS to relocate the user area page to another physical memory page during swapping.
After switching the registers, the scheduler module executes the return instruction resulting in IP value being set from the top of the kernel stack of the new process (except for one special case which we will see below). This transfers control to the next instruction in the kernel handler/module in the new process.
*Note :
A process may invoke the scheduler for several reasons. As noted earlier as Case 1, one reason is that the time slice of the process is finished. Other possibilities (handled under Case 2) includes waiting for disk, terminal, semaphore, file etc. Before calling the scheduler a process must set the STATE field of the process table entry to indicate the correct reason
for invoking the scheduler. Note that the scheduler cannot set the STATE field as only the caller will know the cause.