In this tutorial, we’ll learn about context switches.
Most modern operating systems have a process or task scheduler, which schedules the execution of various available tasks by allocating the CPU time. Furthermore, each process stores information about its state, which we call its context.
When it’s time for a running process to release the CPU, we need a robust and fail-safe way to remove the CPU from the currently running process and allocate it to one of the waiting processes. This means we have to save its state to execute it from that point at a later time.
Similarly, a switch happens when a thread within the running process yields the CPU to another thread.
2.1. Reasons for Context Switching
A context switch can occur mainly for three reasons:
The first case is when the time allocated to the currently running process or thread is over, and we need to free the CPU to give it to one of the waiting processes (or threads).
The second case is the invocation of a kernel function during program execution. For instance, sending a SIGKILL interrupt signal to the OS will free the CPU by killing the running process.
Finally, a higher-priority task can preempt the currently running one.
3. Context Switching
We can define a context switch as a system event in which the operating system or the OS removes the executing job from the CPU and allocates it to another task. It involves saving the context of the switched-out process (or thread) and loading the context of the one taking over. The OS ensures a switch is seamless, fast, and free from conflicts or dependency. Thus, context switching is vital for multitasking and user responsiveness.
The state contains the extended instruction pointer (EIP), the content of used general purpose registers (GPR), the specific segment registers, the control register (), the paging table entries, etc. As evident from this list, the context switch operation involves the read/write of a large amount of data, so it is one of the most costly OS operations.
3.2. Process Control Block
In most modern operating systems, we represent a process by a uniform data structure called the process control block or PCB. A PCB stores the context of a process: the user address space contents, the contents of hardware registers, and its related kernel data structures. So, the context of a process is the concatenation of its user-level, register, and system-level contexts.
A user-level context consists of the process text, process statistics, file and lock descriptors, data, user stack, and shared memory that occupy the process’s virtual address space. The system level contains the process table record, kernel stack, the mapping table from virtual memory to physical memory, etc. Finally, the register context contains the hardware registers for that process. It includes the program counter, process mode, stack pointer, and the data generated by the process during its execution.
On the other hand, when context-switching a thread, we need to store only their private data because they share a lot with other threads from the same process. So, switching them is easier and faster.
3.3. The Flow of Context Switching
Let’s understand the flow of context switching through an example:
Initially, we have task running. Let’s say its time quota expires or we receive an interruption. That triggers a context switch.
First, we save the context of . Then, we free the CPU from . Afterward, we load the context of another task and let it run.
4. Switching Methods
We can do context-switching using hardware and software.
4.1. Hardware Switching
In this method, the processor core includes a unique data segment called the task state segment or TSS.
A hardware switch is implemented as a jump instruction to the specified TSS descriptor in the system-level descriptor table. Although the hardware realizes most of the instructions, this method is slower than the software method. This is so because it saves almost all registers.
4.2. Software Switching
This is the dominant method of context switching. Here, the operating system uses kernel routines and data structures for saving and restoring the context.
This method offers us the advantage of speed and consistency. It copies only those registers the task will need once it gets the CPU again. It uses kernel routines and data structures that are fast and data-consistent.
In this article, we presented context switching in modern-day operating systems.
Each process has its context, which contains the data describing its state, such as program counters, CPU registers, and open file descriptors. In a context switch, the OS saves the context of the running process, detaches it from the CPU, and loads the context of a new process. This way, the new process starts executing. Once the old process gets its turn again, the OS loads its saved context and starts running on the CPU. We need efficient, fast, seamless context switching to support multiprocessing and low latency.