Why multiplexing is necessary
With one CPU and N processes, only one runs at a time. Time-sharing gives each process short slices so all make progress. Context switching saves the outgoing process's registers, stack pointer, and program counter, then restores the incoming process's — the mechanical cost behind scheduler decisions.
Process states and the run queue
[New] → [Ready] ⇄ [Running] → [Terminated]
↑ ↓
└── [Blocked] (I/O, lock, sleep)
The run queue holds ready processes. On timer interrupt, the scheduler may preempt the running process (move it to Ready) and pick another. Involuntary preemption is what makes a single-core machine feel concurrent.
What a context switch costs
| Cost component | Why it matters |
|---|---|
| Register save/restore | ~1–10 µs baseline |
| TLB flush / shootdown | Cache-cold memory accesses after switch |
| Cache pollution | New process evicts warm lines |
| Scheduler bookkeeping | Run-queue locks under contention |
On a loaded 64-core host, scheduler lock contention can dominate — not just the switch itself.
Scheduling metrics
- Turnaround time — total time from submit to complete (batch workloads).
- Response time — time until first output (interactive).
- Fairness — no process starves indefinitely.
- Tail latency — p99 scheduler delay under load (production SLO).
Senior-level signal
Processes in D state (uninterruptible sleep) inflate load average but aren't using CPU — uptime looks scary while the real problem is stuck NFS or failing disk. Don't scale out replicas to fix a D-state pile-up.
Where this goes next
Scheduling Policies & MLFQ covers the algorithms that decide who leaves the run queue next — FIFO, Round Robin, and the feedback queue behind Linux CFS intuition.
Further Reading
Hands-On Tasks (Optional)
Low-setup exercises on your local machine. No autograding — the goal is to build intuition, not pass a test.
- Inspect process states with ps15m
Run `ps aux` and identify processes in R (running), S (sleeping), D (uninterruptible I/O), Z (zombie). Run `ps -eLo pid,tid,stat,comm | head -20` on Linux to see per-thread state.