Abstract

The CPU Scheduler (or Dispatcher) multiplexes physical CPU cores among active threads to create the processing illusion of dedicated execution. By strictly decoupling Policy (decision logic selecting the next thread) from Mechanism (saving/restoring registers), the kernel can optimize execution for specific performance metrics—such as Turnaround Time, Response Time, and CPU Utilization.

  • Category: OS Kernel Scheduling Principles
  • Core Invariant: Policy decides what thread runs; Mechanism handles how execution switches.
  • Key Trade-off: High throughput vs. low interactive response latency.

1. Policy vs. Mechanism

CPU virtualization relies on a strict separation between low-level mechanism and high-level policy:

  • Mechanism (The “How”): System infrastructure routines that perform context switches, manipulate state queues, and handle hardware timer interrupts.
  • Policy (The “What”): Algorithmic rules that select which runnable thread to dispatch next and determine its execution time slice.
void yield() {
    thread_t old_thread = current_thread;
    
    current_thread = get_next_thread();         // POLICY: Selects target thread
    
    append_to_queue(ready_queue, old_thread);
    context_switch(old_thread, current_thread);   // MECHANISM: Assembly register swap
    return;
}

2. When Does the Scheduler Run?

The CPU Scheduler is invoked whenever execution control returns to the kernel through an event:

  1. Running Waiting: A thread issues a blocking I/O system call (e.g., read()) or waits on a synchronization primitive.
  2. Running Ready: A hardware timer interrupt fires, preempting the active thread.
  3. Waiting Ready: An external hardware I/O interrupt completes, unblocking a thread.
  4. Termination: A thread exits explicitly (exit()) or encounters an unhandled fault.


3. Core Scheduling Metrics

Schedulers are evaluated against quantitative mathematical performance metrics:

1. Turnaround Time ()

The total time elapsed from job arrival to complete execution:

2. Response Time ()

The time elapsed from job arrival until it first begins executing on a CPU core:

3. Throughput

The number of completed jobs executed per unit of time (e.g., jobs/sec).

4. Overhead

The fraction of CPU execution time lost to non-productive management tasks (context switching, queue manipulation, schedule selection).

5. CPU Utilization

The fraction of total elapsed time the system spends performing useful application work:


4. Workload Goals & Application Profiles

Schedulers optimize for different metrics depending on the target workload profile:

flowchart TD
    TITLE["<b>Application Profiles</b>"]
        
    B_NODE["<b>Batch Workloads</b><br/><i>(Machine Learning, Simulations)</i><br/><br/>• Primary Goal: Maximize Throughput<br/>• Secondary Goal: Minimize Turnaround Time"]

    I_NODE["<b>Interactive Workloads</b><br/><i>(Browsers, Video Calls, IDEs)</i><br/><br/>• Primary Goal: Minimize Response Time<br/>• Secondary Goal: Predictable Latency"]

    TITLE --> B_NODE
    TITLE --> I_NODE

    classDef cellStyle font-size:15px,padding:12px;
    class TITLE,B_NODE,I_NODE cellStyle

Starvation

Starvation is an undesirable condition where a runnable thread is indefinitely denied access to a resource (CPU time or locks) because higher-priority tasks continuously monopolize execution.

Starvation vs. Deadlock

  • Deadlock: A set of threads is stuck in a closed dependency loop where no progress is possible.
  • Starvation: High-priority threads continue making forward progress, while low-priority threads are starved of CPU time.

5. Context Switch Overhead & CPU Utilization Math

Context switches do not perform useful application work. A typical scheduling quantum is , while a typical hardware context switch takes .

Case 1: CPU-Bound Workload ( Quantum, Overhead)

Three CPU-bound jobs run for their entire allocated quantum:

Case 2: I/O-Bound Workload ( CPU Burst, Overhead)

Three I/O-bound jobs execute for only before issuing an I/O request and yielding:


Related Notes