Chapters 7 and 8 optimized turnaround and response. This chapter wants something else entirely: guarantee each job a slice of the pie โ proportional-share proportional share Scheduling that guarantees each job a percentage of the CPU rather than optimizing turnaround/response (a.k.a. fair-share). defined in ch. 9 โ open in glossary (fair-share) scheduling. The early classic is Waldspurger and Weihlโs lottery scheduling (1994), and its core idea fits in a sentence: every so often, hold a lottery; jobs that deserve more CPU get more chances to win.
The Crux: How To Share The CPU Proportionally
How can we design a scheduler to share the CPU in a proportional manner? What are the key mechanisms for doing so? How effective are they?9.1 Basic Concept: Tickets Represent Your Share
Everything rests on the ticket ticket A token representing a share of a resource; percent of tickets held = share received. Reusable far beyond CPUs (e.g., hypervisor memory). defined in ch. 9 โ open in glossary : a token representing a share of a resource. Hold 75 of the 100 tickets in play, and you should receive 75% of the CPU. Lottery scheduling lottery scheduling Every slice, draw a random winning ticket; the holder runs. Probabilistically proportional, minimal state, no global bookkeeping. defined in ch. 9 โ open in glossary delivers that share probabilistically: every time slice, the scheduler draws a winning ticket (0 to totalโ1) and runs its holder:
| job | arrival | runtime | turnaround | response | CPU share (target) |
|---|---|---|---|---|---|
| A | 0 | 60 | 97 | 3 | 50% (75%) |
| B | 0 | 60 | 120 | 0 | 50% (25%) |
| average | 108.50 | 1.50 | |||
Each tick is one lottery over the ready jobs' tickets. Watch the CPU-share column against its (target): on short stretches the observed share can be well off 75/25 โ the book's own 20-draw example gave B only 20% instead of 25%. Re-roll a few times, then lengthen both runtimes: the longer they compete, the closer to target.
Randomness gives probabilistic correctness โ no guarantee on any short window (the bookโs 20-draw example handed B 20% instead of 25%), but the law of large numbers pulls long runs toward target.
Tip: Use randomness
Random decisions have three lovely properties. They dodge adversarial corner cases (LRU replacement โ coming in the memory chapters โ has a cyclic worst-case workload; random has no worst case). They need almost no state โ no per-process accounting of CPU received, just ticket counts. And theyโre fast: one random number and youโve decided. The faster you need it, the more โrandomโ tends toward pseudo-random.Tip: Use tickets to represent shares
The ticket is the mechanism to remember. Waldspurger later used tickets to represent a guest OSโs share of memory in a hypervisor. Whenever you need to represent proportions of ownership, the answer might beโฆ (wait for it) โฆ the ticket.9.2 Ticket Mechanisms
Tickets come with a small toolkit:
Ticket currency ticket currency Users allocate tickets to their jobs in a private currency; the system converts to global tickets before the drawing. defined in ch. 9 โ open in glossary : each user subdivides their allocation however they like; conversion keeps the global lottery fair. Bโs single job ends up with twice the global tickets of either of Aโs two.
- Ticket transfer ticket transfer Temporarily handing your tickets to another process โ e.g., a client boosting the server working on its request. defined in ch. 9 โ open in glossary : temporarily hand your tickets to another process โ the classic case is a client passing tickets to a server so the server runs fast while doing the clientโs work, then hands them back.
- Ticket inflation ticket inflation A process raising/lowering its own ticket count โ sensible only among mutually trusting processes. defined in ch. 9 โ open in glossary : a process boosts (or trims) its own ticket count. Nonsense among competitors โ a greedy process could grab the machine โ but in a group of mutually trusting processes, itโs a lightweight way to say โI need more CPU right nowโ without any communication.
9.3 Implementation
The most amazing part: the whole scheduler needs a random number
generator, a list of processes, and the total ticket count. To decide,
draw winner in [0, total), then walk the list accumulating tickets
until the counter exceeds the winner:
// counter: used to track if we've found the winner yet
int counter = 0;
// winner: use some call to a random number generator to
// get a value, between 0 and the total # of tickets
int winner = getrandom(0, totaltickets);
// current: use this to walk through the list of jobs
node_t *current = head;
while (current) {
counter = counter + current->tickets;
if (counter > winner)
break; // found the winner
current = current->next;
}
// 'current' is the winner: schedule it...
Figure 9.1: Lottery Scheduling Decision Code
With the list A(100) โ B(50) โ C(250) and winning ticket 300: counter hits 100 (A โ keep going), 150 (B โ keep going), 400 (> 300 โ stop): C wins. One micro-optimization: keep the list sorted by descending tickets โ correctness is unaffected (any order works), but the biggest holders are found in the fewest iterations. Hereโs that exact workload, live:
| job | arrival | runtime | turnaround | response | CPU share (target) |
|---|---|---|---|---|---|
| A | 0 | 50 | 128 | 1 | 33% (25%) |
| B | 0 | 50 | 150 | 7 | 33% (13%) |
| C | 0 | 50 | 88 | 0 | 33% (63%) |
| average | 122.00 | 2.67 | |||
Targets: 25% / 12.5% / 62.5%. C wins most drawings and finishes first; once it completes, the remaining tickets (A's 100 + B's 50) re-divide the machine 2:1. Lottery needs no global bookkeeping for any of this โ dead jobs simply stop holding tickets.
Simple mechanism, three knobs on top of it, and an implementation that fits on an index card. Next: what randomness costs (short-run unfairness), and the deterministic alternatives โ stride scheduling and Linuxโs CFS.
Check yourself
1.A holds 75 tickets, B holds 25. What exactly does lottery scheduling guarantee about their CPU shares?
2.User A gives 500 A-currency tickets to each of two jobs; User B gives 10 B-currency tickets to one job. Both users hold 100 global tickets. Who has more global tickets โ A1 or B1?
3.Why does ticket inflation only make sense among mutually trusting processes?
4.In Figure 9.1's list walk (A:100 โ B:50 โ C:250) with winning ticket 300, how is the winner found?
5.Why does keeping the job list sorted by descending ticket count help โ and what does it NOT affect?