Context Switching

Subpage of Operating Systems

Diving deep into the design and structure of Operating Systems.

To allow multiplexing to happen, there needs to be a point where a CPU goes from executing one thread to executing another thread.

Let's break down the precise steps:

  1. Interrupt or system call – The currently running process either voluntarily yields (e.g., waits for I/O) or an interrupt (e.g., timer interrupt) forces the CPU to jump into the kernel.
  2. Save current process state – The kernel saves the current process’s program counter, registers, and other volatile state into its PCB.
  3. Switch to the scheduler – The kernel runs the scheduler code to choose the next process from the ready queue.
  4. Load next process state – The kernel loads the saved state from the chosen process’s PCB into the CPU registers and program counter.
  5. Return to user mode – The CPU resumes execution of the new process at the point where it was previously stopped.

The context switch is pure overhead. During a context switch, no useful user work is done. This is why there is a trade-off between context switching time and "real stuff" execution time. A typical context switch on modern hardware can take a few microseconds (saving/restoring ~100–1000 bytes of registers + flushing pipeline). Frequent switches reduce responsiveness but waste CPU time. Infrequent switches can cause unfairness or high latency.

The rule of thumb – less than 10% of CPU time on context switching – is widely used in practice. If you measure 20% or more, the scheduler is either too aggressive (too small time slices) or there are too many active processes competing.

Blocking I/O

One of the reasons why there is context switching is blocking I/O. Let’s expand the sequence:

  1. A thread executes a system call like read(fd, buffer, size).
  2. The CPU transitions from user mode to kernel mode (via syscall or int instruction). The kernel now runs on behalf of that thread.
  3. The kernel initiates the I/O request (e.g., sends a command to the disk driver). The I/O will take milliseconds to complete.
  4. Instead of busy-waiting, the kernel changes the thread’s state from RUNNING to WAITING (blocked on I/O). It removes the thread from the ready queue.
  5. The kernel then calls the scheduler to choose another thread to run – this is the “switch while we wait”.
  6. When the I/O completes, a hardware interrupt occurs (see Part 7). The interrupt handler marks the waiting thread as READY and puts it back in the ready queue.
  7. Eventually, the scheduler will resume the thread.

The key is that the kernel proactively switches away when it knows the thread cannot proceed. This is a form of Preemptive Multitasking, but enforced by the kernel – the thread has no choice.

/ Continue

Follow the technical trail.

Use the dense notes as the source material, then move through the guided route, writing, or project proof when you want a cleaner entry point.