Skip to content

CPU Scheduling

CPU scheduling is the mechanism by which the operating system decides which process in the ready queue gets to use the CPU next. Since only one process can run on a single CPU core at a time, the scheduler must make intelligent decisions to maximize performance and fairness. Scheduling is one of the most heavily studied and tested topics in operating systems courses and interviews.

Scheduling Criteria

Before comparing algorithms, we need to understand what “good scheduling” means. The OS tries to optimize several (often conflicting) criteria:

CriterionDefinitionGoal
CPU UtilizationPercentage of time the CPU is busyMaximize (ideally 40-90%)
ThroughputNumber of processes completed per unit timeMaximize
Turnaround TimeTotal time from process submission to completion (finish - arrival)Minimize
Waiting TimeTotal time a process spends in the ready queueMinimize
Response TimeTime from submission to first response (first scheduled - arrival)Minimize

Turnaround Time = Completion Time - Arrival Time

Waiting Time = Turnaround Time - Burst Time


Interactive Scheduler

Experiment with different CPU scheduling algorithms below. Add processes with custom arrival times, burst times, and priorities, then watch the Gantt chart build in real time.

CPU Scheduling Visualizer

First Come First Served (Non-preemptive)

PROCESS TABLE
ProcessArrivalBurst
P1
P2
P3
P4
P5
ACTIONS
SPEED
SlowFast

Configure processes above and click Run to visualize the scheduling algorithm.


Preemptive vs Non-Preemptive Scheduling

TypeDescriptionProsCons
Non-PreemptiveOnce a process gets the CPU, it runs until it voluntarily releases (finishes or blocks on I/O)Simple, no context-switch overhead during executionA long process can starve others
PreemptiveThe OS can forcibly take the CPU away from a running process (e.g., when a higher-priority process arrives or a time quantum expires)Better responsiveness, prevents monopolizationMore context switches, needs careful synchronization

First Come, First Served (FCFS)

The simplest scheduling algorithm. Processes are executed in the order they arrive in the ready queue. Non-preemptive.

How it works: Maintain a FIFO queue. When the CPU is free, pick the process at the front of the queue.

Example

Processes: P1 (burst 24), P2 (burst 3), P3 (burst 3). All arrive at time 0 in order P1, P2, P3.

Gantt Chart:
┌────────────────────────────┬─────┬─────┐
│ P1 │ P2 │ P3 │
└────────────────────────────┴─────┴─────┘
0 24 27 30
ProcessArrivalBurstCompletionTurnaroundWaiting
P102424240
P203272724
P303303027

Average Waiting Time = (0 + 24 + 27) / 3 = 17.0

Average Turnaround Time = (24 + 27 + 30) / 3 = 27.0

Pros and Cons

ProsCons
Very simple to implementSuffers from the convoy effect: short processes stuck behind long ones
No starvationPoor average waiting time
Fair in arrival orderNot suitable for interactive systems

Shortest Job First (SJF) — Non-Preemptive

Selects the process with the smallest burst time. Provably optimal for minimizing average waiting time among non-preemptive algorithms.

How it works: When the CPU is free, look at all processes in the ready queue and choose the one with the shortest burst time. If two processes have the same burst time, use FCFS to break ties.

Example

ProcessArrivalBurst
P106
P208
P307
P403
Gantt Chart:
┌─────┬──────────┬───────────┬────────────┐
│ P4 │ P1 │ P3 │ P2 │
└─────┴──────────┴───────────┴────────────┘
0 3 9 16 24
ProcessArrivalBurstCompletionTurnaroundWaiting
P403330
P106993
P30716169
P208242416

Average Waiting Time = (0 + 3 + 9 + 16) / 4 = 7.0

Average Turnaround Time = (3 + 9 + 16 + 24) / 4 = 13.0

Pros and Cons

ProsCons
Optimal average waiting time (non-preemptive)Requires knowing burst time in advance (often estimated)
Good throughputStarvation: long processes may never execute if short ones keep arriving

Shortest Remaining Time First (SRTF) — Preemptive SJF

The preemptive version of SJF. Whenever a new process arrives, the scheduler compares its burst time with the remaining time of the currently running process. If the new process has a shorter remaining time, it preempts the running process.

Example

ProcessArrivalBurst
P108
P214
P329
P435
Gantt Chart:
┌────┬──────────┬───────────┬────────────────┬───────────────────┐
│ P1 │ P2 │ P4 │ P1 │ P3 │
└────┴──────────┴───────────┴────────────────┴───────────────────┘
0 1 5 10 17 26

Step-by-step:

  • t=0: Only P1 available. P1 runs. Remaining: P1=8.
  • t=1: P2 arrives (burst=4). P1 remaining=7. Since 4 < 7, P2 preempts P1. Remaining: P1=7, P2=4.
  • t=2: P3 arrives (burst=9). P2 remaining=3. Since 3 < 7 < 9, P2 continues.
  • t=3: P4 arrives (burst=5). P2 remaining=2. Since 2 < 5, P2 continues.
  • t=5: P2 finishes. Ready: P1(7), P3(9), P4(5). P4 is shortest. P4 runs.
  • t=10: P4 finishes. Ready: P1(7), P3(9). P1 runs.
  • t=17: P1 finishes. P3 runs.
  • t=26: P3 finishes.
ProcessArrivalBurstCompletionTurnaroundWaiting
P10817179
P214540
P329262415
P4351072

Average Waiting Time = (9 + 0 + 15 + 2) / 4 = 6.5

Average Turnaround Time = (17 + 4 + 24 + 7) / 4 = 13.0


Round Robin (RR)

Each process gets a fixed time quantum (time slice). If a process does not finish within its quantum, it is preempted and placed at the back of the ready queue. Round Robin is the foundation of modern time-sharing systems.

How it works: Maintain a circular FIFO queue. Give each process at the front up to q time units. If it finishes, remove it. If not, move it to the back.

Example (Time Quantum = 4)

ProcessArrivalBurst
P105
P203
P308
Gantt Chart (q=4):
┌──────┬─────┬──────┬────┬──────┐
│ P1 │ P2 │ P3 │ P1 │ P3 │
└──────┴─────┴──────┴────┴──────┘
0 4 7 11 12 16

Step-by-step:

  • t=0-4: P1 runs for 4 (remaining 1). P1 goes to back.
  • t=4-7: P2 runs for 3 (finishes).
  • t=7-11: P3 runs for 4 (remaining 4). P3 goes to back.
  • t=11-12: P1 runs for 1 (finishes).
  • t=12-16: P3 runs for 4 (finishes).
ProcessArrivalBurstCompletionTurnaroundWaiting
P10512127
P203774
P30816168

Average Waiting Time = (7 + 4 + 8) / 3 = 6.33

Average Turnaround Time = (12 + 7 + 16) / 3 = 11.67

Choosing the Time Quantum

The time quantum q has a major impact on performance:

  • q too large (e.g., 100ms): Degenerates into FCFS. Poor response time.
  • q too small (e.g., 1ms): Excessive context switches. High overhead.
  • Rule of thumb: 80% of CPU bursts should be shorter than the time quantum. Typical values: 10-100ms.
Effect of Time Quantum:
q = infinity ───> Becomes FCFS
q = 100ms ───> Good balance for most systems
q = 10ms ───> Very responsive, moderate overhead
q = 1ms ───> Too many context switches (overhead > useful work)

Pros and Cons

ProsCons
Fair: every process gets equal CPU timeHigher average turnaround than SJF
Good response timePerformance depends heavily on time quantum
No starvationMore context switches than FCFS/SJF
Simple to implement

Priority Scheduling

Each process is assigned a priority number. The CPU is allocated to the process with the highest priority (lowest number = highest priority is the common convention, though this varies).

How it works: Always run the highest-priority ready process. Can be preemptive (a new higher-priority process preempts) or non-preemptive.

Example (Non-Preemptive, lower number = higher priority)

ProcessArrivalBurstPriority
P10103
P2011
P3024
P4015
P5052
Gantt Chart:
┌────┬───────────┬────────────────┬─────┬────┐
│ P2 │ P5 │ P1 │ P3 │ P4 │
└────┴───────────┴────────────────┴─────┴────┘
0 1 6 16 18 19
ProcessArrivalBurstPriorityCompletionTurnaroundWaiting
P2011110
P5052661
P1010316166
P3024181816
P4015191918

Average Waiting Time = (0 + 1 + 6 + 16 + 18) / 5 = 8.2

The Starvation Problem and Aging

Low-priority processes may starve (never execute) if higher-priority processes keep arriving. The solution is aging: gradually increase the priority of waiting processes over time.

Aging Example:
Process P_low starts with priority 50
Every 1 second in ready queue: priority += 1
After 30 seconds waiting: priority = 80 (high enough to run)

Pros and Cons

ProsCons
Important processes run firstStarvation of low-priority processes
Flexible priority assignmentPriority inversion (low-priority holds resource needed by high-priority)
Can model real-world importanceRequires aging to prevent starvation

Multilevel Queue Scheduling

Processes are permanently assigned to one of several queues, each with its own scheduling algorithm.

┌─────────────────────────────────────────────┐
│ System processes (highest priority) │ ──> Priority scheduling
├─────────────────────────────────────────────┤
│ Interactive processes │ ──> Round Robin (q=8)
├─────────────────────────────────────────────┤
│ Batch processes │ ──> FCFS
├─────────────────────────────────────────────┤
│ Student processes (lowest priority) │ ──> FCFS
└─────────────────────────────────────────────┘
Scheduling between queues: Fixed priority or time-slice
Example: System gets 40%, Interactive gets 40%, Batch gets 20%

Problem: Processes cannot move between queues. A process classified as “batch” stays batch forever, even if its behavior changes.


Multilevel Feedback Queue (MLFQ)

The most sophisticated and widely used scheduling algorithm in real-world operating systems (used by Linux, Windows, macOS in various forms). Processes can move between queues based on their observed behavior.

MLFQ Rules

  1. If Priority(A) > Priority(B), A runs.
  2. If Priority(A) = Priority(B), A and B run in Round Robin.
  3. A new process enters at the highest-priority queue.
  4. If a process uses up its entire time quantum, it is demoted (moved to a lower-priority queue).
  5. If a process gives up the CPU before its quantum expires (e.g., for I/O), it stays at the same level.
  6. Periodically, all processes are boosted to the highest-priority queue (prevents starvation).
Queue 0 (highest priority): RR with q=8ms
┌──────────────────────────────────────┐
│ New processes start here │
│ If process uses full quantum → Q1 │
│ If process blocks on I/O → stay Q0 │
└──────────────────────────────────────┘
│ (demotion)
v
Queue 1 (medium priority): RR with q=16ms
┌──────────────────────────────────────┐
│ Processes that used full quantum │
│ at Q0 run here with larger slice │
│ If process uses full quantum → Q2 │
└──────────────────────────────────────┘
│ (demotion)
v
Queue 2 (lowest priority): FCFS
┌──────────────────────────────────────┐
│ Long-running CPU-bound processes │
│ Get lowest priority but largest │
│ time slices │
└──────────────────────────────────────┘
↑ Priority Boost (periodically move all to Q0)

Why MLFQ Works Well

  • Interactive (I/O-bound) processes stay in the high-priority queue because they frequently give up the CPU before the quantum expires
  • CPU-bound processes naturally sink to lower queues where they get larger time slices (fewer context switches)
  • Priority boosting prevents starvation and adapts to changing process behavior

Algorithm Comparison

AlgorithmTypePreemptiveStarvationConvoy EffectOptimal Waiting Time
FCFSNon-preemptiveNoNoYesNo
SJFNon-preemptiveNoYesNoYes (non-preemptive)
SRTFPreemptiveYesYesNoYes (overall)
Round RobinPreemptiveYesNoNoNo
PriorityBothConfigurableYes (without aging)NoNo
Multilevel QueueBothConfigurableYesNoNo
MLFQPreemptiveYesNo (with boosting)NoApproximates SJF

Practice Problems

Problem 1: FCFS with Different Arrival Times

ProcessArrivalBurst
P105
P213
P328
P436

Solution:

Gantt Chart:
┌───────────┬─────────┬──────────────────┬────────────────┐
│ P1 │ P2 │ P3 │ P4 │
└───────────┴─────────┴──────────────────┴────────────────┘
0 5 8 16 22
ProcessArrivalBurstCompletionTurnaroundWaiting
P105550
P213874
P32816146
P436221913

Average Waiting Time = (0 + 4 + 6 + 13) / 4 = 5.75

Average Turnaround Time = (5 + 7 + 14 + 19) / 4 = 11.25


Problem 2: SJF (Non-Preemptive) with Different Arrival Times

ProcessArrivalBurst
P107
P224
P341
P454

Solution:

Gantt Chart:
┌─────────────────┬────┬──────────┬──────────┐
│ P1 │ P3 │ P2 │ P4 │
└─────────────────┴────┴──────────┴──────────┘
0 7 8 12 16

Step-by-step:

  • t=0: Only P1 is available. P1 runs (burst=7).
  • t=7: P1 finishes. Ready: P2(burst=4), P3(burst=1), P4(burst=4). Shortest is P3.
  • t=8: P3 finishes. Ready: P2(4), P4(4). FCFS tie-break: P2 arrived first.
  • t=12: P2 finishes. P4 runs.
  • t=16: Done.
ProcessArrivalBurstCompletionTurnaroundWaiting
P107770
P22412106
P341843
P45416117

Average Waiting Time = (0 + 6 + 3 + 7) / 4 = 4.0

Average Turnaround Time = (7 + 10 + 4 + 11) / 4 = 8.0


Problem 3: Round Robin (q=3)

ProcessArrivalBurst
P104
P206
P302

Solution:

Gantt Chart (q=3):
┌─────────┬─────────┬─────┬────┬─────────┐
│ P1 │ P2 │ P3 │ P1 │ P2 │
└─────────┴─────────┴─────┴────┴─────────┘
0 3 6 8 9 12

Step-by-step:

  • t=0-3: P1 runs for 3 (remaining 1). Queue: [P2, P3, P1].
  • t=3-6: P2 runs for 3 (remaining 3). Queue: [P3, P1, P2].
  • t=6-8: P3 runs for 2 (finishes). Queue: [P1, P2].
  • t=8-9: P1 runs for 1 (finishes). Queue: [P2].
  • t=9-12: P2 runs for 3 (finishes).
ProcessArrivalBurstCompletionTurnaroundWaiting
P104995
P20612126
P302886

Average Waiting Time = (5 + 6 + 6) / 3 = 5.67

Average Turnaround Time = (9 + 12 + 8) / 3 = 9.67


Problem 4: SRTF with Arrivals

ProcessArrivalBurst
P106
P222
P344

Solution:

Gantt Chart:
┌─────┬─────┬──────────┬──────────┐
│ P1 │ P2 │ P1 │ P3 │
└─────┴─────┴──────────┴──────────┘
0 2 4 8 12

Step-by-step:

  • t=0: P1 starts (remaining=6).
  • t=2: P2 arrives (burst=2). P1 remaining=4. Since 2 < 4, P2 preempts P1.
  • t=4: P2 finishes. P3 arrives (burst=4). P1 remaining=4. Tie: FCFS favors P1. P1 runs.
  • t=8: P1 finishes. P3 runs.
  • t=12: P3 finishes.
ProcessArrivalBurstCompletionTurnaroundWaiting
P106882
P222420
P3441284

Average Waiting Time = (2 + 0 + 4) / 3 = 2.0

Average Turnaround Time = (8 + 2 + 8) / 3 = 6.0


Real-World Scheduling

Linux: Completely Fair Scheduler (CFS)

Linux uses the CFS, which models an ideal multitasking CPU where each process gets an equal fraction of CPU time. Key ideas:

  • Uses a red-black tree sorted by “virtual runtime” (vruntime)
  • The process with the smallest vruntime is scheduled next
  • Higher-priority processes accumulate vruntime more slowly, so they get more CPU time
  • No fixed time quantum — the time slice adapts based on the number of runnable processes

Windows: Priority-Based Preemptive Scheduling

Windows uses a multilevel feedback queue with 32 priority levels (0-31):

  • Levels 16-31: Real-time priorities
  • Levels 1-15: Variable priorities (dynamically adjusted based on behavior)
  • Level 0: System idle thread

Key Takeaways

  1. FCFS is simple but suffers from the convoy effect — short processes wait behind long ones
  2. SJF/SRTF gives optimal average waiting time but requires knowing burst times and can cause starvation
  3. Round Robin is fair and has good response time; its performance depends heavily on the time quantum
  4. Priority Scheduling serves important processes first but needs aging to prevent starvation
  5. MLFQ is the practical choice — it approximates SJF behavior without requiring burst time estimates
  6. No single algorithm is best for all scenarios; real-world schedulers combine multiple approaches
  7. When solving scheduling problems: draw the Gantt chart first, then calculate completion, turnaround, and waiting times

Next Steps