A strategy [Maksim's] for proving things about the n-process RMW bakery algorithm (Algorithm 4.2): Inductively prove an invariant that says carefully that a correct FIFO queue is maintained: 1. Each processor beyond line 1 but before line 5 is remembering the ``ticket'' he ``took'' in line 1 (``position.last''). 2. These currently held tickets are distinct. 3. The set of these tickets, in the order taken, is {First, First+1 mod n, First+2 mod n, ..., Last-1 mod n}, where First is V.first and Last is V.last. (Note that this set is not *quite* determined by V alone, because of the case First=Last. When any process looks at V, however, he knows where *he* is and can thus tell.) 4. Only a processor with ticket equal to First might currently be beyond line 4. Is the induction routine enough now? And, given this, are disproofs of deadlock and lockout clear now? Maybe we'll be able to adapt all this later, when we look at the n-process R/W bakery algorithm (Algorithm 4.3). ------------------------ R/W bakery emulation: Design approach: Adapt naively; patch/debug; reanalyze. Naive adaptation: Simply unbundle each RMW. Promising: Second *is* just a read. Third is just a write, provided we unbundle the two components. But the first includes both a read and a write. Can the read get ``stale''? Slightly: Two might claim same ticket, not know. (E.g., read1, read2, write1, write2.) Very: Might set Last *back*! (E.g., read1, read2, write2, read3, write3, write1.) Partial fix: Use uid's to break ties. Requires look at previously unshared information. Have to ``poll'' anyway ==> may as well do without original shared vbles., get by without shared writing. Result so far: try: Take next available number, based on polling Wait until your number is lowest, based on polling exit: Give up your number Idea to *live with* the still worrisome delayed writes: Don't conclude your number is best while things might change. *No* worry: 1. Someone you've already beat (Stays until *you* change, after your crit and exit) 2. Someone who has not even started choosing, since he'll see your number More careful waiting for each other process: Wait until he is not choosing a number Wait until his number is worse than yours Key claim: Latter will remain true until *you* change *your* number (in exit). Proof idea: After the first wait, all of his changes will make him worse than you. The second wait waits until they do. Reanalysis: Mutual exclusion: When each enters crit, he is better; contradiction. Lemma 1: Choosing ``doorway'' is ``wait-free'' (get through in your next n steps, no matter what). Corollary: Progress (i.e., no deadlock). Proof: Suppose not (in some admissible infinite execution). Wait until crit and (also wait-free) exit sections empty. Wait until all ultimate choosers are through doorway. Consider the one with the best number; nothing can stop him now! Lemma 2: No one can enter crit twice while you are in choosing doorway. Proof: First wait would stop him before second time. Lemma 3: FIFO after the wait-free choosing doorway. I.e., once through, you can lose only to those already in doorway (or further) (each at most once, therefore). I.e., if contender instances don't overlap in doorway presence, then first goes first. Remark: ``FIFO doorway'' is trivial for any mutual exclusion protocol-- just use whole trying section! The big deal: *wait-free*. Corollary: No lockout! Proof: Wait until through wait-free doorway. Wait for progress. Wait for progress. ..., until *you* get your turn, after at most n-1 who were already trying when you got through the doorway. Ponder: Why not bound the registers? Modular arithmetic? [Insight by Jayanti, Tan, Friedland, Katz, SOFSEM 2001?] ------------------------ Typical ideas (behind Dijkstra and ``Fast,'' for example): General: If ``the coast looks clear,'' then ``grab.'' (Duh.) Possible senses of ``the coast looks clear'': no one critical--too permissive (usual reason) no one else trying--mutual exclusion (see why?), but too *restrictive* no one else up to this test--similar, but perhaps less restrictive Possible things to ``grab'': critical section entry (duh) setting of some auxiliary vble. (such as ``Turn'' or ``Lock'') (less committal--sort of ``bootstrapping'') Patch for undoing apparent deadlock (overrestriction): ``partial backoff'' (from some earlier overpermissive test) ------------------------ A version of Dijkstra, FYI: try: Flag(me) := 1 while Turn <> me do if Flag(Turn)=0 then Turn := me Flag(me) := 2 if Flag(anyone else)=2 then retry exit: Flag(me) := 0 (Note how to ``compile'' this.)