Β§6.4–6.5Worried About Concurrency? … Summary

Part I OSTEP pp. 59–61 Β· ~4 min read

The machinery is in place β€” but a sharp reader should be twitchy about one thing.

6.4 Worried About Concurrency?

What happens if, during a system call, a timer interrupt fires? What if an interrupt arrives while the OS is already handling another interrupt? Good questions (β€œwe really have some hope for you yet”) β€” and they are exactly the subject of the book’s entire second piece, on concurrency. Two teasers of how the OS copes:

CPU:process runningOS handling interrupt #1…then handles #2interrupts DISABLED in this windowinterrupt #2 arrives mid-handling……and waits: delivered only when handling of #1 completes⚠ but disable interrupts for too long and some may be LOST β€” which is (in technical terms) bad

Coping strategy #1: disable interrupts while handling one β€” no second interrupt is delivered mid-handling. It must be brief, though; the window is dangerous.

Strategy #2: operating systems developed sophisticated locking schemes to protect concurrent access to internal kernel data structures β€” which lets multiple activities proceed inside the kernel at once, especially useful on multiprocessors. As Part II will show at length (starting with the broken counter from chapter 2), such locking is complicated and breeds wonderfully hard-to-find bugs.

6.5 Summary

The collection of techniques of this chapter β€” modes, traps, the trap table, the timer, the context switch β€” together form limited direct execution : run the program you want to run on the CPU, but first set up the hardware to limit what it can do without OS assistance. The book’s analogy is irresistible:

Aside: Baby-proofing the CPU

Before letting a baby roam, you lock the cabinets with the dangerous stuff and cover the electrical sockets; afterward you can relax, knowing the worst hazards are out of reach. The OS baby-proofs the CPU the same way: at boot, set up the trap handlers and start the interrupt timer (lock the cabinets); at run time, only ever run processes in restricted user mode (cover the sockets). Then the OS relaxes: processes run at full speed, and OS intervention is needed only for privileged operations β€” or when a process hogs the CPU long enough for the timer to intervene.

How expensive is all this machinery? There’s a tool that measures exactly that:

How long do these mechanisms take? (lmbench measurements β€” click cells for caveats)
1996 Β· Linux 1.3.37, 200-MHz P6modern Β· 2–3 GHz systems
null system callβ‰ˆ 4 ΞΌssub-microsecond
context switchβ‰ˆ 6 ΞΌssub-microsecond
Dotted-underlined cells have explanations β€” click one.

With mechanisms done, the great unanswered question β€” which process should run at a given time β€” belongs to the scheduler, and to the next chapters. Time to meet the policies.

Homework (measurement): time it yourself

The third homework species: measure a real system. (1) System call: time millions of 0-byte read() calls with gettimeofday() and divide β€” after first measuring back-to-back gettimeofday() calls to learn the timer’s real precision (if it’s too coarse, look at rdtsc). (2) Context switch: lmbench’s trick β€” two processes ping-ponging one byte over two pipes, forcing a switch per hop; pin both to one CPU with sched_setaffinity() so you measure switching, not cross-CPU chatter. Details at ostep-homework.

Check yourself

1.An interrupt arrives while the OS is already handling another interrupt. What is the simple coping strategy this chapter sketches?

2.In the baby-proofing analogy, which pair correctly matches precaution to mechanism?

3.lmbench says system calls and context switches cost well under a microsecond on modern hardware. Why does Ousterhout's observation still urge caution?

4.The homework measures context-switch cost with two processes ping-ponging on pipes. Why must both be pinned to the SAME CPU (sched_setaffinity)?

4 questions