CEUC301 · Unit 2 of 9

CPU Scheduling &
Performance Evaluation

Chapter 1 established that switching costs something and that a kernel-level thread is an independent, schedulable thing. This chapter answers the question that sets up: when several of those things all want the one CPU at once, which one runs next — and what does "best" even mean when different answers are best for different people?

Colour contract Linux — primary OS Windows — secondary OS process-level — a whole process thread-level — one thread of WriteWell

The spine, expanded. WriteWell's T_ui and T_save are back — but a CPU scheduler is only interesting when more than one thing wants the CPU, so this chapter gives them company: at this same instant, three more independent, kernel-visible entities are sitting in the ready queue on the same single core. B_sync is a browser process syncing a page in the background. P_audio is a music player that just needs to refill a tiny playback buffer before it runs dry. P_backup is a cloud-backup process indexing files — long, patient, CPU-bound work with nowhere urgent to be. Two threads of one process, three separate processes, one CPU, one ready queue: exactly the mix Chapter 1's Section 1.5 said the scheduler treats identically.

2.1 · FOUNDATIONS

Scheduling Metrics & Workload Characterization

Before comparing algorithms, you need numbers to compare them with.

Five things want the CPU right now: T_ui, B_sync, P_audio, T_save, P_backup. Ask "which scheduling order is fastest?" and the honest answer is: fastest for whom? P_audio wants an answer in the next instant or its audio glitches. P_backup doesn't care when it finishes, only that it eventually does. "Best" isn't one thing here — which is exactly why this section exists before Section 2.2 compares five different answers to the same question.

What a scheduler knows about each job

Every scheduling decision is made from the same small set of facts about each waiting job:

  • Arrival Time (AT) — when the job entered the ready queue.
  • Burst Time (BT) — how long it needs the CPU. Real jobs alternate CPU bursts with I/O bursts (Chapter 1's T_save is the example: a short CPU burst to compute a diff, then an I/O burst while the disk write completes) — a scheduling algorithm only ever sees the CPU side of that alternation.
  • Priority — a number expressing how urgent a job is, where relevant.

From those facts alone, every one of this chapter's algorithms decides who runs next. The difference between them is entirely in the rule for choosing — never in what they're allowed to know.

The metrics, formally

Per-job metrics, computed once a job finishes Completion Time (CT) = the instant the job finishes (read off the schedule) Turnaround Time (TAT) = CT − AT (arrival to finish, total) Waiting Time (WT) = TAT − BT (TAT minus the work itself) Response Time (RT) = (time of FIRST CPU allocation) − AT (arrival to first run, not finish)
System-wide metrics CPU Utilization = (busy time ÷ total elapsed time) × 100% Throughput = (jobs completed) ÷ (total elapsed time)
Pitfall

Turnaround Time and Waiting Time are confused constantly, and it costs marks. TAT includes the burst time; WT does not. WT is always TAT − BT — if your waiting time comes out larger than your turnaround time, you've swapped them.

Worked example: reading the metrics off one schedule

Run the five jobs in arrival order — First-Come-First-Served, the simplest possible rule — and the metrics above stop being formulas and become a table.

Figure 1 · one schedule, every metric

FCFS: T_ui, B_sync, P_audio, T_save, P_backup, in arrival order
reading example
0 5 10 15 20 25 T_ui B_sync P_audio T_save P_backup
Reading the figure: violet blocks are threads of WriteWell (T_ui, T_save); amber blocks are separate processes. Colour here means exactly what it meant in Chapter 1 — the scheduler doesn't care about the difference, but it's worth seeing that it doesn't.
Every metric, computed from the Gantt chart above
JobATBTCT TATWT
T_ui04440
B_sync161093
P_audio211198
T_save3516138
P_backup49252112
average11.206.20

Take P_audio as the worked line: it arrives at AT=2 needing only BT=1 unit of CPU, but T_ui and B_sync are already ahead of it in arrival order, so it doesn't run until t=10 and finishes at CT=11. TAT = 11−2 = 9. WT = 9−1 = 8: it waited eight times longer than the work it actually needed. Since nothing preempts anything under FCFS, response time and waiting time are identical for every job here — that stops being true the moment Section 2.2 introduces preemption, which is exactly why RT and WT are tracked separately from the start.

CPU utilization and throughput, made concrete

In this particular schedule the CPU is never idle — all five jobs have arrived by t=4, and something is always ready to run — so utilization is a perfect 25⁄25 = 100%, and throughput is 5 jobs in 25 time units, or one job roughly every 5 units. Utilization only gets interesting when there are gaps: if T_ui instead arrived at t=2 with nothing else ready before it, the CPU would sit idle for 2 units first, and utilization would drop to 25⁄27 ≈ 92.6% — the same total work, spread over a longer wall-clock span.

Practice 2.1

  1. A job has AT=3, and under some schedule it finishes at CT=15 having needed BT=7 units of CPU. Compute its TAT and WT.
    Show solution

    TAT = CT − AT = 15 − 3 = 12. WT = TAT − BT = 12 − 7 = 5.

  2. Variation. Under a preemptive algorithm, that same job is first given the CPU at t=6, then finishes at CT=15 as before. What is its Response Time, and is it the same number as its Waiting Time?
    Show solution

    RT = (first allocation) − AT = 6 − 3 = 3. This is not the same as WT (5) — RT only counts the wait until the job first starts running, while WT counts every unit spent waiting across the job's entire lifetime, including any time spent waiting again after being preempted. RT ≤ WT always, and under a non-preemptive algorithm they're equal, exactly as seen for every job in the FCFS worked example above.

  3. Interpretation. A system reports 100% CPU utilization all day. Does that mean the scheduler is doing a good job?
    Show solution

    Not necessarily — 100% utilization only says the CPU is never idle, which a badly-chosen algorithm can achieve just as easily as a good one (FCFS hit 100% in the worked example above while still making P_audio wait 8× its own burst time). Utilization measures whether the CPU is busy, not whether it's busy doing the right thing first — that's what waiting time, turnaround time, and response time are for.

  4. Synthesis. Explain why a scheduling algorithm can only ever use AT, BT, and priority to make its decision — connecting this back to Chapter 1's PCB/TCB fields.
    Show solution

    Those three facts are what actually gets recorded per schedulable entity: arrival is implicit in when its control block was created or re-queued, burst time is estimated or tracked via prior CPU usage in the TCB/task_struct's scheduling fields, and priority is a field the PCB or TCB stores directly (Chapter 1, Section 1.3). A scheduler can't act on information that isn't in some control block somewhere — which is exactly why "we don't know the burst time in advance" (Section 2.2) is a real, structural limitation and not just a textbook caveat.

2.2 · ALGORITHMS

CPU Scheduling Algorithms

Five different answers to "who runs next," run on the same five jobs.

Every algorithm below sees the exact same ready queue from the hero and Section 2.1: T_ui, B_sync, P_audio, T_save, P_backup, with the same arrival times and burst times. Only the rule for choosing changes. Watching one dataset produce five different schedules is the fastest way to see what each rule actually optimises for — and what it costs to get there.

First-Come, First-Served (FCFS)

Rule: whoever arrives first runs first, to completion. No cutting, ever — a single checkout line. Non-preemptive. Section 2.1 already walked this one in full: average waiting time 6.20, and P_audio — a job that only needed 1 unit of CPU — waited 8 units for it.

Pitfall — the convoy effect

A short job stuck behind long ones is called the convoy effect: a fast car stuck behind a truck on a one-lane road. It's the single biggest reason FCFS is rarely used alone in a real scheduler, and "explain the convoy effect, with an example" is a near-guaranteed exam question.

Shortest Job First (SJF) — non-preemptive

Rule: among the jobs currently waiting, run whichever has the smallest total burst time — but once started, let it run to completion regardless of what arrives afterward. Non-preemptive. On the spine data, SJF drops average waiting time from FCFS's 6.20 to 5.00: P_audio still has to wait for T_ui to finish (SJF can't interrupt it), but then jumps ahead of the much longer B_sync and T_save.

Pitfall

SJF needs to know each job's burst time before running it — which, for a genuinely new program, is impossible to know exactly. Real schedulers that use SJF-like ideas predict the next burst from a job's recent history (commonly an exponentially-weighted average of past bursts) rather than knowing it outright. And like every "run the shortest thing" rule, SJF can starve a long job indefinitely if short jobs keep arriving — exactly the same risk Priority scheduling has, below.

Shortest Remaining Time First (SRTF) — preemptive SJF

Rule: the same "shortest wins" idea, but re-decided at every arrival: if a newly-arrived job needs less time than whatever is currently running has left, the new job preempts it. Preemptive. This is where the dataset actually shows a preemption happen: T_ui starts at t=0 needing 4 units total. At t=2, with 2 units of T_ui left, P_audio arrives needing only 1 — strictly less — and takes the CPU. T_ui resumes at t=3 and finishes its last 2 units at t=5. Ties in SRTF are broken by earliest arrival, and if still tied, by name — the convention this chapter uses throughout, since real textbooks aren't consistent about it.

Average waiting time drops again, to 4.80 — the best of every algorithm in this chapter. This isn't a coincidence of this dataset: SRTF is provably optimal for minimising average waiting time among all scheduling algorithms, for a fixed set of arrival and burst times. The intuition: any time a longer job runs while a shorter one waits, that shorter job's wait could only have been reduced by running it first, and SRTF always makes exactly that choice, continuously.

Pitfall

Optimal on paper costs more than SJF in two real ways: it needs to know remaining time continuously, an even harder prediction problem than SJF's already-unrealistic one, and every preemption is a genuine context switch, paying the real microsecond cost Chapter 1's Section 1.4 measured. Starvation risk is also worse than plain SJF: a long job can be preempted again and again, indefinitely, if short jobs keep arriving.

Round Robin (RR)

Rule: every job gets a fixed slice of CPU time — a quantum (here, q=3) — and if it isn't finished when the quantum ends, it goes to the back of the ready queue. Preemptive, but by the clock rather than by burst length. Convention used throughout this chapter: if a job's quantum expires at the exact instant a new job arrives, the new arrival is placed in the ready queue before the just-preempted job re-joins it.

RR is the one algorithm here that makes average waiting time worse, not better — 8.80, the highest of all five, because every job now waits behind partial slices of every other job instead of running straight through. What RR buys instead is response time: 3.40, the best of all five, because no job ever waits more than one quantum-length's worth of other jobs before its first turn.

Callback to 1.4 — what those nine switches actually cost

This RR schedule makes 8 genuine context switches (a ninth Gantt boundary is P_backup resuming itself with nothing else in the queue — no real scheduler pays a switch cost to keep running the job that's already running). At Chapter 1's measured 1.8 µs per thread switch, that's 8 × 1.8 = 14.4 µs of real overhead. If these Gantt units are milliseconds, the whole 25-unit schedule takes 25,000 µs — so the switching overhead here is 14.4 ÷ 25,000 ≈ 0.058% of the total. Section 1.4's lesson holds exactly: at a millisecond-scale quantum, this cost is a rounding error. Shrink the quantum toward microseconds instead of milliseconds, and it stops being one.

Pitfall — the quantum has no free lunch

Too short a quantum and the CPU spends more time context-switching than working (Section 1.4, again). Too long a quantum and RR quietly degenerates into FCFS — once the quantum exceeds every job's burst time, nothing ever gets preempted, and RR's whole point disappears.

Priority Scheduling — non-preemptive

Rule: the highest-priority ready job runs next, to completion. This chapter uses lower number = higher priority throughout (matching Linux's nice value convention from Chapter 1). A preemptive variant also exists — a higher-priority arrival interrupts whatever is running — but isn't worked here.

With P_audio at priority 1 (an audio glitch is worse than a delayed sync) and P_backup at priority 5 (a backup job has nowhere urgent to be), average waiting time comes out to 5.20 — close to SJF's 5.00, because on this dataset priority order happens to roughly track burst-time order. That's a coincidence of these particular numbers, not a general property: priority and burst time measure completely different things.

Pitfall — starvation, and the fix

If high-priority jobs keep arriving, a low-priority job can wait forever — not just a long time, literally forever. The standard fix is aging: gradually raise a job's priority the longer it waits, so eventually it out-ranks everything else. Concretely: aging P_backup by one priority level for every 5 units it spends waiting takes 4 promotions — 5→4→3→2→1 — so after 20 units of continuous waiting, it would out-rank even P_audio. Aging doesn't eliminate the wait; it guarantees it's bounded.

Figure 2 · the same five jobs, five rules

Pick an algorithm
click to switch
0 5 10 15 20 25 T_ui B_sync P_audio T_save P_backup
Per-job metrics for the selected algorithm
JobATBTCT TATWTRT
All five algorithms, side by side
Algorithmavg TATavg WTavg RT
FCFS11.206.206.20
SJF (non-preemptive)10.005.005.00
SRTF (preemptive)9.804.804.60
Round Robin (q=3)13.808.803.40
Priority (non-preemptive)10.205.205.20

No row wins on every column, and that's the point of this whole section: SRTF wins on turnaround and waiting time by provable construction, RR wins on response time by design, and both wins come at a cost the other pays. "Which algorithm is best" is only ever answerable once you've said best by which metric — the exact question Section 2.1 opened with.

Practice 2.2

  1. Using the spine dataset, verify by hand that SJF's schedule gives T_save a waiting time of 2, then check your answer against Figure 2.
    Show solution

    Under SJF, order is T_ui(0-4), P_audio(4-5), T_save(5-10), B_sync(10-16), P_backup(16-25). T_save: CT=10, AT=3, BT=5. TAT = 10−3 = 7. WT = 7−5 = 2. Matches Figure 2's SJF table.

  2. Variation. If P_backup's burst time were 3 instead of 9 (everything else unchanged), would SRTF's schedule change at all before t=4? Why or why not?
    Show solution

    No. P_backup doesn't arrive until t=4, and SRTF's decisions before t=4 only depend on jobs that have already arrived (T_ui, B_sync, P_audio, T_save) and their remaining times — none of which involve P_backup at all. A job's own burst time can never affect the schedule before that job has arrived; this is worth checking precisely because it's easy to assume changing one number ripples backward through a Gantt chart, and it never does.

  3. Interpretation. A report claims "we switched from FCFS to Round Robin and average turnaround time got worse." Is that evidence RR was implemented incorrectly?
    Show solution

    No — this chapter's own numbers show exactly that pattern (FCFS avg TAT 11.20 vs. RR's 13.80). RR trades average turnaround and waiting time for better response time and fairness; a worse average TAT after switching to RR is the expected, documented trade-off, not a bug. The right follow-up question is whether response time improved to justify it — which, here, it did (6.20 → 3.40).

  4. Synthesis. P_audio has the highest priority (1) and also the shortest burst time (1) in this dataset. Design a small variation to the dataset where Priority scheduling and SJF would clearly disagree about which job runs first.
    Show solution

    Give P_backup priority 1 instead of 5, keeping its burst time at 9 (the longest in the set). SJF would still run it last (longest remaining burst); Priority scheduling would now run it first among ready jobs, the moment it arrives — directly contradicting SJF's choice. This is the general point Section 2.2 makes about this dataset's near-agreement: priority and burst time are independent axes, and any dataset can be built to make them agree, disagree, or anything between.

2.3 · ALGORITHMS

Multilevel & Real-Time Scheduling

"Fair, eventually" isn't good enough when a deadline is a hard requirement.

Every algorithm in Section 2.2 was judged on averages — average waiting time, average response time. P_audio doesn't care about averages. It needs its next buffer refill by a specific instant, or the user hears a click. A real-time system isn't asking "how fast, on average" — it's asking "did every deadline get met, every single time, guaranteed."

The periodic task model

Real-time scheduling theory models recurring work as a set of periodic tasks: task i releases new work every Ti time units (its period) and needs Ci units of CPU time to finish that work (its execution time) — by convention, before the next release, which is its deadline. P_audio refilling its buffer every 4 time units is exactly this: a period of 4, needing 1 unit of CPU each time.

Utilization — the fraction of the CPU a task needs Ui = Ci ÷ Ti (one task) U = ∑ Ui (the whole task set — the fraction of CPU time it needs, forever, to keep up)

Two ways to assign priority

Rate Monotonic Scheduling (RMS)
  • Static priority: shorter period = higher priority, fixed for the task's entire lifetime.
  • Liu & Layland's 1973 sufficient bound: a task set of n tasks is guaranteed schedulable if U ≤ n(21/n − 1) — a bound that shrinks toward ln 2 ≈ 0.693 as n grows.
  • Simple, predictable, cheap to implement — priorities never change at runtime.
Earliest Deadline First (EDF)
  • Dynamic priority: whichever ready job has the nearest absolute deadline runs next, re-decided continuously.
  • Optimal: a task set is EDF-schedulable if and only if U ≤ 1 — a necessary and sufficient condition, not just a sufficient one.
  • Costs more at runtime: priorities are recomputed on every release, not fixed once.

Worked example: one task set, two outcomes

A periodic task set built from three familiar residents
TaskPeriod TExec. time CUtilization U
P_audio410.2500
B_sync620.3333
T_save830.3750
Total0.9583

Three tasks, so the RMS bound is 3(21/3−1) ≈ 0.7798. Our utilization, 0.9583, is well above it — RMS's simple test can't guarantee this task set is schedulable. EDF's bound is just U ≤ 1; at 0.9583, EDF is guaranteed.

Figure 4 · guaranteed isn't the same as inconclusive

One hyperperiod (24 time units), both algorithms, same task set
P = P_audio · B = B_sync · S (violet) = T_save

RMS

0 4 8 12 16 20 24 P B S P S B P S P B P S B P S DEADLINE MISSED

EDF

0 4 8 12 16 20 24 P B S P B P S P B P S B P
Reading the figure: under RMS, T_save (lowest static priority — longest period) gets bumped by both higher-priority tasks and has only banked 2 of its 3 required units by t=8, its first deadline — a real miss, not a close call. Under EDF, the same T_save job is recognised as increasingly urgent as its deadline approaches and gets an uninterrupted run from t=3 to t=6, finishing with two full units to spare.
The RMS bound is a floor, not a ceiling

An earlier candidate task set for this example — periods 4, 8, 10 with utilization 0.90, also above the 3-task RMS bound — turned out, when actually simulated, to meet every deadline under RMS anyway. The Liu & Layland bound is a sufficient condition: below it, you're safe, guaranteed. Above it, the honest answer is "unknown without checking further," not "unsafe." This chapter's task set was chosen specifically because checking further reveals a genuine miss — not because every above-bound task set fails.

Pitfall

EDF's optimality on paper doesn't make it the automatic right choice. Recomputing priority on every release is real runtime overhead that RMS's fixed priorities never pay (Chapter 1, Section 1.4, again). More importantly: under transient overload (utilization briefly exceeding 1, from a bug or a burst of work), EDF can miss deadlines unpredictably across many tasks at once — a "domino effect" — while RMS's fixed priorities guarantee that if anything misses, it's the lowest-priority task first, leaving the important ones protected. This is a real, common reason safety-critical systems still choose RMS despite EDF's better theoretical guarantee.

Practice 2.3

  1. A task has period 5 and execution time 2. A second has period 20 and execution time 4. Compute the total utilization and check it against the 2-task RMS bound.
    Show solution

    U = 2/5 + 4/20 = 0.4 + 0.2 = 0.6. The 2-task RMS bound is 2(21/2−1) ≈ 0.8284. Since 0.6 ≤ 0.8284, RMS guarantees this task set is schedulable — no simulation needed.

  2. Variation. Using this chapter's worked task set, if T_save's execution time dropped from 3 to 2 (period unchanged at 8), does the total utilization now satisfy the RMS bound?
    Show solution

    New U = 0.25 + 0.3333 + 2/8 (0.25) = 0.8333. The bound is still 0.7798, so 0.8333 is still above it — RMS's simple test remains inconclusive, though closer to the line. (A full re-simulation would be needed to say for certain whether this smaller task set now meets every deadline.)

  3. Interpretation. A task set has utilization 1.05. What can you conclude about its schedulability under EDF, and under RMS?
    Show solution

    Under EDF: definitely not schedulable — EDF's bound is necessary and sufficient, so U>1 guarantees deadlines will be missed no matter how work is ordered. Under RMS: also definitely not schedulable, since RMS can never do better than EDF (EDF is optimal); if the optimal algorithm can't meet every deadline, no fixed-priority scheme can either.

  4. Synthesis. Explain why EDF's dynamic priority recalculation connects to Chapter 1's Section 1.4 in a way RMS's static priority never does.
    Show solution

    Every time EDF re-evaluates which job has the nearest deadline and switches to it, that's a genuine context switch, paying whatever real microsecond cost Chapter 1 measured. RMS's priorities are fixed at design time, so while it still context-switches between jobs, it never pays a cost for the act of deciding priority itself the way a naive EDF implementation recomputing deadlines on every tick might. This is part of why EDF's theoretical optimality doesn't automatically translate into being cheaper to run.

2.4 · ALGORITHMS

Multilevel Queue & Multilevel Feedback Queue

What if you don't have to pick just one rule?

Every algorithm in Section 2.2 applies one rule to every job, uniformly. But P_audio and P_backup aren't really the same kind of thing — one is a quick interactive burst, the other is patient batch work. Real systems separate work like this into different classes and treat each class differently, rather than forcing one algorithm to serve every kind of job equally badly.

Multilevel Queue (MLQ): fixed classes, fixed rules

A Multilevel Queue splits the ready queue into several separate, permanent queues — say, a system queue, an interactive queue, and a batch queue — each with its own scheduling algorithm (the interactive queue might run Round Robin; the batch queue, FCFS). The queues themselves are served by fixed priority (drain the interactive queue completely before touching the batch queue) or by a fixed CPU-percentage split between them.

Pitfall

MLQ is rigid: once a job is assigned to a queue, it stays there for its entire lifetime. A batch job that suddenly starts behaving interactively gets no benefit from that — it's still stuck in the batch queue, at the batch queue's priority, indefinitely.

Multilevel Feedback Queue (MLFQ): classes that adapt

A Multilevel Feedback Queue keeps the multiple-queues idea but removes the rigidity: jobs move between queues based on how they actually behave, not on a fixed assignment. First described by Fernando Corbató in 1962 for CTSS (work later recognised with the Turing Award), MLFQ or its direct descendants have shown up in most major operating systems since — older Linux schedulers (before the current CFS design), classic Solaris, and the Windows NT kernel scheduler are all MLFQ-derived.

The rules (following the standard modern formulation) Rule 1: if Priority(A) > Priority(B), A runs, B doesn't. Rule 2: if Priority(A) = Priority(B), run them round-robin. Rule 3: a new job enters at the TOP (highest-priority) queue. Rule 4: once a job uses up its FULL time allotment at a level — however many times it gave up the CPU to get there — its priority is reduced one level. Rule 5: after some period S, boost every waiting job back to the top queue (prevents permanent starvation).

Rule 4's "however many times it gave up the CPU" clause exists for a specific, sneaky reason: without it, a job could deliberately give up the CPU one tick before its quantum expires, over and over, and never get demoted — gaming the scheduler into treating pure CPU-bound work as if it were interactive forever. Rule 4 closes that loophole by tracking the total time used at a level, not just whether any single visit used the full quantum.

Figure 3 · who's watching TV and who's doing the dishes

A small trace, isolating just T_save and P_backup against a 3-queue MLFQ — Q0 (quantum 2), Q1 (quantum 4), Q2 (FCFS, the bottom). T_save only ever needs a 1-unit CPU burst before it blocks for its autosave I/O (Chapter 1, Section 1.5) — well under Q0's quantum, so by Rule 4 it never gets demoted. P_backup is pure CPU-bound batch work with nowhere to be; it uses its full quantum every time, and sinks a level each visit.

T_save (I/O-bound-ish) vs. P_backup (CPU-bound), traced through three queues
separate mini-example
Q0 (q=2) Q1 (q=4) Q2 (FCFS) 0 2 4 6 8 10 12 T_save P_backup T_save P_backup T_save P_backup
Reading the figure: T_save never leaves the top row — every visit is short and voluntary. P_backup sinks one level every time it exhausts its quantum: Q0 (2 units) → Q1 (4 units) → Q2 (remaining 3 units, run to completion) — 2+4+3=9, exactly its total burst time from the main spine dataset.
Depth — MLFQ approximates SJF without knowing the future

Section 2.2 flagged SJF and SRTF's fatal flaw: they need to know burst time in advance. MLFQ sidesteps this by learning a job's behaviour from how it has already behaved — a job that keeps finishing or yielding quickly earns and keeps a high priority, without the scheduler ever being told a burst time up front. This is why MLFQ is sometimes described as the most general scheduling algorithm on this syllabus: tune the number of queues, their quanta, and the demotion rule, and it can be made to approximate FCFS, RR, or a priority scheme.

Pitfall

Modern Linux does not run a textbook MLFQ — its current scheduler (CFS, and its more recent successor EEVDF) tracks per-task virtual runtime directly rather than moving jobs between discrete queues. MLFQ's real, direct descendants are found in older schedulers (pre-CFS Linux, classic Solaris, Windows NT). The ideas — reward short/interactive bursts, protect against starvation — persist everywhere; the literal queue-based mechanism mostly doesn't, in the systems you'd actually install today.

Practice 2.4

  1. A job in Q1 (quantum 4) uses only 3 units before voluntarily yielding for I/O. Under Rule 4, does it get demoted to Q2?
    Show solution

    No. Rule 4 only demotes a job once it has used its full allotment at a level. 3 units used out of a 4-unit quantum means it yielded early, so by the same logic as T_save in Figure 3, it stays at Q1.

  2. Variation. Suppose P_backup is cunning and yields voluntarily after exactly 1.9 units every time it's given a 2-unit quantum at Q0, repeating this forever. Under the simple version of Rule 4 (only checking whether the current visit used the full quantum), what happens? What does the real Rule 4 (tracking cumulative usage) do instead?
    Show solution

    Under the simple, single-visit-only version, P_backup never technically uses its "full" quantum on any one visit, so it would never be demoted — effectively gaming its way into permanent top-priority treatment despite being purely CPU-bound. The real Rule 4 tracks cumulative time used at a level across all visits; once those 1.9-unit visits add up to a full quantum's worth (just over one visit and change), it gets demoted anyway. This is exactly the loophole Rule 4 was written to close.

  3. Interpretation. Without Rule 5 (the periodic priority boost), could a job in Q2 wait forever?
    Show solution

    Yes — if new jobs keep entering at Q0 (Rule 3) faster than Q0 and Q1 ever empty out, a Q2 job can starve indefinitely, for exactly the same structural reason Priority scheduling can starve a low-priority job in Section 2.2. Rule 5 is MLFQ's version of ageing: instead of gradually raising priority, it periodically resets everyone to the top, guaranteeing every job gets a turn at least once per period S.

  4. Synthesis. Explain why T_ui would behave like T_save in an MLFQ, not like P_backup — using Chapter 1's description of what T_ui actually does.
    Show solution

    T_ui spends most of its life waiting for keystrokes and only briefly computes to update the display, then blocks again waiting for input (Chapter 1, hero). Each of those CPU bursts is short and ends in a voluntary yield, exactly the pattern that keeps T_save pinned at Q0 in Figure 3. MLFQ rewards this pattern automatically, without ever being told "this is an interactive thread" — it only ever sees the behaviour.

WRAP-UP

Cheat Sheet & Self-Test

Everything above, compressed to what you'd want on the way into an exam.

2.1 Metrics

CT = finish time. TAT = CT−AT. WT = TAT−BT. RT = first-run−AT.

WT includes ALL waiting (even after preemption); RT only counts the wait to first run. RT ≤ WT always.

Utilization = busy÷total. Throughput = jobs÷time. 100% utilization ≠ a good schedule.

2.2 FCFS / SJF / SRTF

FCFS: arrival order, non-preemptive. Convoy effect.

SJF: shortest burst next, non-preemptive. Needs BT known in advance.

SRTF: preemptive SJF. Provably minimal avg WT. Needs remaining time known continuously.

2.2 Round Robin

Fixed quantum q, preemptive by clock. Best avg RT, worst avg WT of the five algorithms here.

Tiny q → overhead dominates (Ch1 1.4). Huge q → degenerates to FCFS.

2.2 Priority

Lower number = higher priority (this chapter's convention). Preemptive variant exists.

Starvation risk for low priority — fixed by aging: priority rises the longer a job waits.

2.3 Real-time (EDF, RMS)

RMS: static priority, shorter period wins. Sufficient bound U ≤ n(21/n−1).

EDF: dynamic priority, nearest deadline wins. Optimal: schedulable iff U ≤ 1.

Above the RMS bound = inconclusive, not doomed — check by simulation.

2.4 MLQ / MLFQ

MLQ: fixed queues, fixed assignment, never moves.

MLFQ: jobs move by behaviour. Full quantum used → demoted. Yield early → stays. Periodic boost (Rule 5) prevents starvation.

Corbató 1962. Pre-CFS Linux, Windows NT, classic Solaris are MLFQ-derived; modern Linux (CFS/EEVDF) is not.

Mixed self-test

Deliberately not grouped by section — your exam won't be either.

  1. True or false: Waiting Time is always greater than or equal to Response Time, for any job under any algorithm.
    Show solution

    True. RT measures only the wait until a job's first run; WT measures every unit spent waiting across its entire lifetime, including any further waits after being preempted. RT is a lower bound baked into WT's own definition, not an independent quantity that could exceed it. (2.1)

  2. SRTF is often called "optimal." Optimal for exactly which metric?
    Show solution

    Minimum average waiting time (equivalently, minimum average turnaround time, since TAT = WT + a fixed total burst time), across the full set of jobs. It is not claimed optimal for response time (Round Robin wins that in this chapter's own numbers) or for any single job's individual wait. (2.2)

  3. A job in Q0 (quantum 2) runs for exactly 2 units and still has work remaining. What happens to it next?
    Show solution

    It is demoted to Q1. Rule 4 demotes any job that uses its full allotment at a level, and using exactly the quantum counts as using it in full. (2.4)

  4. If you shrink Round Robin's quantum toward zero, what happens to response time, and what happens to overhead?
    Show solution

    Response time keeps improving, approaching perfect fairness in the limit — but overhead grows without bound, since a real context switch (Chapter 1: on the order of 1–4 µs direct cost, more with an address-space change) is paid at every one of those vanishingly short quanta. Section 1.4's overhead-vs-quantum curve and this chapter's RR section are the same trade-off, looked at from two different chapters. (2.2, callback to 1.4)

  5. A job has AT=5, BT=10, finishes at CT=20, and was first given the CPU at t=8. Find its TAT, WT, and RT.
    Show solution

    TAT = CT−AT = 20−5 = 15. WT = TAT−BT = 15−10 = 5. RT = (first allocation)−AT = 8−5 = 3. (2.1)

  6. Why can a low-priority job starve forever under plain Priority scheduling, but never under Round Robin?
    Show solution

    Round Robin cycles through the entire ready queue by construction — any waiting job is guaranteed a turn within, at most, (n−1) other jobs' quanta, no matter what else arrives. Priority scheduling has no such bound: as long as higher-priority jobs keep arriving, a low-priority job can be skipped indefinitely, which is precisely why aging has to be added on top of it and RR never needed an equivalent fix. (2.2)

  7. Which real scheduler lineage is MLFQ-derived: the current Linux CFS/EEVDF design, or the scheduler Linux used before it?
    Show solution

    The pre-CFS scheduler (and, separately, the Windows NT kernel scheduler and classic Solaris). Modern Linux tracks per-task virtual runtime directly rather than moving jobs between discrete priority queues, even though it keeps MLFQ's underlying goals. (2.4)

  8. Under SRTF, two ready jobs have exactly the same remaining time. Which one does this chapter say should run?
    Show solution

    Whichever arrived earlier — the tie-breaking convention this chapter declares and uses throughout, precisely because real textbooks don't agree on one and an exam question needs a stated rule to be answerable at all. (2.2)

  9. A task set's total utilization is 0.85, and the RMS sufficient bound for that many tasks is 0.78. Is the task set definitely unschedulable under RMS?
    Show solution

    No — "above the bound" means the simple test can't guarantee schedulability, not that it's impossible. The task set might still meet every deadline under RMS; the only way to know for certain is to check further (simulate it, or use an exact response-time analysis). This chapter's own worked example included a task set above its bound that turned out fine, alongside one that didn't. (2.3)

  10. Why is EDF described as "optimal" while RMS is not, even though RMS is still widely used in practice?
    Show solution

    EDF's schedulability condition (U≤1) is both necessary and sufficient — no fixed-priority or other algorithm can schedule a task set EDF cannot. RMS only has a sufficient bound, which is more conservative. RMS remains popular anyway because its priorities are fixed and cheap to reason about, and because its failure mode under overload is more predictable (lowest-priority tasks miss first) than EDF's, which can miss deadlines unpredictably across several tasks at once. (2.3)

Further reading

  • Stallings, Operating Systems: Internals and Design Principles, 9th ed., Ch. 9. This course's primary text; closest match to this chapter's metrics and algorithm definitions.
  • Silberschatz, Galvin & Gagne, Operating System Concepts, 10th ed., Ch. 5. The classic Gantt-chart worked-example style this chapter follows for FCFS/SJF/SRTF/RR/Priority.
  • Tanenbaum & Bos, Modern Operating Systems, 5th ed., Ch. 2 (scheduling section). Good breadth on scheduling goals across batch, interactive, and real-time systems.
  • Liu, C.L. & Layland, J.W., "Scheduling Algorithms for Multiprogramming in a Hard-Real-Time Environment," Journal of the ACM, 1973. The original paper behind both RMS's utilization bound and EDF's optimality proof used in Section 2.3.
  • Arpaci-Dusseau, Operating Systems: Three Easy Pieces, Ch. 8, "Multi-Level Feedback Queue." Primary source for the five MLFQ rules used in Section 2.4; free at ostep.org.
  • Corbató, Daggett & Daley, "An Experimental Time-Sharing System," 1962. The original paper describing what became MLFQ, for anyone who wants the source rather than the summary.

Before this chapter — Chapter 1, Operating System Design, Processes & Threads. This chapter assumes its PCB/TCB model (a scheduler's decisions come from fields stored in exactly those control blocks), its finding that kernel-level threads are scheduled independently of whatever process they belong to (Section 1.5, which is why this chapter's ready queue freely mixes threads and whole processes), and its measured context-switch cost of roughly 1.8 µs (Section 1.4, reused directly in this chapter's Round Robin overhead calculation).

Where this goes next — Unit 3, Synchronization and Concurrency Control Design, turns to what happens when several of these schedulable entities share more than just a CPU: race conditions and the critical section problem, then the real toolkit built to solve it — semaphores, mutexes, monitors, and condition variables — plus memory consistency models and the lock-based-vs-lock-free design question. T_ui and T_save share WriteWell's document buffer already — Unit 3 asks what could go wrong if they touch it at the same instant, and what it actually takes to fix that properly.