CPU Scheduling

Learn how an operating system decides which program runs next on the CPU. Measure schedules with turnaround and response time, then compare first-in-first-out, shortest-job-first, round-robin and priority scheduling on worked examples. See how a multi-level feedback queue learns which jobs are interactive, how lottery, stride and Linux's fair schedulers give each job a set share of the CPU, and how schedulers spread work over several CPUs. Finish by reading the schedulers of Linux and Windows and choosing a policy for a given workload.

IntermediateLesson 2 of 9 in Operating Systems Course

What you will learn

  1. Explain where scheduling decisions happen in the life of a process, tell preemptive from non-preemptive scheduling, and calculate the metrics used to compare scheduling policies.
    • Explain when and how the scheduler picks the next job
      Place the CPU scheduler in the process life cycle, distinguish preemptive from non-preemptive scheduling, and name the kinds of schedulers an operating system can have.
    • Calculate turnaround, response and waiting time
      Draw a timeline of a schedule and calculate turnaround time, response time, waiting time, throughput and CPU utilization, and explain which goal each metric serves.
  2. Schedule a set of jobs under the classic policies, calculate how each one performs, and explain why each policy suits some workloads and fails others.
    • Schedule jobs with FIFO and shortest job first
      Apply first-in, first-out and non-preemptive shortest-job-first scheduling, explain the convoy effect, and estimate run times that are not known in advance.
    • Preempt for shorter jobs and overlap I/O
      Apply shortest time-to-completion first, explain when preemption improves turnaround, and keep the CPU busy by running other jobs while one waits for I/O.
    • Use round robin for fast response
      Apply round-robin scheduling, explain its effect on response and turnaround time, and choose a sensible time slice.
    • Use priorities without starving jobs
      Apply priority scheduling, read the different priority scales used in practice, and prevent starvation and priority inversion.
  3. Explain how a multi-level feedback queue learns from a job's behavior to approximate shortest-job-first while keeping interactive jobs responsive, and how its rules are tuned against starvation and gaming.
    • Trace jobs through a multi-level feedback queue
      State the basic rules of the multi-level feedback queue and trace how CPU-bound, short and interactive jobs move between its queues.
    • Tune MLFQ against starvation and gaming
      Explain the problems of the basic MLFQ rules, fix them with priority boosts and better accounting, and choose its parameters.
  4. Explain proportional-share scheduling, calculate the shares that lottery, stride and Linux's fair schedulers give, and compare their strengths.
    • Share the CPU by lottery
      Represent shares with tickets, run a lottery draw, predict how close lottery scheduling comes to the target shares, and use ticket currency, transfer and inflation.
    • Get exact shares with stride scheduling
      Calculate strides and pass values, trace a stride schedule, and compare stride with lottery scheduling.
    • Explain Linux's fair schedulers: CFS and EEVDF
      Calculate time slices and virtual runtime under the Completely Fair Scheduler, relate nice values to weights, and describe how EEVDF chooses the next task.
  5. Explain how caches, coherence and affinity change scheduling on a multiprocessor, and compare single-queue and multi-queue designs that balance load across CPUs.
    • Explain what changes with several CPUs
      Describe multiprocessor hardware as the scheduler sees it: private caches, cache coherence, the need for locking, cache affinity and different kinds of cores.
    • Compare single-queue and multi-queue multiprocessor scheduling
      Compare single-queue and multi-queue multiprocessor schedulers, recognize load imbalance, and fix it with migration and work stealing.
  6. Read how Linux, Windows and other systems combine priorities, feedback and proportional sharing, control them with standard tools, and choose and evaluate a policy for a given workload.
    • Control the Linux scheduler
      Describe Linux's scheduling policies and their history, and use nice values, real-time policies, CPU affinity and control groups.
    • Read Windows and other systems as MLFQ-style schedulers
      Calculate Windows base priorities, explain dynamic priority boosts and their decay, and recognize the same feedback ideas in other systems.
    • Choose and evaluate a scheduling policy for a workload
      Match scheduling policies to workloads, compare them on one example, and choose a method for evaluating a scheduler.

CPU Scheduling study guide

6 chapters

1

Decide who runs and measure the result

A CPU can run one thread at a time, yet a busy system may have many threads ready to use it. The scheduler decides whose work advances at each opportunity. To judge that choice, follow both the process states and the clock: a quick first turn, an early finish, and a high rate of completed work describe different successes. A timeline makes those differences visible and gives you the evidence for comparing policies.

1.1 From a ready job to a running job

A CPU scheduler chooses the ready process or thread that runs next on a CPU. The rule it follows is its policy. The dispatcher carries out the choice by switching execution to the selected job. A different policy can use the same switching mechanism.

Follow the state changes

A running job owns a CPU. A ready job could run but is waiting for a turn. A blocked job is waiting for an event, such as the completion of a disk read. Only ready jobs are candidates for selection.

Suppose an editor starts a disk read while a compiler is ready. The editor moves from running to blocked, so the compiler can run. When the read finishes, an interrupt makes the editor ready again. It does not necessarily run immediately: the policy must choose between it and other ready work.

Scheduling decisions occur when a job blocks, finishes, becomes ready, or is interrupted and returned to ready. Voluntary yielding also releases the CPU. Preemption means taking the CPU from a job that could have continued running; the job keeps its saved state and can resume later.

Policy styleWhen a running job gives up the CPUEffect of a new ready job
Non-preemptiveIt blocks, yields, or finishesIt waits for a decision opportunity
PreemptiveIt can also lose the CPU while still able to runIt may displace the current job

A timer interrupt lets the kernel enforce a time slice, even if a program loops without yielding. A completed I/O can also trigger preemption by making a more favored task ready. Linux, Windows, and macOS use preemptive scheduling.

Work comes in bursts

Programs alternate between CPU bursts, when they compute, and periods spent waiting for I/O. A CPU-bound program such as an encoder has long CPU bursts. An I/O-bound program such as an editor often computes briefly and then waits. Giving an editor prompt service after a keypress can help responsiveness without giving it much total CPU time.

The dispatcher saves the old task's state, restores the chosen task's registers, and resumes its instruction stream in user mode. Dispatch latency is the time taken to hand over execution. Switching also disturbs caches and the translation lookaside buffer, or TLB, which caches address translations. The next task may need to refill them, so register-saving time is only part of the cost.

Three scheduling timescales

The long-term scheduler admits submitted jobs and controls how many are in the system. The medium-term scheduler can suspend whole processes by swapping them out of memory and later restoring them. The short-term scheduler selects the next ready task and acts frequently. General-purpose systems rely mainly on this last role; batch systems and clusters may also control admission explicitly.

Start a policy comparison with simple CPU-only jobs and known lengths. Then vary one feature: unequal lengths expose FIFO's delays, later arrivals expose the limits of non-preemption, I/O creates opportunities to overlap work, and unknown lengths require prediction or feedback.

Key Takeaways

  • Only ready jobs can be selected to run.
  • A scheduling policy chooses; the dispatcher performs the switch.
  • Preemption preserves a task so it can resume.
  • Timer and device interrupts can create scheduling opportunities.
  • Frequent switching costs both dispatch time and cache locality.
  • Admission, swapping, and CPU selection act on different timescales.

1.2 Read times from a schedule

A schedule tells you when jobs run. A metric tells you which part of that schedule matters. Record each job's arrival, first run, and completion before calculating any averages.

Separate the three times

Turnaround time measures the whole interval from arrival to completion. Response time measures the delay until the first run. Waiting time adds every interval spent ready but not running.

Tturnaround=Tcompletion−Tarrival Tresponse=Tfirst run−Tarrival

For a CPU-only job, turnaround equals waiting plus CPU run time. With I/O, blocked time is also part of turnaround, so subtracting CPU time alone would overcount waiting. Response uses the first-run definition here; a user-facing service may separately measure time to its first output.

Work through a FIFO timeline

A arrives at 0 ms and needs 8 ms of CPU time. B arrives at 1 ms and needs 4 ms. C arrives at 2 ms and needs 2 ms. With no switching cost, FIFO gives:

  • A: 0–8 ms.
  • B: 8–12 ms.
  • C: 12–14 ms.
JobTurnaroundResponseWaiting
A8−0=8 ms0−0=0 ms0 ms
B12−1=11 ms8−1=7 ms7 ms
C14−2=12 ms12−2=10 ms10 ms

The average turnaround is 8+11+123=313≈10.33 ms. Average response and waiting are both 0+7+103=173≈5.67 ms. They coincide because each job runs once without interruption. Under preemption, a job may wait again after its first turn, so waiting can exceed response.

Measure the whole workload

Throughput counts completed jobs per unit of elapsed time. The schedule completes three jobs in 14 ms, about 214.29 jobs/s. CPU utilization is busy CPU time divided by elapsed time; it is 100% here because the CPU never idles. Specify the measurement interval: adding an idle period after completion would change both figures.

High utilization can still accompany long waits. It also need not mean all busy time is useful application work: real measurements may count switching and other kernel work as busy time. State whether an overhead calculation measures busy time or useful work.

Choose what to optimize

Batch work often values average turnaround. Interactive work values a quick response. Shared services need fair access as well as throughput. Starvation means an eligible job waits indefinitely, so a good average alone cannot establish fair treatment.

Inspect individual delays and the tail of the distribution. A 99th-percentile response time describes the delay at or below which roughly 99% of observations fall; a few severe delays can disappear inside a low average. Always subtract the job's own arrival time, and count its running intervals as service, never as waiting.

Key Takeaways

  • Turnaround ends at completion; response ends at the first run.
  • Waiting counts ready intervals and excludes blocked intervals.
  • Subtract each job’s arrival before averaging.
  • Throughput and utilization depend on the observation interval.
  • Inspect tail delays and starvation alongside averages.
2

Trace the classic scheduling policies

The same ready jobs can finish in very different orders under different policies. FIFO follows arrival, shortest-job policies favor small CPU demands, round robin rotates turns, and priority scheduling follows a rank. Build the timeline from the rule at each decision point, then calculate the outcome. Later arrivals, blocked jobs, and switching costs reveal trade-offs that a single ordering of jobs cannot show. Hand traces ignore switching cost unless specified.

2.1 FIFO and the shortest ready burst

FIFO, also called first come, first served or FCFS, runs ready jobs in arrival order. It is non-preemptive: a later arrival cannot interrupt a running CPU burst. For CPU-only examples, each selected job runs to completion.

See the convoy effect

A, B, and C arrive together. A needs 60 ms; B and C need 6 ms each. With A first, FIFO runs A 0–60, B 60–66, and C 66–72. Turnaround times are 60, 66, and 72 ms, averaging 66 ms. The small jobs spend most of their lives waiting behind A. This is the convoy effect.

Shortest job first (SJF) selects the shortest next CPU burst among ready jobs and does not preempt it. With the same arrivals, it runs B 0–6, C 6–12, then A 12–72. Average turnaround becomes 6+12+723=30 ms. Total CPU work is still 72 ms; the improvement comes from finishing short jobs sooner.

Why does this help? If a long burst runs immediately before a short burst, both jobs wait for all earlier work. Swapping just these two cuts the short job's delay by the long burst's length while increasing the long job's delay only by the short burst's length. Repeating such swaps puts the bursts in ascending order. With all jobs arriving together and known lengths, SJF minimizes average turnaround and waiting; first-run response also equals waiting in this non-preemptive CPU-only case.

Restrict the choice to ready jobs

Now A arrives at 0 ms, while B and C arrive at 10 ms. At 0 ms, A is the only choice. Non-preemptive SJF runs A 0–60, B 60–66, C 66–72. Turnaround times are 60, 56, and 62 ms, averaging about 59.33 ms. SJF cannot act on a future job or interrupt a burst it already started.

PolicyInformation usedMain weakness
FIFOArrival orderShort work can wait behind long work
SJFPredicted next burst lengthLong work can be postponed by repeated short arrivals

FIFO avoids starvation when jobs ahead eventually release the CPU. SJF can starve a long waiting job if short work keeps arriving.

Predict a burst

The next CPU burst is usually unknown. An exponential average combines the latest measured burst with the previous prediction:

τn+1=αtn+(1−α)τn

Here, tn is the measured burst, τn the previous prediction, and α a weight between 0 and 1. Starting with 10 ms and using α=0.5, a measured 6 ms gives a prediction of 8 ms. A subsequent 4 ms gives 6 ms; another 6 ms leaves it at 6 ms. At zero weight, measurements have no effect; at weight one, only the newest measurement matters. The predicted quantity is CPU burst length, not program file size or line count.

Key Takeaways

  • FIFO uses arrival order and can create a convoy.
  • SJF chooses the shortest burst already ready.
  • SJF’s average-time optimum requires the relevant workload assumptions.
  • Later arrivals cannot interrupt non-preemptive SJF.
  • Exponential averaging balances recent measurements with past predictions.
  • A stream of short jobs can starve a long SJF job.

2.2 Interrupt a long job and overlap I/O

Shortest time-to-completion first (STCF), also called shortest remaining time first or SRTF, is preemptive SJF. At an arrival or completion, compare the CPU time each ready job still needs. A newcomer interrupts the current job when it needs less time than the current job has left.

Compare remaining time

A needs 60 ms and arrives at 0 ms. B and C each need 6 ms and arrive at 10 ms. A runs for 10 ms, leaving 50 ms. At 10 ms, B wins because 6 ms is less than 50 ms; C has the same length, so arrival order and then the name break the tie.

The timeline is A 0–10, B 10–16, C 16–22, A 22–72. Turnaround times are A 72 ms, B 6 ms, and C 12 ms, averaging 30 ms. Response times are 0, 0, and 6 ms, averaging 2 ms. Non-preemptive SJF on these arrivals averages about 59.33 ms turnaround and 35.33 ms response.

Always subtract service already received. Comparing a new 12 ms burst with A's original 60 ms would be wrong if A had only 5 ms left. STCF would finish A first. With known CPU-only lengths and zero switching cost, STCF minimizes average turnaround across arbitrary arrivals. Long jobs can still starve under a continuing stream of shorter work.

When all CPU-only jobs arrive together, SJF and STCF give the same ordering. The running shortest job only gets shorter, so no waiting job becomes a reason to preempt it.

Use another job's blocked time

A blocked job cannot use the CPU. Its I/O wait is an opportunity to run other ready work, even under a non-preemptive policy. Preemption matters again when completed I/O makes a short burst ready while another job is running.

Consider A with five 10 ms CPU bursts and a 10 ms disk read after each of its first four bursts. B needs one 50 ms CPU burst. Both arrive at 0 ms. If the CPU idles during A's reads and delays B until A finishes, A completes at 90 ms and B at 140 ms.

Treat each returning burst of A as short ready work:

  • A runs 0–10; its read occupies 10–20 while B runs.
  • A returns for 20–30; B has 40 ms left, so A's 10 ms wins.
  • B runs 30–40 during the next read. The alternation repeats.
  • A's last burst runs 80–90; B finishes its last 10 ms during 90–100.

A still finishes at 90 ms, but B finishes at 100 ms. The CPU performs 100 ms of work in 100 ms of elapsed time. Disk activity and CPU activity overlap; the CPU does not execute A while A is blocked. A device interrupt marks A ready when each read ends, after which STCF compares its new burst with B's remaining work.

Key Takeaways

  • STCF compares remaining CPU demand at decision points.
  • Preemption can let later short jobs finish much earlier.
  • With simultaneous CPU-only arrivals, SJF and STCF agree.
  • A blocked job releases the CPU so other work can overlap its I/O.

2.3 Rotate turns with round robin

Round robin (RR) keeps a FIFO ready queue and gives its front job at most one quantum, or time slice. A job that finishes or blocks leaves the CPU early. A job still ready when its slice expires moves to the back.

Trace turns before calculating times

A, B, and C arrive at 0 ms and each need 9 ms. With a 3 ms quantum, RR runs:

  • First round: A 0–3, B 3–6, C 6–9.
  • Second round: A 9–12, B 12–15, C 15–18.
  • Final round: A 18–21, B 21–24, C 24–27.

First runs are at 0, 3, and 6 ms, so average response is 3 ms. Completions are at 21, 24, and 27 ms, so average turnaround is 24 ms. FIFO gives average response 9 ms and average turnaround 18 ms. Here RR starts everyone promptly but postpones the first completed job until 21 ms.

RR divides CPU access while jobs compete; it does not equalize completion times. A short job can finish on its first turn. With a fixed population of n ready jobs and quantum q, the wait between turns is at most (n−1)q without switching costs. Ongoing arrivals, other priority classes, and restricted CPU eligibility change the setting of that bound.

Handle arrivals at a slice boundary

Use arrival order, then alphabetical order for ties. A job arriving exactly when a slice expires joins before the preempted job. With A arriving at 0 ms needing 8 ms, B at 1 ms needing 4 ms, and C at 2 ms needing 2 ms, a 2 ms quantum gives A 0–2, B 2–4, C 4–6, A 6–8, B 8–10, A 10–14.

The final A interval contains two consecutive turns with no competitor. Response times are 0, 1, and 2 ms; turnaround times are 14, 9, and 4 ms. Their averages are 1 ms and 9 ms. When a blocked job returns in basic RR, it joins for a fresh turn; it does not reserve unused CPU time while blocked.

Make the quantum worth its cost

A very large quantum makes RR behave like FIFO for bursts shorter than that quantum. A tiny quantum creates many dispatches and repeated cache disruption. In a simple timer-based implementation the quantum is a whole number of timer periods.

For switching cost s after each useful slice of length q, the approximate overhead fraction is sq+s. A 0.1 ms switch costs about 9.1% with a 1 ms slice, but about 0.99% with a 10 ms slice. Longer slices amortize switching cost by spreading it over more useful work.

A common sizing heuristic is to let most bursts, for example about 80%, end within one slice. The right choice depends on measured burst lengths and the response delays the workload can tolerate. Count switches between tasks separately from timer events that simply let the same sole ready task continue.

Key Takeaways

  • RR requeues an unfinished ready job after its quantum.
  • Response can improve while average turnaround grows.
  • Boundary arrival rules determine queue order.
  • A short quantum increases switching overhead.
  • Longer slices amortize dispatch and cache costs.

2.4 Priorities, aging, and lock dependencies

A priority scheduler runs the highest-priority ready job. Equal-priority jobs can follow FIFO or round robin. In a preemptive version, a newly ready higher-priority job takes the CPU immediately; in a non-preemptive version it waits until the current job releases it.

Read the direction of the scale

Priority numbers have no universal direction. Use smaller numbers for higher priority in the textbook examples here. Linux nice values follow that direction, but Windows priority levels and Linux real-time priorities use larger numbers for higher priority.

A, B, and C arrive at 0 ms with bursts of 4, 3, and 5 ms and priorities 2, 1, and 3. Non-preemptive priority scheduling runs B 0–3, A 3–7, and C 7–12. Their waiting times are 0, 3, and 7 ms, averaging about 3.33 ms; turnarounds are 3, 7, and 12 ms, averaging about 7.33 ms.

An internal priority comes from measured behavior, such as CPU usage or I/O waits. SJF derives rank from predicted burst length. An external priority comes from a person, such as an administrator who marks a backup as less urgent. Neither choice ensures that low-priority work receives time under a continuous supply of higher-priority work.

Raise priority with waiting

Aging gradually raises the priority of a waiting job. If the rank improves by one every 100 ms, a job starting at priority 20 reaches the top priority 0 after 2 s of ready waiting. Higher rank brings it into competition with favored work; tie rules determine turns among jobs at the same rank.

Starvation is a lack of progress caused by repeated selection of other work. Aging tackles it by changing rank over time. It serves a different purpose from predicting burst length: an old long job may deserve a turn even though its burst remains long.

Follow the dependency in priority inversion

A high-priority job H may be blocked on a lock held by low-priority job L. A medium-priority job M can preempt L. Now H cannot proceed, even though M has lower priority than H: L must run to release the lock first. This is priority inversion.

With priority inheritance, L temporarily inherits H's priority while it holds the lock H needs. M can no longer keep L off the CPU. L runs, releases the lock, and loses the inherited priority; H becomes ready and can run.

ProblemCauseScheduling response
StarvationOther ready work keeps outranking a jobAging raises its rank with waiting
Priority inversionFavored work waits for a lower-ranked lock holderInheritance raises the holder while the dependency lasts

Raising H's own priority does not release its lock: H remains blocked. The key is to let the thread that can satisfy the dependency execute. In 1997, Mars Pathfinder encountered a priority-inversion problem that was addressed by enabling priority inheritance.

Key Takeaways

  • Check which direction means higher priority.
  • Aging raises waiting jobs to address starvation.
  • A blocked high-priority task cannot run until its dependency is satisfied.
  • Priority inheritance temporarily raises the lock holder.
3

Learn a job’s behavior with feedback queues

The next CPU burst is rarely known in advance. A multi-level feedback queue learns from CPU use: new work gets an early chance, while sustained computation moves down to queues with less urgent service. Tracing both queue membership and consumed allotment explains that behavior. Periodic boosts and careful accounting then address the two main failures: work that waits too long and work that yields strategically to keep its rank.

3.1 Move jobs through feedback queues

A multi-level feedback queue (MLFQ) combines priorities with round robin. Its goal is to approximate short-job service and keep interactive work responsive without being told each job's future run time. Recent CPU use supplies the feedback.

Apply the queue rules

Each ready job belongs to one priority queue. The basic accounting version follows four rules:

  1. Choose the highest-priority queue containing ready work.
  2. Within that queue, rotate equal-priority jobs with round robin.
  3. Put a new job in the top queue.
  4. Demote a job when it consumes its CPU allotment at its current level, counting usage across all turns and I/O interruptions.

A quantum limits one turn. An allotment limits total service at a priority level. A level may allow several quanta before demotion. At the bottom level a demotion leaves the job in the bottom queue.

This gives a new job a chance to finish quickly. A job that repeatedly consumes CPU time reveals a longer demand and moves down. A short burst that blocks consumes little allotment, so interactive jobs tend to stay high for longer.

Trace a long job and a newcomer

Use queues Q2, Q1, and Q0, with Q2 highest, 10 ms quanta and 10 ms allotments at each level, and no boost during this trace. A needs 200 ms and arrives at 0 ms. It runs in Q2 from 0–10, in Q1 from 10–20, and in Q0 afterward.

At 100 ms, A has received 100 ms of CPU time. B arrives needing 20 ms. B enters Q2 and preempts A, then runs 100–110 in Q2. It has consumed that level's allotment and drops to Q1. Q1 outranks A's Q0, so B runs 110–120 and finishes. A resumes at 120 and completes its remaining 100 ms at 220 ms. B's turnaround is 20 ms despite arriving after a much longer job.

Track A's remaining work while B runs: it stays at 100 ms. Elapsed time advances during B's service, but A receives no CPU service then.

Separate waiting from CPU consumption

An editor that runs for 1 ms and waits for input uses a 10 ms allotment over ten such bursts. Blocked time does not count against the CPU allotment. Under strict accounting, those short bursts still add up, so the editor eventually moves down unless a priority boost resets it first.

An early MLFQ rule demoted only jobs that used a whole uninterrupted quantum. A job that yielded just before expiry kept its priority. That rule made interactive work responsive but also allowed deliberate gaming. Counting cumulative CPU use closes that loophole.

Lower queues run whenever all higher queues have no ready work. A higher-priority job that is blocked does not prevent lower-priority jobs from using the CPU. Under sustained high-priority demand, lower work needs an additional anti-starvation mechanism, supplied by periodic boosts.

Key Takeaways

  • MLFQ learns from observed CPU use, without knowing future burst lengths.
  • The highest ready queue wins; equal-priority jobs rotate.
  • New jobs enter at the top.
  • Quantum and allotment control different parts of the schedule.
  • Cumulative CPU accounting includes service before a job blocks.

3.2 Prevent starvation and strategic yielding

Feedback creates useful separation, but a job's past behavior can stop representing its current needs. A long computation may later become interactive. Meanwhile, a bottom-queue job can wait indefinitely if higher queues stay busy.

Reconsider every job periodically

A priority boost moves all jobs back to the top queue after a period S. It lets waiting jobs share the top queue and lets the scheduler learn changed behavior afresh. A boosted CPU-bound job later consumes its allotment and moves down again.

Consider the early MLFQ rules: two interactive jobs always yield before a full 10 ms slice and together keep Q2 busy. A CPU-bound job waits in Q0. Without boosts it gets no service. In a repeating schedule where a boost every 100 ms gives it one 10 ms top-level turn before it is demoted and higher work fills the rest, it receives 10% of the CPU. That percentage comes from this trace; a boost does not assign a general fixed share.

A long boost period leaves long waits between opportunities. A very short period repeatedly resets CPU-bound work and weakens the advantage of interactive work. Designs have used periods around one second, but the period is a tuning choice based on workload behavior and response goals.

Account across yields

A separate problem is gaming. Under the early full-slice rule, a program can run for 9 ms, request a 1 ms I/O, and repeat. It never uses a whole 10 ms slice at once, so it retains top priority while consuming nearly all available CPU time.

With a cumulative 10 ms allotment, the first burst consumes 9 ms and leaves 1 ms. After the I/O, one further millisecond exhausts the allotment, and the job is demoted during its second burst. An I/O request changes state; it does not erase service already received. The accounting rule prevents this tactic even without a boost.

MechanismWhat it changesProblem it addresses
Allotment accountingAdds CPU use across turnsStrategic yielding before expiry
Periodic boostRestarts priority learningStarvation and changed behavior
Tune the levels

Choose the number of queues, each queue's quantum, each level's allotment, and the boost period. Top queues usually use short quanta, for example 10 ms, to alternate quickly among interactive jobs. Lower queues can use much longer quanta, sometimes hundreds of milliseconds, to reduce switching during sustained computation.

Allotment can grow independently of quantum. A level with a 5 ms quantum and 15 ms allotment can allow three full turns before demotion. Increasing allotment delays classification as long-running; increasing quantum lengthens an individual turn.

Solaris's time-sharing design illustrates table-based feedback: its classic configurable table has 60 priority levels, with quanta ranging from about 20 ms at high priority to a few hundred milliseconds at low priority. Classic BSD designs instead computed priority from recent CPU usage that decays over time. Both let old CPU use lose influence, so a thread's distant history does not permanently determine its treatment.

Key Takeaways

  • Boosts reopen service opportunities and let changed behavior be relearned.
  • A boost does not give a permanent high priority or fixed CPU share.
  • Cumulative accounting prevents the yield-before-expiry tactic.
  • Short top-level quanta support response; longer low-level quanta reduce overhead.
  • Allotment can span several turns at one level.
  • Feedback can use priority tables or decaying CPU-use formulas.
4

Divide CPU time by shares

A fair-share scheduler starts with an entitlement: how much of the contested CPU each runnable job should receive. Tickets express that entitlement in lottery and stride scheduling; weights express it in Linux’s fair class. The selection rules differ in how closely short intervals follow the intended split and how they favor prompt service. Follow the accounting to see why a larger weight earns more real CPU time while its virtual progress grows more slowly.

4.1 Draw weighted turns with lottery scheduling

Proportional-share scheduling aims to divide CPU service according to assigned shares. In lottery scheduling, each runnable job owns tickets. A random winning ticket chooses the job for the next equal-length slice. A job's chance of winning is its tickets divided by all runnable tickets.

Locate a winning ticket

A holds 100 tickets, B 50, and C 250. Number the 400 tickets from 0 through 399. A owns 0–99, B owns 100–149, and C owns 150–399. A draw of 300 selects C.

A list-based implementation draws a number and accumulates ticket counts. The running totals are 100 after A, 150 after B, and 400 after C. Stop at the first total strictly greater than the draw. Using “greater than or equal” would assign boundary tickets incorrectly: draw 100 belongs to B. Putting larger ticket holders first reduces the average length of this list search.

Distinguish expectation from a guarantee

With A holding 75 tickets and B 25, A's expected share is 75%. In 100 independent equal-slice draws with both runnable, A expects 75 wins. The standard deviation is:

100×0.75×0.25≈4.33 slices.

A result around 71–79 wins is within roughly one standard deviation of the mean; it is not a guaranteed range. Short runs can depart markedly from the intended 3:1 ratio. As the observation window grows, the relative random variation becomes smaller. Lottery provides probabilistic fairness, not an exact finite-window split or a bounded wait for the next turn.

For two equal-ticket jobs with equal CPU demands, the unfairness metric U divides the earlier completion time by the later one. The ratio reaches 1 when they complete together and is smaller when one completes much earlier. This completion ratio is especially variable for short lottery-scheduled jobs.

Allocate tickets across users and dependencies

Ticket currency lets a user divide an assigned global entitlement locally. User X has 200 global tickets and assigns 300 local tickets to X1 and 100 to X2. Of 400 local tickets, X1 has three quarters, giving 150 global tickets; X2 gets 50. User Y has 100 global tickets for Y1. The total is 300, so X1 receives an expected 50%, X2 about 16.67%, and Y1 about 33.33% of the contested CPU.

Ticket transfer temporarily lends a client's tickets to a server doing work for it, then returns them when the request completes. This follows the work dependency. Ticket inflation lets cooperating jobs increase their own ticket counts to request more service. It requires trust or limits: unrestricted inflation lets a greedy job dilute everyone else's shares.

Lottery needs ticket totals but no record of how far each job is ahead in service. A new job simply contributes its tickets to the runnable pool. Assigning the tickets remains a policy choice; the random draw enforces that choice in expectation. A blocked job's tickets do not compete for a slice it cannot use.

Key Takeaways

  • A ticket fraction gives a job’s chance of winning each draw.
  • Cumulative lookup stops when the total exceeds the winning number.
  • Lottery shares are expected proportions, with short-run variation.
  • Ticket currency preserves a user’s global entitlement while dividing it locally.
  • Transfer follows a dependency; unrestricted inflation can dilute others’ shares.

4.2 Keep service on track with stride values

Stride scheduling turns ticket shares into a deterministic sequence. Each runnable job has a stride, calculated as a large constant divided by its tickets, and a pass value that records its weighted progress. Choose the lowest pass, run that job for one equal-length slice, then add its stride to its pass.

Calculate the strides

A has 50 tickets, B 25, and C 100. With constant 1,000, their strides are 20, 40, and 10. More tickets produce a smaller stride. A favored job's pass rises slowly, so it becomes the minimum more frequently.

Start all passes at zero and break ties alphabetically. Keep the tuple in the fixed order A, B, C:

Passes before selectionJob selectedPasses after its slice
(0, 0, 0)A(20, 0, 0)
(20, 0, 0)B(20, 40, 0)
(20, 40, 0)C(20, 40, 10)
(20, 40, 10)C(20, 40, 20)
(20, 40, 20)A(40, 40, 20)
(40, 40, 20)C(40, 40, 30)
(40, 40, 30)C(40, 40, 40)

Only the selected job's pass changes. In seven slices, A receives two turns, B one, and C four: the exact ratio 50:25:100. At the shared pass value of 40, each has advanced through the same amount of weighted service. Between such alignments, short-window shares need not be exact.

Keep real service and virtual progress separate

The pass is an ordering value, not elapsed time or a count of tickets. B's large stride makes it wait while A and C catch up in pass. It still receives its intended one-seventh share over this repeating cycle. Adding the ticket count to the pass would reverse the design: the highest-ticket job would make the biggest jump and be selected less often.

The constant controls the scale of strides, not the intended ticket ratios. Integer implementations need enough precision to avoid distorting those ratios through rounding. Comparisons and updates must use a consistent scale.

Place a newcomer sensibly

Suppose established jobs have passes around 4,000. A new job starting at zero would win repeatedly while catching up, even if it had few tickets. Initialize its pass relative to current system progress, such as the minimum current pass, so it does not collect service for time before it arrived.

LotteryStride
Random draws enforce expected sharesLowest-pass selection tracks service deterministically
Ticket counts are enough for selectionEvery job needs a pass and stride
A newcomer simply adds ticketsA newcomer needs a suitable initial pass

Linux virtual runtime uses the related idea of charging weighted progress for actual CPU service. In both designs, a higher entitlement makes that progress grow more slowly, keeping the task competitive for later service.

Key Takeaways

  • Stride is the common constant divided by tickets.
  • Select the minimum pass and add only that job’s stride.
  • Larger ticket holdings make pass values grow more slowly.
  • New jobs need pass values tied to current progress.

4.3 Weights, virtual runtime, and eligible deadlines

Linux's fair schedulers track weighted CPU service. The Completely Fair Scheduler (CFS), introduced in Linux 2.6.23 in 2007, chose the runnable task with the smallest virtual runtime. Linux began replacing that selection rule with EEVDF in 6.6 in 2023.

Divide service by weight

A nice value ranges from −20, most favored, to +19, least favored. Nice 0 has weight 1024. Each step toward a larger nice value reduces weight by a factor of about 1.25. Example weights are 3121 at nice −5, 820 at nice 1, 335 at nice 5, 110 at nice 10, and 15 at nice 19.

Nice 0 against nice 1 gives 10241024+820≈0.555, about 55.5% against 44.5%. Shares depend approximately on the difference in nice values: 3121/1024 and 335/110 are both about 3.05. Nice +19 competing with nice 0 still receives about 1.4% in this simple two-task model.

Classic CFS distributes a target scheduling latency by weight:

slicek=wk∑iwi×latency

For weights 1024, 1024, and 335, the total is 2383. A 48 ms target period gives about 20.63 ms to each heavier task and 6.75 ms to the lighter one. These are illustrative parameters, not universal kernel defaults. With four equal tasks, 48 ms gives 12 ms each. With ten, 4.8 ms each would fall below an illustrative 6 ms minimum granularity, so the period must grow.

Charge virtual progress

CFS increases a running task's virtual runtime by:

Δv=1024w×Δt

A weight-1024 task gains one virtual millisecond per real millisecond. A weight-335 task gains about 3.06. Charging lighter tasks faster makes them wait sooner while heavier tasks receive more real service.

Classic CFS orders queued runnable tasks in a red-black tree by virtual runtime. Insertion and removal cost logarithmic time; a cached pointer to the leftmost node makes finding the minimum constant time. Blocked tasks leave this runnable tree. Wake-up placement limits old sleep from becoming an unlimited claim on catch-up service.

Choose among eligible tasks with EEVDF

Earliest Eligible Virtual Deadline First keeps weights and virtual service accounting. A task has positive lag when it is owed service and negative lag when it has received more than its entitlement. Tasks with nonnegative lag are eligible. EEVDF selects the eligible task with the earliest virtual deadline.

The deadline combines a request's virtual start with its requested service length scaled into virtual time. It is a service-ordering value, not a promised wall-clock completion time. A shorter requested slice can give an eligible task an earlier deadline and improve latency without increasing its long-run weight share. Current Linux supports slice requests through sched_setattr().

Classic CFS selectionEEVDF selection
Smallest virtual runtimeEarliest virtual deadline among eligible tasks

Key Takeaways

  • Nice values determine relative weights for normal fair-class service.
  • Virtual runtime grows inversely with weight.
  • Classic CFS uses minimum virtual runtime and a cached tree minimum.
  • Minimum granularity can extend the classic CFS period.
  • EEVDF first checks eligibility, then compares virtual deadlines.
  • Shorter EEVDF requests change latency, while weights determine shares.
5

Place work across several CPUs

Several CPUs create more opportunities to run work, but placement now affects the cost of every choice. A thread may find warm caches on one core and distant memory on another. Ready queues must also support simultaneous decisions without corrupting shared state. Compare a single shared queue with separate per-CPU queues, then weigh the benefit of balancing work against the cost of moving it.

5.1 Account for caches and CPU topology

Several CPUs help only when there is parallel work. A single thread runs on one logical CPU at a time; several threads or independent programs can use several CPUs together. A scheduler must choose both which job runs and where it runs.

Share scheduling responsibility

In symmetric multiprocessing (SMP), CPUs run kernel code and make scheduling decisions for themselves. In asymmetric multiprocessing, one main processor coordinates scheduling while others run assigned work. Central control is simpler, but the main processor can become a bottleneck. General-purpose systems use SMP.

Simultaneous decisions require coordination. If two CPUs remove tasks from a shared ready queue, its updates must be synchronized so neither loses an entry nor selects the same queued task twice. More CPUs can increase contention for that shared structure.

Preserve useful cache contents

Cores have small fast caches, typically private L1 and L2 caches and a larger L3 shared by several cores. Temporal locality means reusing recently accessed data. Spatial locality means accessing nearby data, such as consecutive array elements.

A sorting thread on core 0 fills its caches and TLB. If it resumes there after a brief preemption, many needed entries may still be present. On core 3, it may need to fetch the same data again from a shared cache or memory. Cache affinity is the scheduler's tendency to keep a thread near the CPU it recently used. The exact benefit depends on what remains cached and on the cache-sharing topology.

Separate coherence from synchronization

Cache coherence prevents cores from indefinitely using conflicting cached copies of a single memory location. Bus snooping is one implementation idea: caches observe traffic and invalidate or update copies when another core writes. Larger systems can use other coherence mechanisms.

Coherence does not turn several instructions into one atomic operation. If two CPUs both read a queue length, alter entries, and write the length back, coherent individual reads and writes still allow harmful interleavings. The scheduler needs locks or another synchronization method for the whole update. A lock's shared cache line can itself move between cores as they compete for it.

Read the hardware layout
Hardware featureWhat the scheduler must consider
Simultaneous multithreading (SMT)Logical CPUs on one core share execution units and caches
Non-uniform memory access (NUMA)Memory near one socket can be faster to access than remote memory
Heterogeneous coresPerformance and efficiency cores offer different speed and energy trade-offs

Intel calls its SMT implementation Hyper-Threading. Two busy threads on sibling logical CPUs contend for one core's resources; two logical CPUs are not equivalent to two independent physical cores. A NUMA migration may also move computation away from the memory it uses, even when cache warm-up is brief.

Moving a thread to an idle CPU can eliminate a long queue delay. Keeping it in place can preserve locality. Compare those costs using the actual workload: affinity is a performance preference, while an explicit affinity mask restricts which CPUs are allowed at all.

Key Takeaways

  • Parallel speedup needs several runnable threads or programs.
  • SMP lets several CPUs make scheduling decisions.
  • Cache affinity preserves recently useful data and translations.
  • Coherence does not make a multi-step update atomic.
  • SMT, NUMA, and unequal core types affect placement costs.

5.2 Balance work without moving it constantly

A multiprocessor scheduler needs somewhere to hold ready work. A single shared queue makes work easy to find. Separate per-CPU queues reduce shared contention and preserve placement, but can leave one CPU overloaded while another is idle.

Compare queue designs
DesignMain advantageMain cost
Single queue (SQMS)Any eligible idle CPU can take waiting workQueue contention and weaker cache affinity
Multiple queues (MQMS)Local decisions scale and retain affinityLoad imbalance needs active correction

In single-queue multiprocessor scheduling, all CPUs draw from one shared queue. If jobs can run on every CPU, waiting work naturally fills an idle CPU. A shared lock protects the queue, so increasing CPU count can turn that lock into a bottleneck.

With five round-robin jobs A–E on four CPUs, one sequence assigns A, B, C, D in the first round; E, A, B, C in the second; and D, E, A, B in the third. A runs on CPU 0, then 1, then 2. The machine stays busy, but A repeatedly changes private caches. Affinity rules can retain most placements while moving selected jobs to balance work.

Notice unequal shares

In multi-queue multiprocessor scheduling, each CPU schedules its own queue. Suppose CPU 0 has A and C and CPU 1 has B and D, all CPU-bound and sharing locally in round robin. Initially each job gets half a CPU. When C finishes, A receives all of CPU 0 while B and D still receive half of CPU 1 each.

The machine remains fully utilized, but the jobs no longer get equal shares. If A also finishes, CPU 0 becomes idle even though B and D are ready. Moving one of them to CPU 0 gives both a full CPU and uses previously idle capacity.

With three equal CPU-bound jobs and two CPUs, equal long-run service is two-thirds of a CPU per job. A fixed placement leaves one job alone and two sharing. Periodically rotating which job is alone can approach the equal split. No one thread executes on both CPUs at once.

Decide when to migrate

Migration moves a task to another CPU's queue. Work stealing is a pull strategy: a CPU with little work examines a busier CPU's queue and takes work. Frequent checks create synchronization traffic; rare checks leave imbalance unresolved. Stealing also has to respect CPU eligibility and memory locality.

Compare expected saved waiting time with migration cost. A long queue on one CPU and an idle compatible CPU create a strong reason to move. A tiny temporary queue difference may disappear before cold-cache costs are recovered.

Linux's O(1) and CFS designs used per-CPU run queues; Linux balances across hardware scheduling domains, accounting for shared cores and sockets. The alternative BF Scheduler used a single queue. Users can constrain placement with taskset or sched_setaffinity() on Linux and SetThreadAffinityMask() on Windows. A restricted affinity mask can explain why a ready task does not use a CPU that appears idle.

Key Takeaways

  • A shared queue finds waiting work easily but needs shared synchronization.
  • Per-CPU queues preserve locality and reduce contention.
  • Full CPU utilization can coexist with unequal per-job shares.
  • Migration corrects imbalance at a cache and coordination cost.
  • Work stealing pulls tasks toward CPUs with spare capacity.
  • Affinity restrictions limit which idle CPUs can accept a task.
6

Read system settings and evaluate a policy

Real schedulers combine several ideas: priority classes, weighted shares, feedback after waits, and placement across CPUs. A setting can change precedence, share, or allowed placement, so identify which control you are reading before predicting its effect. Linux and Windows provide concrete examples. To choose a policy, connect those mechanisms to a workload and test both average results and the delays experienced by its least favored jobs.

6.1 Use Linux scheduling controls

Linux schedules threads, called tasks in the kernel. A task's scheduling policy, nice value, group controls, and CPU affinity answer different questions about when and where it runs.

Read the policy first
PolicySelection behavior
SCHED_OTHER and SCHED_BATCHNormal fair-class service, weighted by nice
SCHED_IDLEExtremely low-priority normal work; nice does not affect it
SCHED_FIFOReal-time priority, without a same-priority quantum
SCHED_RRReal-time priority, rotating equal-priority tasks by quantum
SCHED_DEADLINEDeadline-class service above the other classes

The normal policies have static priority 0. Real-time FIFO and RR use 1–99, where 99 is highest. A FIFO task continues until it blocks, yields, or is preempted by higher-priority work. RR adds turns among equal-priority tasks; sched_rr_get_interval() reports its quantum. These names describe Linux policies: normal fair scheduling is not the textbook equal-slice RR algorithm.

Change shares and placement

Nice runs from −20 to +19, with default 0. Larger values reduce fair-class weight, by roughly a factor of 1.25 per step. On a typical launch at nice 0, nice -n 10 make starts a build at nice 10; -n is an adjustment to inherited niceness. renice -n 5 -p 4321 sets the target process to nice 5. A user can make their own work less favored; increasing priority requires suitable privilege or an allowed resource limit.

taskset -c 0,1 ./app permits a program to run on CPUs 0 and 1. It does not create a second thread or promise either CPU exclusively. ps -o pid,cls,ni,rtprio,comm shows policy-related fields, while top helps observe priority, nice, and CPU consumption.

chrt -f 50 ./app selects FIFO real-time priority 50. Use real-time settings only in a controlled environment: a busy high-priority thread can delay the shell and essential system work. Default real-time bandwidth limits reserve some time for normal work, but do not make every such workload responsive. Precedence changes access to CPU service, not the speed of an instruction.

Distinguish group weight from quota

In cgroup v2, cpu.weight ranges from 1 to 10000, default 100, and divides contested fair-class CPU capacity among active sibling groups. Weights 200 and 100 give about two-thirds and one-third of one CPU when both groups are busy. If the second becomes idle, the first can use all available capacity.

cpu.max sets a bandwidth cap. The value "50000 100000" permits 50 ms of aggregate CPU time per 100 ms period, equivalent to half a CPU on average. Several threads can consume that budget in parallel and exhaust it sooner in elapsed time. A capped group can be throttled even when spare CPU capacity exists.

Place the names in history

Linux 2.6.0's O(1) scheduler used priority arrays and interactivity feedback. CFS arrived in 2.6.23 in 2007. Linux 6.6 in 2023 began the transition to EEVDF selection in the fair class. Since Linux 6.12 in 2024, sched_ext supports dynamically loaded BPF scheduling policies on configured kernels. If such a scheduler fails or stalls runnable work, the kernel restores built-in scheduling.

Key Takeaways

  • Policy class determines precedence before nice is interpreted.
  • Nice adjusts relative fair-class share; affinity restricts allowed CPUs.
  • SCHED_IDLE ignores nice.
  • A cgroup weight shares contested capacity; a quota caps aggregate CPU service.
  • EEVDF changes fair-class selection, while sched_ext supports replaceable policies.

6.2 Follow Windows priorities and feedback

Windows schedules ready threads by priority from 0 through 31, with larger numbers higher. Equal-priority ready threads rotate in round robin. A newly ready higher-priority thread preempts a lower one without waiting for its quantum to end. Priority 0 belongs to the zero-page thread, which clears free pages.

Find base priority from two settings

A thread's base priority depends on its process's priority class and its own relative thread level. Process classes are Idle, Below normal, Normal, Above normal, High, and Realtime. Thread levels include Idle, Lowest, Below normal, Normal, Above normal, Highest, and Time critical.

Process classThread levelBase priority
NormalNormal8
NormalHighest10
HighNormal13
RealtimeNormal24

Time critical gives 15 outside Realtime class and 31 within it. Idle thread level gives 1 outside Realtime and 16 within it. These boundary levels are special table entries, so adding a fixed offset to every class would give wrong results.

Follow a temporary boost

Priorities 1–15 are the variable range; 16–31 are the real-time range. A thread starts with dynamic priority equal to base priority. For variable-range threads, events such as input or completion of a wait can temporarily raise dynamic priority. Threads with real-time base priorities receive no such boosts.

Suppose a thread with base priority 8 is boosted to 14. If it keeps computing, its dynamic priority falls one level after each complete quantum: 13 after the first, 12 after the second, and 8 after the sixth. The boost does not permanently change base priority and does not decay below that base.

This is feedback: recently unblocked work gets prompt service, while sustained CPU use loses the temporary advantage. Windows also uses temporary boosts for long-waiting ready threads to address starvation. Such a boost can help a low-ranked lock holder make progress, but it is a different mechanism from lock-specific priority inheritance.

Recognize related designs

Solaris's time-sharing class is a table-driven MLFQ design. FreeBSD's ULE uses per-CPU run queues and compares sleep with running behavior to identify interactive threads. These systems share the idea of adapting service to observed behavior without using identical queue rules.

macOS provides quality-of-service (QoS) classes, including user-interactive, user-initiated, default, utility, and background. They describe the urgency of work. On Apple silicon, QoS helps the system place work across performance and efficiency cores. Programs communicate the work's importance; the operating system chooses placement according to policy and available hardware.

Real schedulers combine feedback, priorities, fairness, and affinity. A Windows Realtime class has stronger precedence, not a guaranteed faster computation or a complete real-time correctness guarantee.

Key Takeaways

  • Windows priority numbers increase with precedence.
  • Base priority combines process class with relative thread level.
  • Variable-range boosts decay one level per full quantum toward base.
  • Real-time base priorities do not receive dynamic boosts.
  • Solaris, ULE, and macOS use related ideas with different mechanisms.
  • QoS communicates work urgency and helps guide placement.

6.3 Choose a policy and test its consequences

Choose the workload's objective before choosing a scheduler. A batch queue may value quick completion of many small jobs. An editor needs prompt service after input. A shared server needs a defensible allocation among users or groups.

Match the mechanism to the objective
Workload needSuitable mechanismTrade-off to inspect
Low average batch turnaroundSJF or STCF with known or predicted burstsPrediction error and starvation
Prompt interactive servicePreemption with feedback or latency-aware fair selectionSwitching cost and tail delays
Proportional access among usersTickets, strides, or group weightsShort-window fairness and group allocation
Long CPU-bound computationEnough service per turn to amortize switchingResponsiveness of competing work
Time-critical device workAppropriate real-time policiesInterference with other tasks
Compare policies on identical inputs

A arrives at 0 ms needing 8 ms, B at 1 ms needing 4 ms, and C at 2 ms needing 2 ms. Ignore switching cost. FIFO runs A, B, C. SJF also starts A, but then runs C before B. STCF runs A 0–1, B 1–2, C 2–4, B 4–7, A 7–14. RR uses a 2 ms quantum with boundary arrivals queued before the expired task.

PolicyAverage turnaroundAverage first-run response
FIFO10.33 ms5.67 ms
SJF9.67 ms5 ms
STCF7.33 ms0 ms
RR9 ms1 ms

STCF wins both metrics on this workload because each newly arriving shorter job immediately runs. RR gives a quick start without knowing burst lengths. With equal-length simultaneous arrivals, FIFO can have lower average turnaround than RR. A ranking on one workload is evidence about that workload.

Choose an evaluation method

Deterministic modeling calculates a fixed trace by hand. It gives exact results for its inputs and makes decisions easy to inspect, but often leaves out dispatch and cache costs. Queueing models describe arrival and service patterns using distributions and predict average behavior.

For a stable system in steady state, Little's law links average population n, arrival rate λ, and average residence time W:

n=λW

At 14 jobs/s and 0.5 s average time in the system, the average population is 7 jobs. Keep the boundary consistent: a ready-queue population needs time waiting in that queue, while a whole-system population needs time in the whole system. Convert units before multiplying.

Simulation executes a scheduler model, often against a recorded workload trace. It can test complicated arrival and blocking patterns, but its conclusions depend on the model and the chosen traces. Implementation measures the scheduler in a real operating system and includes actual overhead; it takes more effort and still needs representative workloads and repeatable measurements.

Inspect throughput, utilization, individual and tail delays, fairness, and energy use alongside means. On a multiprocessor, a busy machine can still divide service unevenly or waste time refilling caches. Compare policies using the same observation window and workload, then vary the workload features that matter to the intended users.

Key Takeaways

  • Choose metrics to match the workload’s actual needs.
  • Compare policies on identical arrivals and CPU demands.
  • A workload-specific ranking does not establish a universal winner.
  • Little’s law requires a stable system and matching population/time boundaries.
  • Simulation depends on the model; implementation includes real overhead.
  • Evaluate tail delays, fairness, throughput, and energy alongside averages.

CPU Scheduling examples

6 Walkthroughs

1

From ready states to measured delays

11 steps
Follow a scheduling decision, then extract response, waiting, and turnaround from one timeline.
  1. 1
    IntroductionFollow the CPU handoff

    A running job starts a disk read while another job is ready. The operating system can use that waiting period to advance other work. We will follow the state changes first (a job is ready, running, or blocked), then read a short CPU timeline to measure what each job experienced: response, waiting, and turnaround.

    Keep two questions separate as you work: who can run now, and what delay should a metric count? A job may have a quick first turn but still finish much later.

  2. 2
    ExplanationChoose among jobs that can execute

    The scheduler selects ready work. A running task already has a CPU; a blocked task must wait for its event. When the read starts, its caller becomes blocked and releases the CPU. When the read completes, it becomes ready again.

    The completed read creates a selection opportunity. Whether the returning task runs immediately depends on the policy and on other ready work.

  3. 3
    ConnectionSeparate the choice from the switch

    The policy chooses the next ready task. The dispatcher saves the old state, restores the chosen state, and resumes execution. Its latency and the next task’s cache refills cost time.

    A timer can return control to the kernel even when a program never yields. A device interrupt can also make favored work ready. Preemption preserves the interrupted task for a later turn.

  4. 4
    ChallengeCan the waiting editor preempt?

    An editor is blocked on input while a CPU-bound task runs. The editor has higher priority. Can it take the CPU before input arrives? Explain the state that matters.

    ---reveal---

    No. The editor is blocked and cannot execute until its input event occurs. After input makes it ready, a preemptive priority scheduler can choose it. Priority ranks ready work; it does not remove the event dependency.

  5. 5
    ExampleDraw the service intervals

    A arrives at 0 ms needing 5 ms, B at 2 ms needing 3 ms, and C at 4 ms needing 1 ms. They are CPU-only jobs. FIFO with no switching cost runs A 0–5, B 5–8, then C 8–9.

    Record first-run times 0, 5, and 8 ms and completion times 5, 8, and 9 ms. These are timestamps. We next subtract each job’s own arrival to turn them into delays.

  6. 6
    ExampleMeasure completion delay

    Turnaround runs from arrival through completion. For the timeline, A’s turnaround is 5 ms, B’s is 6 ms, and C’s is 5 ms.

    The mean is:

    (5+6+5)/3=16/3≈5.33 ms.

    B’s completion timestamp is 8 ms, but it has been in the system for only 6 ms because it arrived at 2 ms. Measuring every job from the beginning of the chart would overstate later arrivals’ delays.

  7. 7
    ExampleMeasure the first turn and total waiting

    Response ends when the job first runs. A waits 0 ms for that first turn, B waits 3 ms, and C waits 4 ms. Their average response is about 2.33 ms.

    Here response equals total waiting because each CPU-only job runs without interruption once selected. Under preemption, later ready intervals also count as waiting. A blocked I/O interval counts toward turnaround, but not toward ready-queue waiting.

  8. 8
    ChallengeCalculate a preempted job’s delays

    Task R arrives at 1 ms, first runs at 4 ms, and finishes at 15 ms. It uses 6 ms of CPU with no I/O. Find response, turnaround, and waiting.

    ---reveal---

    Response is 3 ms and turnaround is 14 ms. Subtracting 6 ms of service from turnaround gives 8 ms of total waiting. The initial 3 ms is only part of that waiting; another 5 ms occurs after the first turn.

  9. 9
    Key InsightMeasure the machine and the individual

    Our FIFO trace finishes three jobs in 9 ms with no idle time. Its throughput is about 333.33 jobs/s and its CPU utilization is 100% over that interval. These machine-wide figures do not describe every job’s experience.

    Inspect individual delays and a high percentile when users care about rare long waits. Fairness also asks whether ready work receives service, including jobs hidden behind a favorable average.

  10. 10
    ChallengeUse a blocked interval correctly

    A task arrives at 0 ms, runs 0–2, waits for a device 2–7, waits ready 7–10, and runs 10–12 to finish. What are its response and waiting times?

    ---reveal---

    Response is 0 ms because the task runs immediately. Waiting is 3 ms, the ready interval 7–10. Its 12 ms turnaround also contains 4 ms of CPU and 5 ms blocked. Calling all 8 ms outside CPU execution “waiting” would mix two process states.

  11. 11
    RecapCheck state before counting time

    For a new trace, identify ready work at each event, record service intervals, then extract first-run and completion timestamps. Subtract arrivals before averaging. Keep blocked time separate when measuring ready-queue waiting.

2

Build schedules from the policy rule

17 steps
Compare selection rules, preemptions, round-robin turns, and priority dependencies through worked timelines.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionOne workload, several choices
  2. 2
    ExampleStart with arrival order
  3. 3
    ExampleLet short work finish first
  4. 4
    ChallengePredict the next burst
  5. 5
    ExampleStop the long job for a shorter arrival
  6. 6
    ExampleFinish the remaining work
  7. 7
    ChallengeCompare against what is left
  8. 8
    ConnectionLet blocked work create capacity
  9. 9
    ExampleRotate two equal jobs
  10. 10
    ExampleCalculate completion under rotation
  11. 11
    ChallengePlace a boundary arrival
  12. 12
    Key InsightPay for every handoff
  13. 13
    ExampleRead rank before running
  14. 14
    ExampleFollow the lock holder
  15. 15
    ChallengeChoose the useful priority change
  16. 16
    ChallengeChoose response or completion
  17. 17
    RecapTurn a rule into a timeline
3

Trace feedback and catch gaming

12 steps
Follow a job through queue levels, then repair strategic yielding and long waits with accounting and boosts.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionLearn without a future burst length
  2. 2
    ExplanationUse one queue and two service limits
  3. 3
    ExampleLet sustained CPU use move down
  4. 4
    ExampleGive the newcomer its early chance
  5. 5
    ChallengePreserve an interrupted allotment
  6. 6
    ExampleExpose the early-yield loophole
  7. 7
    ExampleKeep the service history
  8. 8
    ChallengeCount only CPU consumption
  9. 9
    ExplanationGive old work a fresh opportunity
  10. 10
    ChallengeSeparate the two repairs
  11. 11
    ConnectionTune turns separately from classification
  12. 12
    RecapTrack the evidence that changes priority
4

Account for proportional CPU service

16 steps
Turn tickets into probabilities and strides, then follow weighted virtual progress and EEVDF eligibility.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionStart with an entitlement
  2. 2
    ExampleRead the ticket intervals
  3. 3
    Key InsightExpect variation over short windows
  4. 4
    ChallengeConvert a local allocation
  5. 5
    ConnectionLet a service inherit the client’s claim
  6. 6
    ExampleCalculate inverse-ticket strides
  7. 7
    ExampleBring weighted progress back together
  8. 8
    ChallengePlace a new stride task
  9. 9
    ExplanationCharge real service in virtual units
  10. 10
    ExampleSplit a target period
  11. 11
    TipRead nice as a weight input
  12. 12
    ConnectionFind the minimum efficiently
  13. 13
    ExplanationFilter eligibility before deadlines
  14. 14
    ChallengeApply both EEVDF comparisons
  15. 15
    ChallengePreserve share while changing request size
  16. 16
    RecapSeparate allocation from selection
5

Balance CPU load while keeping useful locality

11 steps
Inspect hardware costs, compare queue designs, and decide when moving ready work helps.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionA second CPU adds a placement choice
  2. 2
    ExplanationRecognize the available parallelism
  3. 3
    ExampleKeep a recently used working set
  4. 4
    ChallengeDoes coherence protect the whole update?
  5. 5
    ExplanationChoose a queue layout
  6. 6
    ExampleSpot unequal service on busy CPUs
  7. 7
    ExampleRotate placement to equalize service
  8. 8
    ChallengeUse an idle CPU legally
  9. 9
    Key InsightTrade recovery cost for saved delay
  10. 10
    ChallengeDecide whether the move saves time
  11. 11
    RecapCheck capacity, eligibility, and locality
6

Read system controls and assess a scheduler

15 steps
Interpret Linux and Windows behavior, then choose a measurement boundary and evaluate evidence.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionRead each control at its own layer
  2. 2
    ExplanationCheck the Linux policy class
  3. 3
    ExampleDistinguish share from placement
  4. 4
    ExampleApply group weights under competition
  5. 5
    ChallengeRead an aggregate quota
  6. 6
    ConnectionRecognize the scheduler generation
  7. 7
    ExplanationMap Windows settings to base rank
  8. 8
    ExampleLet a temporary boost decay
  9. 9
    ChallengeCheck the boost range
  10. 10
    ConnectionRecognize related feedback ideas
  11. 11
    ExplanationChoose the measurement that matters
  12. 12
    ExampleKeep Little’s law inside one boundary
  13. 13
    ChallengeRecover waiting from population
  14. 14
    ChallengeExplain an apparent performance win
  15. 15
    RecapConnect a setting to a measured effect

CPU Scheduling practice questions

50 Practice Questions in 5 sets

Set 1: Read decisions and trace CPU service10 Practice Questions

Question 1 of 10

An editor is waiting for a disk read, a compiler is ready, and a viewer has finished. Which task can the CPU scheduler select now?
  1. The editor.
  2. The compiler.
  3. The viewer.
  4. The editor and compiler.
Show answerHide answer
Answer: B
The compiler is ready and can execute as soon as it is selected. The editor must wait for its disk event before becoming a candidate. Having unfinished work is not enough: blocked work cannot use the CPU yet.

Question 2 of 10

A CPU-only task arrives at 4 ms, first runs at 9 ms, and completes at 22 ms after using 10 ms of CPU. What are its response and total waiting times?
  1. Response 9 ms; waiting 12 ms.
  2. Response 5 ms; waiting 18 ms.
  3. Response 8 ms; waiting 5 ms.
  4. Response 5 ms; waiting 8 ms.
Show answerHide answer
Answer: D
Response is the first-run delay: 9 minus 4 gives 5 ms. Turnaround is 22 minus 4, or 18 ms, so waiting is 18 minus 10, or 8 ms. Using the first-run delay for all waiting would miss the 3 ms spent ready after the first dispatch.

Question 3 of 10

Three CPU-only jobs arrive together: A needs 18 ms, B 4 ms, and C 8 ms. What is their average turnaround under non-preemptive SJF with zero switching cost?
  1. 15.33 ms.
  2. 10.00 ms.
  3. 20.67 ms.
  4. 24.67 ms.
Show answerHide answer
Answer: A
SJF runs B, C, then A, giving completion times of 4, 12, and 30 ms. Since all arrivals are zero, their average turnaround is 46 divided by 3, or 15.33 ms. Averaging the burst lengths gives 10 ms, which leaves out time spent behind earlier work.

Question 4 of 10

A burst predictor has an estimate of 20 ms and uses a newest-measurement weight of 0.25. It observes bursts of 8 ms and then 12 ms. What is its prediction after both observations?
  1. 17.00 ms.
  2. 14.00 ms.
  3. 15.75 ms.
  4. 13.50 ms.
Show answerHide answer
Answer: C
The first update is 0.25 times 8 plus 0.75 times 20, giving 17 ms. The second uses that updated estimate: 0.25 times 12 plus 0.75 times 17 gives 15.75 ms. Reusing the original 20 ms estimate would discard the first observation’s effect.

Question 5 of 10

CPU-only jobs are A (arrival 0 ms, demand 10 ms), B (2 ms, 4 ms), and C (3 ms, 2 ms). Under STCF, what is the average turnaround? Ignore switching costs.
  1. 7.00 ms.
  2. 9.33 ms.
  3. 8.00 ms.
  4. 8.67 ms.
Show answerHide answer
Answer: C
A runs 0–2, B 2–3, C 3–5, B 5–8, and A 8–16. Turnarounds are 16, 6, and 2 ms, averaging 8 ms. Letting B finish before considering C misses the second preemption: at 3 ms, B still needs 3 ms and C needs only 2 ms.

Question 6 of 10

At 0 ms, task D begins a 7 ms device operation and blocks. Task E is ready and needs 5 ms of CPU, with no I/O. If the CPU is work-conserving and switching costs are zero, when does E finish?
  1. At 7 ms.
  2. At 12 ms.
  3. At 2 ms.
  4. At 5 ms.
Show answerHide answer
Answer: D
E can use the CPU immediately while D’s device operation proceeds, so its five milliseconds of service finish at 5 ms. Waiting until D’s operation ends would produce 12 ms, but D is blocked and does not occupy the CPU. Device time and another task’s CPU time can overlap.

Question 7 of 10

Round robin uses a 3 ms quantum. A arrives at 0 ms needing 7 ms, B at 1 ms needing 4 ms, and C at 3 ms needing 2 ms. A boundary arrival joins before the expired job. When does A finish? Ignore switching cost.
  1. At 13 ms.
  2. At 10 ms.
  3. At 11 ms.
  4. At 12 ms.
Show answerHide answer
Answer: A
The turns are A 0–3, B 3–6, C 6–8, A 8–11, B 11–12, and A 12–13. A needs its last millisecond after B’s final turn, so it completes at 13 ms. Placing A before the boundary arrival C incorrectly changes the queue after the first slice.

Question 8 of 10

A repeating scheduling cycle contains 3.8 ms of useful CPU work followed by a 0.2 ms switch. What fraction of elapsed time is switching overhead?
  1. 5.26%.
  2. 5%.
  3. 0.05%.
  4. 95%.
Show answerHide answer
Answer: B
The whole cycle lasts 4 ms, of which 0.2 ms is switching, so the fraction is 0.05, or 5%. Dividing by only the 3.8 ms of useful work gives about 5.26%, but that is a ratio to useful work rather than the requested fraction of total elapsed time.

Question 9 of 10

Ready jobs P, Q, R, and S have textbook priorities 7, 2, 5, and 9. Smaller numbers mean higher priority. Which runs first under priority scheduling?
  1. P.
  2. R.
  3. S.
  4. Q.
Show answerHide answer
Answer: D
Q has the smallest priority number and therefore the highest rank on this scale. Priority scheduling selects it before P, R, or S, regardless of their names. Choosing S from the largest number applies the Windows direction to a scale explicitly defined the other way.

Question 10 of 10

A running task voluntarily starts a read and becomes blocked. Another ready task is selected. Does this handoff require preemptive scheduling?
  1. Yes; every switch is preemption.
  2. No; blocking releases the CPU.
  3. Yes; I/O is a timer event.
  4. No; the blocked task still runs.
Show answerHide answer
Answer: B
A blocked task cannot continue executing, so even a non-preemptive scheduler can choose another job. Preemption specifically takes the CPU from a task that remains able to run. Calling every context switch preemption confuses the switching mechanism with the reason for the handoff.
Set 2: Track priorities, allotments, and feedback10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

Two stride jobs have equal pass values. Job A has 20 tickets and job B has 40, with stride constant 800. After A receives one slice, what is its pass increase?
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A high-priority thread waits for a lock held by a low-priority thread, while a medium-priority thread keeps running. What is this scheduling problem called?
  1. Priority aging.
  2. Round-robin rotation.
  3. Priority inversion.
  4. CPU load imbalance.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A ready job starts at priority 12, with smaller numbers higher. Aging improves its priority by one every 15 ms of ready waiting. At 90 ms, what is its rank relative to a ready priority-5 job?
  1. Priority 6; it still ranks lower.
  2. Priority 5; they now tie.
  3. Priority 6; it now ranks higher.
  4. Priority 7; it still ranks lower.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

An MLFQ level has a 4 ms quantum and a 10 ms cumulative allotment. A task uses 4 ms, later 3 ms, and then resumes. How much CPU service remains before demotion?
  1. 4 ms.
  2. 3 ms.
  3. 6 ms.
  4. 7 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

An MLFQ has Q2 above Q1 above Q0, with 4 ms quanta and 4 ms allotments at each level. A arrives at 0 ms needing 15 ms; B arrives at 6 ms needing 3 ms. There are no boosts or switch costs. When does A first run in Q0?
  1. At 8 ms.
  2. At 9 ms.
  3. At 12 ms.
  4. At 11 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A task runs 5 ms, blocks for 1 ms, and repeats. Its top-level allotment is 8 ms, with cumulative CPU accounting and no boosts. During which CPU burst is it first demoted?
  1. During its second burst.
  2. After its first full burst.
  3. During its third burst.
  4. It keeps top priority indefinitely.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

An MLFQ job is in Q1 with 7 ms of its 12 ms allotment used. It runs 3 ms, blocks for 5 ms, then runs again. No boost occurs. At what elapsed time from the start of these events is it demoted?
  1. At 5 ms.
  2. At 8 ms.
  3. At 13 ms.
  4. At 10 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A CPU-bound job waited in the bottom queue, but now handles short bursts after input. What MLFQ mechanism lets its new behavior be learned from the top again?
  1. A longer bottom quantum.
  2. A larger bottom allotment.
  3. A periodic priority boost.
  4. A reset on each early yield.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

Three runnable lottery jobs hold 40, 60, and 100 tickets. What is the second job’s chance of winning the next draw?
  1. 20%.
  2. 30%.
  3. 40%.
  4. 60%.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A user has 120 global tickets and gives local jobs L and M 1 and 3 local tickets. A second user has 80 global tickets for one runnable job. All jobs remain runnable. If the first user doubles both local allocations, what is L’s expected system-wide CPU share?
  1. 15%.
  2. 25%.
  3. 30%.
  4. 7.5%.
Show answerHide answer

Save this lesson to see this answer.

Set 3: Follow ticket and virtual-time accounting10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

Lottery jobs A, B, and C hold 35, 25, and 40 tickets in that order. Tickets start at zero. Which job wins a draw of 60?
  1. A.
  2. B.
  3. B and C tie.
  4. C.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A lottery job owns 20% of all runnable tickets and wins 2 of the first 20 equal slices. What can be concluded about this result?
  1. Its ticket share must now be 10%.
  2. It can occur under a fair draw.
  3. Its next two wins are guaranteed.
  4. The lottery must be implemented wrong.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

User X has 180 global tickets, split locally as A:2 and B:1. User Y has 120 global tickets for C. All three jobs are runnable. X changes only A’s local count from 2 to 5. What is B’s new expected system share?
  1. 20%.
  2. 16.67%.
  3. 10%.
  4. 8.33%.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

Stride jobs A, B, and C have 30, 60, and 20 tickets, with constant 600 and all passes initially zero. Break ties alphabetically. What is the first six-job selection sequence?
  1. A, B, C, B, A, B.
  2. A, B, C, A, B, C.
  3. A, B, C, B, C, A.
  4. A, B, C, B, B, A.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

Existing stride passes are 420, 440, and 460. A new task is initialized to the current minimum pass. What is its initial pass?
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Stride jobs A and B have strides 15 and 40, both starting at pass zero. Break ties alphabetically. By the first time their pass values become equal again, how many slices has A received?
  1. 3 slices.
  2. 8 slices.
  3. 5 slices.
  4. 11 slices.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A classic CFS model has task weights 1024 and 512 and a 30 ms target period, with no minimum-granularity constraint active. What nominal slice does the lighter task receive?
  1. 5 ms.
  2. 15 ms.
  3. 20 ms.
  4. 10 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A task of weight 256 runs for 2 real ms in a classic CFS model. How much virtual runtime does it gain?
  1. 0.5 virtual ms.
  2. 2 virtual ms.
  3. 8 virtual ms.
  4. 4 virtual ms.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

An EEVDF decision sees A with lag −1 and virtual deadline 6, B with lag 2 and deadline 12, and C with lag 0 and deadline 9. Which task runs next?
  1. A.
  2. C.
  3. B.
  4. A and C tie.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Two always-runnable equal-weight fair-class tasks compete on one CPU. One requests shorter EEVDF slices. What should change without changing its weight?
  1. Its share doubles; its latency stays equal.
  2. Its share shrinks; its deadlines stay equal.
  3. Its latency stays equal; its share becomes random.
  4. Its latency can improve; its share stays equal.
Show answerHide answer

Save this lesson to see this answer.

Set 4: Place work and interpret Linux controls10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A program has one runnable thread and no helper processes. How many logical CPUs can execute that thread at the same instant?
  1. One.
  2. Two.
  3. All CPUs in its affinity mask.
  4. All CPUs sharing its cache.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

Two CPUs each read a shared queue length, alter an entry, then write an updated length. Their caches are coherent. What else is needed to protect the update?
  1. A cache flush before each queue read.
  2. A longer time quantum for every task.
  3. Synchronization spanning the queue operation.
  4. A duplicate private queue length only.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

Two identical CPUs serve equal CPU-bound jobs A, B, and C. For 12 ms A runs alone while B and C share the other CPU equally. For the next 6 ms B runs alone while A and C share; for the final 6 ms C runs alone while A and B share. Ignoring costs, what is the largest minus smallest per-job CPU service after 24 ms?
  1. 0 ms.
  2. 6 ms.
  3. 12 ms.
  4. 3 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

Three CPU-only jobs are ready at 0 ms: A needs 8 ms, B 2 ms, and C 6 ms. A and B may run only on CPU 1; C may run on CPU 0 or 1. Both CPUs are identical and work-conserving, with local SJF and free migration. What is the lowest achievable average turnaround?
  1. 5.33 ms.
  2. 6 ms.
  3. 8 ms.
  4. 8.67 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A program is launched from a shell at nice 0 with nice -n 8 ./worker. Under normal fair scheduling with busy peers, what does the command change?
  1. The worker becomes more favored.
  2. The worker becomes less favored.
  3. The worker enters real-time priority 8.
  4. The worker is limited to 8% of one CPU.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Two sibling cgroups share one CPU. A has weight 300 and quota 40 ms per 100 ms; B has weight 100 and no quota. Both are always busy. Ignore overhead. What average allocation is feasible over full quota periods?
  1. A 75%; B 25%.
  2. A 40%; B 25%.
  3. A 40%; B 60%.
  4. A 30%; B 70%.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A cgroup has cpu.max set to "60000 100000". At the start of a fresh period, two threads in it run simultaneously on two CPUs. After how much elapsed running time do they exhaust the budget?
  1. 30 ms.
  2. 60 ms.
  3. 100 ms.
  4. 120 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

Two ready Linux real-time tasks can run on the same CPU: one uses SCHED_FIFO at priority 35, the other SCHED_RR at priority 45. Which has higher precedence?
  1. The FIFO task at priority 35.
  2. Neither; they share the CPU.
  3. The lower-nice-value task.
  4. The RR task at priority 45.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A Windows thread has base priority 10 and is boosted to dynamic priority 14. It then uses three full quanta with no further boosts. What is its dynamic priority?
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A stable ready queue receives 250 jobs/s and has an average of 5 waiting jobs. Each job uses 8 ms of CPU after leaving the queue, with no other delay. What is its mean arrival-to-completion time?
  1. 28 ms.
  2. 20 ms.
  3. 8 ms.
  4. 12 ms.
Show answerHide answer

Save this lesson to see this answer.

Set 5: Compare system behavior and evaluate evidence10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A Windows process has Normal priority class and a thread at Highest relative level. What base priority does that combination have?
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A Windows thread has base priority 18 and finishes a keyboard wait. Does the normal dynamic-boost mechanism raise it?
  1. Yes; keyboard completion always gives a boost.
  2. No; its base is in the real-time range.
  3. No; only CPU-bound threads get boosts.
  4. Yes; its base becomes 31 permanently.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

CPU-only jobs A and B arrive together, needing 6 ms and 2 ms. Alphabetical ties put A first in FIFO and RR. Compare FIFO with 2 ms RR, ignoring switching costs. How does RR change average response and turnaround?
  1. Response improves by 2 ms; turnaround improves by 1 ms.
  2. Response improves by 1 ms; turnaround worsens by 2 ms.
  3. Response improves by 2 ms; turnaround worsens by 1 ms.
  4. Response worsens by 2 ms; turnaround improves by 1 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A stable system averages 6 jobs in residence and completes 15 jobs/s, matching its arrival rate. What is the average residence time?
  1. 2.50 s.
  2. 0.90 s.
  3. 0.10 s.
  4. 0.40 s.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

Two RR designs use useful quanta of 0.9 ms and 4.9 ms. Every full quantum is followed by a 0.1 ms switch. Useful execution completes 2 records per CPU millisecond. Which design reaches at least 1900 records/s, and what throughput does it achieve? Assume full quanta repeat continuously.
  1. The 0.9 ms design; 2000 records/s.
  2. Both designs; 2000 records/s each.
  3. The 4.9 ms design; 1900 records/s.
  4. The 4.9 ms design; 1960 records/s.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

An MLFQ uses two queues. Top quantum and allotment are 3 ms; bottom quantum is 6 ms. At 0 ms A and B are boosted to the top in that order, with 10 ms and 4 ms left. No arrivals, further boosts, or costs occur. When does B finish?
  1. At 7 ms.
  2. At 10 ms.
  3. At 13 ms.
  4. At 14 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A migration takes 2 ms to recover useful cache contents. Staying in the current queue means waiting 9 ms; moving to an eligible idle CPU has no other delay. What direct waiting-and-recovery advantage does migration offer?
  1. 7 ms.
  2. 11 ms.
  3. 9 ms.
  4. 2 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

Two always-runnable fair tasks have weights 2048 and 1024 on one CPU. Each receives service until both have gained 12 virtual ms from equal starting values. How much real CPU service has the heavier task received?
  1. 6 ms.
  2. 24 ms.
  3. 12 ms.
  4. 36 ms.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

An active sched_ext BPF scheduler stalls a runnable task and the kernel detects the failure. What recovery does the interface provide?
  1. Keep it active and increase all nice weights.
  2. Move every affected task to SCHED_FIFO.
  3. Abort it and restore built-in fair scheduling.
  4. Block its tasks until the BPF policy is reloaded.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Policy X gives lower average response than policy Y, but one long ready job never runs under X during an ongoing stream of short arrivals. What additional property needs investigation?
  1. Starvation resistance.
  2. Arrival time precision.
  3. Equal program sizes.
  4. Peak device throughput.
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

87 Key Terms, each with its definition

A

Aging
Aging is a gradual improvement in a waiting job’s priority, intended to let long-waiting work compete and resist starvation.
Aging lifts a long-waiting batch job toward the rank of foreground work that keeps arriving.
Allotment
An allotment is the total CPU service a task may consume at an MLFQ level before demotion, possibly across several turns.
The 15 ms allotment permits three complete 5 ms quanta at the same priority level.
Amortization
Amortization spreads a fixed cost over enough useful work that the cost becomes a smaller fraction of the total time.
Longer service turns improve amortization of cache refill costs after a switch.

B

Base priority
A Windows thread’s base priority is its baseline rank, obtained by combining its process priority class with its relative thread level.
The Normal process class and Highest thread level give a Windows base priority of 10.
Blocked state
The blocked state is the condition of a task that cannot proceed until an event, such as completion of an I/O request, occurs.
The editor enters the blocked state while waiting for the next keyboard event.
Boost period
A boost period is the elapsed interval between MLFQ-wide priority resets, balancing fresh opportunities against useful priority separation.
A very short boost period repeatedly returns long computations to the interactive queues.

C

Cache affinity
Cache affinity is the preference for running a task near its recent CPU placement so it can reuse warm caches and translations.
Cache affinity can favor core 2 after a short preemption of a thread that was sorting there.
Cache coherence
Cache coherence keeps cached copies of individual memory locations consistent across cores, without making multi-step operations atomic.
Cache coherence cannot protect a multi-instruction shared-queue update from harmful interleaving.
CFS
CFS is Linux’s classic fair scheduler, introduced in 2.6.23, whose task selection favors the smallest weighted virtual runtime.
CFS charges a lighter task more virtual runtime for the same amount of real CPU service.
Control group
A control group is a Linux grouping of processes or threads to which controllers apply resource allocation and consumption policies.
A control group lets a service’s CPU budget cover several cooperating worker processes.
Convoy effect
The convoy effect is the delay suffered by short tasks queued behind a long CPU burst, producing poor average completion times.
The convoy effect is visible when several tiny jobs finish only after the first large job.
CPU affinity
CPU affinity constrains or favors the processors on which a task executes; an explicit mask specifies which CPUs are allowed.
CPU affinity restricted to core 0 explains why the ready task cannot use idle core 1.
CPU burst
A CPU burst is a stretch of computation between waits or completion, used to describe how a task demands CPU service.
A text editor’s CPU burst after input can be much shorter than a video encoder’s burst.
CPU scheduler
A CPU scheduler is the operating-system component that chooses which ready process or thread should execute next on a CPU.
The CPU scheduler selects the editor after a completed read makes its next burst ready.
CPU utilization
CPU utilization is the fraction of an observation interval during which a CPU is busy, which can include kernel overhead.
A CPU with a long ready queue reaches 100% CPU utilization even though several of its jobs get poor response.
CPU-bound job
A CPU-bound job needs long stretches of computation, with relatively few waits for input or devices between CPU bursts.
A CPU-bound job such as video encoding can use each available turn for a long period.
cpu.max
The cpu.max setting caps a cgroup v2 group’s aggregate CPU service within each configured bandwidth period.
A cpu.max quota can throttle a group after its workers jointly consume the period’s budget.
cpu.weight
The cpu.weight setting assigns a cgroup v2 group a relative fair-service weight when it competes with active sibling groups.
A service with cpu.weight 300 competes for about three times the service of a busy sibling at 100.
Cumulative accounting
Cumulative accounting adds a task’s CPU use across turns at one priority level so blocking or yielding cannot erase consumed allotment.
Cumulative accounting demotes the task even though none of its individual bursts lasts a full quantum.

D

Demotion
Demotion is movement to a lower-priority MLFQ level after a task consumes the service allotment assigned to its current level.
Demotion leaves the long computation behind newly ready work in a higher queue.
Deterministic modeling
Deterministic modeling evaluates scheduling policies against one fixed workload with specified arrival times, demands, and modeled costs.
Deterministic modeling makes every scheduling choice inspectable but establishes results for only that trace.
Device interrupt
A device interrupt signals an event such as I/O completion, allowing the kernel to make waiting work ready again.
A device interrupt signaling that an editor’s read has finished changes that editor from blocked to ready.
Dispatch latency
Dispatch latency is the delay involved in handing CPU execution from one task to the task chosen by the scheduler.
A shorter quantum makes dispatch latency a larger fraction of each service cycle.
Dispatcher
The dispatcher is the mechanism that carries out a scheduling choice by saving and restoring task state and resuming execution.
The dispatcher restores the chosen thread’s registers before returning to its user code.
Dynamic priority
A Windows thread’s dynamic priority is its current scheduling rank, which can rise temporarily above base in the variable range.
The thread’s dynamic priority drops toward its base after each full boosted quantum.

E

EEVDF
EEVDF is fair-class selection that chooses the earliest virtual deadline among tasks eligible because they are not ahead of entitlement.
EEVDF can favor an eligible short request without increasing the task’s long-run weighted share.
Exponential averaging
Exponential averaging predicts a next CPU burst by combining a fixed fraction of the latest measurement with the previous estimate.
With exponential averaging, a larger measurement weight makes predictions react faster to new bursts.

F

FIFO
FIFO is a non-preemptive policy that selects ready tasks in arrival order and lets a running CPU burst continue until it ends or yields.
Under FIFO, a short newly arrived burst waits behind the long burst already executing.

I

I/O overlap
I/O overlap occurs when the CPU executes one task while a device operation requested by another task is still in progress.
I/O overlap lets the compiler make progress during the editor’s disk read.
I/O-bound job
An I/O-bound job has frequent short CPU bursts separated by device or input waits, often needing prompt service when it becomes ready.
An I/O-bound job such as an editor may run briefly after each keypress, then block again.
Interactive job
An interactive job frequently responds to input or other events with short CPU bursts separated by periods of waiting.
An interactive job may spend most elapsed time blocked while needing prompt service after each input.

L

Lag
Lag is the difference between the CPU service a task is entitled to and the service it has received, with positive lag indicating owed work.
A task with negative lag has already received extra service and is not eligible under EEVDF.
Little’s law
Little’s law relates average population, arrival rate, and residence time in a stable steady-state system with a consistent boundary.
Little’s law gives an average population of four when eight jobs arrive per second and stay 0.5 s.
Load imbalance
Load imbalance is an uneven distribution of runnable demand across CPUs, which can waste capacity or give comparable jobs unequal service.
Load imbalance appears when a lone task gets a whole CPU while two peers split another.
Long-term scheduler
A long-term scheduler controls which submitted jobs enter a system, thereby influencing its degree of multiprogramming.
A cluster’s long-term scheduler admits another batch job when capacity becomes available.
Lottery scheduling
Lottery scheduling chooses each next CPU slice through a random ticket draw, giving runnable tasks winning chances proportional to tickets.
Lottery scheduling can give a 60-ticket job fewer than six wins in its first ten draws.

M

Medium-term scheduler
A medium-term scheduler temporarily suspends whole processes by swapping them out of memory and later restoring them.
A medium-term scheduler can reduce memory pressure by suspending a process temporarily.
Migration
Migration moves a task’s execution placement between CPUs, often to correct imbalance at the cost of cache and memory locality.
Migration to an idle compatible CPU can save more waiting time than it costs in cache refills.
Minimum granularity
Minimum granularity is the lower service-turn scale in classic CFS that prevents many runnable tasks from creating excessively short slices.
Minimum granularity can make the total scheduling period exceed its target under heavy competition.
MLFQ
An MLFQ is a scheduler with several priority queues that changes a job’s queue according to observed CPU consumption and feedback.
The MLFQ starts the newcomer at the top and demotes it after sustained CPU use.
MQMS
MQMS is multiprocessor scheduling with local per-CPU ready queues, supporting scalable local selection while requiring load balancing.
MQMS can leave one CPU idle while two ready tasks remain assigned to another CPU.

N

Nice value
A nice value is a user-facing priority input for normal Linux tasks, ranging from −20, most favored, to +19, least favored.
A larger nice value reduces a normal task’s relative CPU share when competitors are runnable.
NUMA
NUMA is a memory architecture in which access latency depends on whether memory is local to the executing processor or on another node.
NUMA placement matters when a migrated thread repeatedly accesses memory on its previous socket.

P

Pass value
A pass value records weighted service progress in stride scheduling and is compared with other runnable jobs’ passes to select a turn.
The task with pass value 40 runs before a competitor whose pass has already reached 60.
Preemption
Preemption is the removal of the CPU from a running task that could continue, with its state preserved for a later resumption.
A timer-triggered preemption lets another ready thread run before the computation finishes.
Priority boost
A priority boost temporarily raises scheduling rank; an MLFQ-wide boost returns jobs to the top so their behavior can be learned again.
The priority boost gives the old bottom-queue job a new chance to run at the top.
Priority class
A Windows priority class is a process-level setting that combines with each thread’s relative level to determine its base priority.
Changing the process’s priority class changes how its thread levels map to base priorities.
Priority inheritance
Priority inheritance temporarily gives a lock holder the priority of a higher-priority task waiting for that lock.
Priority inheritance lets the low-ranked holder run long enough to release the needed lock.
Priority inversion
Priority inversion occurs when high-priority work waits for a lower-priority dependency that medium-priority execution can delay.
Priority inversion keeps the urgent task blocked while medium-priority work preempts its lock holder.
Priority scheduling
Priority scheduling selects the highest-ranked ready task, using another rule such as FIFO or round robin to resolve equal ranks.
Priority scheduling runs a newly ready urgent task before ordinary work on a preemptive system.
Proportional share
A proportional share is a target fraction of contested CPU service assigned to a task or group through a relative entitlement.
The service receives a larger proportional share when its weight rises relative to its busy sibling.

Q

Quality of service
Quality of service is a work-urgency classification used by macOS to guide service decisions, including placement across core types.
Background quality of service signals different urgency from user-interactive work on Apple silicon.
Quantum
A quantum is the maximum CPU service allowed in one round-robin turn before an unfinished ready task is preempted.
A 4 ms quantum lets a task with 10 ms of work continue through several turns.
Queueing model
A queueing model represents arrivals and service using probability distributions to study average populations, delays, and capacity.
A queueing model can estimate average waiting under a chosen distribution of burst lengths.

R

Ready state
The ready state is the condition of a task that can execute but is waiting to be selected for an available CPU.
A preempted compiler returns to the ready state while another task uses the CPU.
Red-black tree
A red-black tree is a balanced search tree; classic CFS orders queued runnable tasks by virtual runtime within such a structure.
The red-black tree supports logarithmic updates, while a cached pointer supplies its minimum quickly.
Remaining time
Remaining time is the CPU service a job or burst still needs after subtracting the service it has already received.
The scheduler compares the running job’s remaining time with the newcomer’s full burst.
Response time
Response time in a scheduling trace is the interval from a job’s arrival until its first CPU execution, before any later waits.
An editor can have a short response time even when its full operation finishes much later.
Round robin
Round robin is a policy that rotates ready tasks through a FIFO queue, giving each at most one time quantum before requeuing it.
Under round robin, a report generator that still has work gets another turn after the other ready jobs run.

S

sched_ext
The sched_ext class lets a configured Linux kernel run a dynamically loaded BPF scheduler, with recovery to built-in scheduling on failure.
An error in the active sched_ext policy causes the kernel to restore ordinary fair scheduling.
SCHED_FIFO
SCHED_FIFO is a Linux real-time policy without a same-priority quantum; tasks continue until blocking, yielding, or higher-priority preemption.
A SCHED_FIFO task at priority 40 can run ahead of normal work while it remains runnable.
SCHED_RR
SCHED_RR is Linux real-time scheduling that adds quantum-based rotation among ready tasks sharing the same static priority.
SCHED_RR makes two priority-50 tasks alternate, while priority 60 can preempt either one.
Scheduler gaming
Scheduler gaming is deliberate manipulation of observed behavior to obtain service advantages that the policy was not intended to grant.
Scheduler gaming succeeds when an early-yield rule forgets CPU time used before each I/O.
Shortest job first
Shortest job first is a non-preemptive policy that selects the ready task with the shortest known or predicted next CPU burst.
Shortest job first selects a ready 3 ms burst before a ready 11 ms burst.
Simulation
Simulation evaluates a scheduler by executing a model on synthetic workloads or recorded events and measuring its resulting behavior.
Simulation can replay the same arrival and blocking trace against two scheduling policies.
SMP
SMP is a multiprocessor design in which CPUs can execute operating-system code and make scheduling decisions themselves.
An SMP kernel coordinates simultaneous ready-queue updates made by several CPUs.
SMT
SMT lets several logical CPUs share one physical core’s execution resources, providing parallel instruction streams with shared capacity.
Two CPU-bound threads on SMT siblings contend more directly than threads on separate cores.
Spatial locality
Spatial locality is a program’s tendency to access data near recently accessed locations, such as neighboring elements of an array.
Spatial locality helps a sequential array scan benefit from fetching an entire cache line.
SQMS
SQMS is multiprocessor scheduling through one shared ready queue, making work easy to distribute but creating shared synchronization costs.
SQMS can give an idle eligible CPU the next waiting job without searching separate queues.
Starvation
Starvation is indefinite postponement of a ready job because scheduling decisions repeatedly give other jobs the CPU.
A steady stream of short jobs can cause starvation of a long job under SJF.
STCF
STCF is a preemptive policy that runs the ready job with the least remaining CPU demand, also called shortest remaining time first.
STCF preempts a job with 14 ms left when a newly ready job needs only 2 ms.
Stride
A stride is a common constant divided by a task’s ticket count, added to its pass after the task receives a service slice.
A smaller stride lets the favored job’s pass rise more slowly after each selected turn.
Stride scheduling
Stride scheduling is deterministic proportional sharing that runs the minimum-pass task and advances its pass by an inverse-ticket stride.
Stride scheduling keeps short-window service close to ticket ratios without random lottery draws.
Switching overhead
Switching overhead is CPU time spent dispatching between tasks and recovering useful execution state instead of advancing application work.
A tiny quantum raises switching overhead because useful bursts are separated by frequent handoffs.

T

Tail latency
Tail latency describes delays near the slow end of a response-time distribution, often reported through a high percentile.
The service’s tail latency worsens when a small number of requests wait far longer than average.
Temporal locality
Temporal locality is a program’s tendency to reuse recently accessed data, making cached contents useful for later execution.
Temporal locality helps the loop reuse the same table entries from a warm cache.
Throughput
Throughput is the number of jobs completed per unit of elapsed time during a specified observation interval.
A test comparing two scheduling policies reports throughput in jobs per second over the same interval for each policy.
Ticket currency
Ticket currency divides a user’s fixed global entitlement among local jobs by converting local ticket fractions into global tickets.
Ticket currency lets one user split a fixed 80-ticket allocation across three local jobs.
Ticket inflation
Ticket inflation increases a job’s own ticket count to request more service, requiring trust or controls to prevent unfair dilution.
Unrestricted ticket inflation lets a greedy task reduce every other runnable job’s winning probability.
Ticket transfer
Ticket transfer is the temporary lending of a job’s tickets to another job, often a server carrying out the lender’s request.
Ticket transfer lets the server performing the client’s request compete using the client’s entitlement.
Turnaround time
Turnaround time is the elapsed time from a job’s arrival until its completion, including service, ready waits, and blocked time.
A batch job that uses only 7 ms of CPU service but completes 18 ms after it arrives has a turnaround time of 18 ms.

U

ULE
ULE is FreeBSD’s scheduler, using per-CPU run queues and observed sleep-versus-run behavior to help identify interactive threads.
ULE combines local CPU scheduling with feedback about how often a thread sleeps.

V

Virtual deadline
A virtual deadline is a weighted service-ordering endpoint used by EEVDF to compare requests from tasks eligible for service.
An earlier virtual deadline helps a short eligible request run sooner without a wall-clock guarantee.
Virtual runtime
Virtual runtime is CPU service scaled by task weight so that higher-weight tasks accumulate virtual progress more slowly.
The heavy task gains less virtual runtime per millisecond and remains competitive for more service.

W

Waiting time
Waiting time is the sum of the intervals in which a task is ready but not executing, excluding its CPU service and blocked waits.
The task’s waiting time includes both its initial queue delay and the wait after preemption.
Work stealing
Work stealing is a balancing method in which a lightly loaded CPU pulls runnable work from a busier CPU’s queue.
Work stealing moves a queued computation to the idle core after checking its CPU eligibility.
Workload trace
A workload trace is a recorded sequence of events such as arrivals, bursts, and waits that can drive a scheduling experiment.
A workload trace from interactive use may expose delays absent from a CPU-only batch test.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started