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?
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.
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_saveis 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
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 exampleT_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.| Job | AT | BT | CT | TAT | WT |
|---|---|---|---|---|---|
| T_ui | 0 | 4 | 4 | 4 | 0 |
| B_sync | 1 | 6 | 10 | 9 | 3 |
| P_audio | 2 | 1 | 11 | 9 | 8 |
| T_save | 3 | 5 | 16 | 13 | 8 |
| P_backup | 4 | 9 | 25 | 21 | 12 |
| average | — | — | — | 11.20 | 6.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
- 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.
- 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.
- 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_audiowait 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. - 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.
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| Job | AT | BT | CT | TAT | WT | RT |
|---|
| Algorithm | avg TAT | avg WT | avg RT |
|---|---|---|---|
| FCFS | 11.20 | 6.20 | 6.20 |
| SJF (non-preemptive) | 10.00 | 5.00 | 5.00 |
| SRTF (preemptive) | 9.80 | 4.80 | 4.60 |
| Round Robin (q=3) | 13.80 | 8.80 | 3.40 |
| Priority (non-preemptive) | 10.20 | 5.20 | 5.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
- Using the spine dataset, verify by hand that SJF's schedule gives
T_savea 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.
- 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_backupdoesn'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 involveP_backupat 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. - 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).
- Synthesis.
P_audiohas 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_backuppriority 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.
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.
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
ntasks is guaranteed schedulable ifU ≤ n(21/n − 1)— a bound that shrinks towardln 2 ≈ 0.693asngrows. - 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
| Task | Period T | Exec. time C | Utilization U |
|---|---|---|---|
| P_audio | 4 | 1 | 0.2500 |
| B_sync | 6 | 2 | 0.3333 |
| T_save | 8 | 3 | 0.3750 |
| Total | — | — | 0.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_saveRMS
EDF
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
- 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. - 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.)
- 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.
- 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.
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.
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-exampleT_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
- 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_savein Figure 3, it stays at Q1. - Variation. Suppose
P_backupis 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_backupnever 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. - 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.
- Synthesis. Explain why
T_uiwould behave likeT_savein an MLFQ, not likeP_backup— using Chapter 1's description of whatT_uiactually does.Show solution
T_uispends 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 keepsT_savepinned 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.
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.
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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)
- 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.