OS Notes
Understanding context switching in operating systems — what triggers it, the exact steps involved, performance overhead, hardware support, and how modern CPUs optimize context switches.
Introduction
Imagine a juggler keeping three balls in the air. At any moment, only one ball is in their hand (running). The others are in the air (ready). The juggler constantly catches one ball and throws another — this switching happens so fast that it looks like all three are being handled simultaneously. Context switching in an OS is the same principle — the CPU rapidly switches between processes, creating the illusion that all are running at the same time.
A context switch is the mechanism by which the operating system saves the state of a currently running process and loads the state of another process to run next. It is the fundamental operation that enables multitasking. Without context switching, the CPU could only run one process from start to finish before moving to the next.
What Triggers a Context Switch?
Context switches occur when:
- Time quantum expires — The timer interrupt fires in Round Robin scheduling
- Higher priority process arrives — Preemptive priority scheduling
- Process performs I/O — The running process blocks, a ready process takes over
- Process terminates — Another process must be scheduled
- System call — Some system calls require a switch to a kernel-mode process
- Interrupt — Hardware interrupt requires immediate attention
The Exact Steps of a Context Switch
When switching from Process A (running) to Process B (ready):
| │ ←── Interrupt ── | │ │ |
| │ 2. Update A's state | │ |
| │ Running | Ready │ |
| │ 4. Update B's state | │ |
| │ Ready | Running │ |
| │ │───────────────────── | │ |
Detailed Steps
// Simplified context switch implementation
void context_switch(PCB *old_process, PCB *new_process) {
// STEP 1: Save CPU state of current (old) process
old_process->program_counter = get_PC();
old_process->stack_pointer = get_SP();
save_all_registers(old_process->registers);
save_fpu_state(old_process->fpu_registers); // Floating point
// STEP 2: Save memory management state
old_process->page_table_base = get_CR3(); // x86 page table register
// STEP 3: Update process states
old_process->state = READY; // (or WAITING if it blocked)
new_process->state = RUNNING;
// STEP 4: Load new process's memory context
set_CR3(new_process->page_table_base); // Switch address space
flush_TLB(); // Translation Lookaside Buffer must be cleared
// STEP 5: Load CPU state of new process
restore_all_registers(new_process->registers);
restore_fpu_state(new_process->fpu_registers);
set_SP(new_process->stack_pointer);
// STEP 6: Jump to new process's program counter
jump_to(new_process->program_counter);
// We never return here — execution continues in new_process
}Context Switch Overhead
Context switching is pure overhead — during the switch, no useful user work is being done. The costs include:
Direct Costs (Time)
- Saving and restoring registers: ~1-2 microseconds on modern hardware
- Switching page tables: ~0.5 microseconds
- Flushing TLB entries: ~0.1-1 microseconds
- Total hardware cost: typically 1-10 microseconds
Indirect Costs (Cache Pollution)
The bigger cost is often invisible. When Process B starts running, the CPU cache is full of Process A's data. Process B experiences many cache misses until its own data is loaded. This "cold cache" effect can make the process run 10-1000x slower for a brief period after switching.
| Before switch | Cache full of A's data (warm cache) |
| After switch | Cache full of A's data (cold for B!) |
| After 100μs | Cache mostly has B's data (warm again) |
Performance Impact
| Scenario | Switch Time | Context switches/sec | Overhead |
|---|---|---|---|
| Linux, modern CPU | ~3-5 μs | 1000/sec | 0.3-0.5% |
| Heavy multitasking | ~3-5 μs | 10000/sec | 3-5% |
| Real-time system | ~1-2 μs | 100/sec | 0.01% |
| Threads (same process) | ~1-2 μs | 5000/sec | 0.5-1% |
Thread Context Switch vs Process Context Switch
Switching between threads within the same process is much cheaper than switching between different processes because threads share the same address space:
| Operation | Process Switch | Thread Switch |
|---|---|---|
| Save/restore registers | Yes | Yes |
| Switch page tables | Yes | No (same address space) |
| Flush TLB | Yes | No |
| Cache pollution | Severe | Minimal (shared memory) |
| Total time | 5-10 μs | 1-3 μs |
This is a major reason why multi-threaded programs can be more efficient than multi-process programs — context switches between their threads are much faster.
Hardware Support for Context Switching
Modern processors provide hardware support to make context switching faster:
- Hardware task switching (x86 TSS): Deprecated but available — CPU can switch tasks with a single instruction
- Tagged TLBs: Each TLB entry is tagged with a process ID, so the TLB does not need to be flushed entirely on switch
- ASID (Address Space ID): Similar to tagged TLBs — different address spaces coexist in the TLB
- Shadow register banks: Some architectures (ARM) have multiple register sets, making register save/restore nearly instant
Minimizing Context Switch Overhead
- Use threads instead of processes where possible (cheaper switch)
- Increase time quantum — Fewer switches but worse response time
- CPU affinity — Keep a process on the same core to preserve cache state
- Avoid unnecessary blocking — Non-blocking I/O prevents switches
Real-World Analogy
Context switching is like a chef working on multiple orders in a restaurant kitchen. To switch from preparing Order A to Order B, the chef must: note where they left off on Order A (save PC), put A's ingredients aside (save registers), clear the workspace (flush cache), get B's ingredients out (load registers), and read B's recipe from where they left off (load PC). The switching itself does not produce any food (overhead), but it allows one chef to serve multiple customers.
Key Takeaways
- A context switch saves one process's CPU state and loads another's, enabling multitasking
- Direct costs are typically 1-10 microseconds on modern hardware
- Indirect costs (cache pollution, TLB flush) often exceed direct costs
- Thread switches are much cheaper than process switches (no page table or TLB change)
- Modern hardware features (tagged TLBs, ASID) reduce switch overhead
- Context switch frequency is a tradeoff: more switches = better responsiveness but more overhead
- Minimizing switches through CPU affinity, larger quanta, and thread use improves performance
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Context Switching.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Operating Systems topic.
Search Terms
operating-systems, operating systems, operating, systems, process, management, context, switching
Related Operating Systems Topics