Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Pavol Černý, Programming Paradigms for Concurrency, Fall 2010, IST Austria Review: Peterson’s Algorithm Alice flag[0] ←0 no access flag[0] ←0 Bob flag[1] ←0 no access flag[0] ← 1 flag[1] ← 1 turn ← 1 turn ← 0 request flag[1] = 0 or turn = 0 access flag[0] request flag[0] = 0 or turn = 1 access ←0 Implementing a Counter public class Counter { private long value; Use Peterson’s public long getAndIncrement() { temp = value; value = temp + 1; return temp; Make these } } steps indivisible using locks Art of Multiprocessor 3 Programming Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } Art of Multiprocessor Programming 4 Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void unlock(); } Art of Multiprocessor Programming 5 Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void unlock(); release lock } Art of Multiprocessor Programming 6 Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Art of Multiprocessor Programming 7 Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); acquire try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Art of Multiprocessor Programming Lock 8 Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { Release lock lock.unlock(); } (no matter what) return temp; }} Art of Multiprocessor Programming 9 Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Art of Multiprocessor Programming Critical section 10 Peterson’s in Java public void lock() { flag[i] = 1; turn = 1-i; while (!((flag[1-i] == 0) || (turn == i))) { } } flag[0] ←0 public void unlock() { flag[i] = 0; } flag[0] ←0 no access flag[0] ← 1 turn ← 1 request flag[1] = 0 or turn = 0 access Review: Peterson’s Algorithm Questions from last lecture: 1.Can we make do with two shared bits (instead of three)? 2.How can one extend this idea to n processes? 3.Does the algorithm work in Java? Run it and see. What is the problem? Where is the fault in our proof? Question 1: Modify Peterson’s to use two bits public void lock() { if (i==0) { flag[0] = 1; while (!(flag[1] == 0)) { } } else { while (!( flag[1] == 1)) {; flag[1] = 1; while (!(flag[0] == 0)) { flag[1] = 0; } } } } public void unlock() { flag[i] = 0; } Question 2: Modify Peterson’s for n processes Today’s class Question 3: But does it work in Java? public void lock() { flag[i] = 1; turn = 1-i; while (!((flag[1-i] == 0) || (turn == i))) { } } public void unlock() { flag[i]=0; } java Peterson … (results in deadlock) java Peterson ... (mutual exclusion fails (if a counter is protected with these locks, we observe a problem after enough iterations)) Fact • Most hardware architectures don’t support sequential consistency • Because they think it’s too strong Art of Multiprocessor Programming 16 The Flag Example y.read(0) x.write(1) y.write(1) x.read(0) time time Art of Multiprocessor Programming 17 The Flag Example y.read(0) x.write(1) y.write(1) x.read(0) • Each thread’s view is sequentially consistent – It went first time Art of Multiprocessor Programming 18 The Flag Example y.read(0) x.write(1) y.write(1) x.read(0) • Entire history isn’t sequentially consistent – Can’t both go first time Art of Multiprocessor Programming 19 The Flag Example y.read(0) x.write(1) y.write(1) x.read(0) • Is this behavior really so wrong? – We can argue either way … time Art of Multiprocessor Programming 20 Opinion1: It’s Wrong • This pattern – Write mine, read yours • Is exactly the flag principle – Beloved of Alice and Bob – Heart of mutual exclusion • Peterson • Bakery, etc. • It’s non-negotiable! Art of Multiprocessor Programming 21 Opinion2: But It Feels So Right … • Many hardware architects think that sequential consistency is too strong • Too expensive to implement in modern hardware • OK if flag principle – violated by default – Honored by explicit request Art of Multiprocessor Programming 22 Who knew you wanted to synchronize? • Writing to memory = mailing a letter • Vast majority of reads & writes – Not for synchronization – No need to idle waiting for post office • If you want to synchronize – Announce it explicitly – Pay for it only when you need it Art of Multiprocessor Programming 23 Explicit Synchronization • Memory barrier instruction – Flush unwritten caches – Bring caches up to date • Expensive Art of Multiprocessor Programming 24 Volatile • In Java, can ask compiler to keep a variable up-to-date with volatile keyword • Also inhibits reordering & other “optimizations” • Example: public static volatile int[] flag; public static volatile int z = 0; Art of Multiprocessor Programming 25 Mutual Exclusion • • • • • Problem definitions Solutions for 2 threads Solutions for n threads Fair solutions Inherent costs Art of Multiprocessor Programming 26 Warning • You will never use these protocols • Understanding these is necessary – The same issues show up everywhere – Except hidden and more complex Art of Multiprocessor Programming 27 Formalizing the Problem • Two types of formal properties in asynchronous computation: • Safety Properties – Nothing bad happens ever – E.g. Mutual exclusion, No overtaking • Liveness Properties – Something good happens eventually – E.g. Deadlock freedom, Starvation freedom Art of Multiprocessor Programming 28 Events • An event a0 of thread A is – Instantaneous – No simultaneous events (break ties) a0 time Art of Multiprocessor Programming 29 Threads • A thread A is (formally) a sequence a0, a1, ... of events – “Trace” model – Notation: a0 a1 indicates order a0 a1 a2 … time Art of Multiprocessor Programming 30 Example Thread Events • • • • • Assign to shared variable Assign to local variable Invoke method Return from method Lots of other things … Art of Multiprocessor Programming 31 Threads are State Machines Events are transitions a3 a2 Art of Multiprocessor Programming a0 a1 32 States • Thread State – Program counter – Local variables • System state – Object fields (shared variables) – Union of thread states Art of Multiprocessor Programming 33 Concurrency • Thread A time Art of Multiprocessor Programming 34 Concurrency • Thread A time • Thread B time Art of Multiprocessor Programming 35 Interleavings • Events of two or more threads – Interleaved – Not necessarily independent (why?) time Art of Multiprocessor Programming 36 Intervals • An interval A0 =(a0,a1) is – Time between events a0 and a1 a0 A0 a1 time Art of Multiprocessor Programming 37 Intervals may Overlap b0 a0 A0 B0 b1 a1 time Art of Multiprocessor Programming 38 Intervals may be Disjoint b0 a0 A0 B0 b1 a1 time Art of Multiprocessor Programming 39 Precedence Interval A0 precedes interval B0 b0 a0 A0 B0 b1 a1 time Art of Multiprocessor Programming 40 Precedence • Notation: A0 B0 • Formally, – End event of A0 before start event of B0 – Also called “happens before” or “precedes” Art of Multiprocessor Programming 41 Precedence Ordering • • • • Never true that A A If A B then not true that B A If A B & B C then A C Funny thing: A B & B A might both be false! Art of Multiprocessor Programming 42 Partial Orders (review) • Irreflexive: – Never true that A A • Antisymmetric: – If A B then not true that B A • Transitive: – If A B & B C then A C Art of Multiprocessor Programming 43 Total Orders (review) • Also – Irreflexive – Antisymmetric – Transitive • Except that for every distinct A, B, – Either A B or B A Art of Multiprocessor Programming 44 Repeated Events while (mumble) { a0; a1; } a0 k A0k k-th occurrence of event a0 k-th occurrence of interval A0 =(a0,a1) Art of Multiprocessor Programming 45 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution Art of Multiprocessor Programming 46 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be thread j’s m-th critical section execution Art of Multiprocessor Programming 47 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or Art of Multiprocessor Programming 48 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or CSik CSjm Art of Multiprocessor Programming 49 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or CSik CSjm Art of Multiprocessor Programming CSjm CSik 50 Deadlock-Free • If some thread calls lock() – And never returns – Then other threads must complete lock() and unlock() calls infinitely often – This is true for all fair schedules – Schedule is fair if all threads in CS or concurrency parts proceed • System as a whole makes progress – Even if individuals starve Art of Multiprocessor Programming 51 Starvation-Free • If some thread calls lock() – It will eventually return • Individual threads make progress Art of Multiprocessor Programming 52 Example – proving mutual exclusion class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Art of Multiprocessor Programming 53 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} Set my flag } Art of Multiprocessor Programming 54 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} Set my flag } Wait for other flag to go false Art of Multiprocessor Programming 55 LockOne Satisfies Mutual Exclusion • Assume CSAj overlaps CSBk • Consider each thread's last (j-th and k-th) read and write in the lock() method before entering • Derive a contradiction Art of Multiprocessor Programming 56 From the Code • writeA(flag[A]=true) readA(flag[B]==false) CSA • writeB(flag[B]=true) readB(flag[A]==false) CSB class LockOne implements Lock { … public void lock() { flag[i] = true; while (flag[j]) {} } Art of Multiprocessor Programming 57 From the Assumption • readA(flag[B]==false) writeB(flag[B]=true) • readB(flag[A]==false) writeA(flag[A]=true) Art of Multiprocessor Programming 58 Combining • Assumptions: – readA(flag[B]==false) writeB(flag[B]=true) – readB(flag[A]==false) writeA(flag[A]=true) • From the code – writeA(flag[A]=true) readA(flag[B]==false) – writeB(flag[B]=true) readB(flag[A]==false) Art of Multiprocessor Programming 59 Combining • Assumptions: – readA(flag[B]==false) writeB(flag[B]=true) – readB(flag[A]==false) writeA(flag[A]=true) • From the code – writeA(flag[A]=true) readA(flag[B]==false) – writeB(flag[B]=true) readB(flag[A]==false) Art of Multiprocessor Programming 60 Combining • Assumptions: – readA(flag[B]==false) writeB(flag[B]=true) – readB(flag[A]==false) writeA(flag[A]=true) • From the code – writeA(flag[A]=true) readA(flag[B]==false) – writeB(flag[B]=true) readB(flag[A]==false) Art of Multiprocessor Programming 61 Combining • Assumptions: – readA(flag[B]==false) writeB(flag[B]=true) – readB(flag[A]==false) writeA(flag[A]=true) • From the code – writeA(flag[A]=true) readA(flag[B]==false) – writeB(flag[B]=true) readB(flag[A]==false) Art of Multiprocessor Programming 62 Combining • Assumptions: – readA(flag[B]==false) writeB(flag[B]=true) – readB(flag[A]==false) writeA(flag[A]=true) • From the code – writeA(flag[A]=true) readA(flag[B]==false) – writeB(flag[B]=true) readB(flag[A]==false) Art of Multiprocessor Programming 63 Combining • Assumptions: – readA(flag[B]==false) writeB(flag[B]=true) – readB(flag[A]==false) writeA(flag[A]=true) • From the code – writeA(flag[A]=true) readA(flag[B]==false) – writeB(flag[B]=true) readB(flag[A]==false) Art of Multiprocessor Programming 64 Cycle! Art of Multiprocessor Programming 65 Deadlock Freedom • LockOne Fails deadlock-freedom – Concurrent execution can deadlock flag[i] = true; while (flag[j]){} flag[j] = true; while (flag[i]){} – Sequential executions OK Art of Multiprocessor Programming 66 The Filter Algorithm for n Threads There are n-1 “waiting rooms” called levels ncs • At each level – At least one enters level – At least one blocked if many try cs • Only one thread makes it through Art of Multiprocessor Programming 67 Filter class Filter implements Lock { int[] level; // level[i] for thread i int[] victim; // victim[L] for level L 2 public Filter(int n) { n-1 0 level = new int[n]; level 0 0 4 0 0 0 0 0 victim = new int[n]; 1 for (int i = 1; i < n; i++) { level[i] = 0; }} 2 4 … } Thread 2 at level 4 Art of Multiprocessor Programming n-1 victim 68 Filter class Filter implements Lock { … public void lock(){ for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i level[k] >= L) && victim[L] == i ); }} public void unlock() { level[i] = 0; }} Art of Multiprocessor Programming 69 Filter class Filter implements Lock { … public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void release(int i) { level[i] = 0; }} One level at a time Art of Multiprocessor Programming 70 Filter class Filter implements Lock { … public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); // busy wait }} public void release(int i) { level[i] = 0; }} Art of Multiprocessor Programming Announce intention to enter level L 71 Filter class Filter implements Lock { int level[n]; int victim[n]; public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void release(int i) { level[i] = 0; }} Art of Multiprocessor Programming Give priority to anyone but me 72 Filter class Filter implements Lock { Wait as long as someone else is at int level[n]; int victim[n]; higher level, and I’m designated public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; same or victim while (($ k != i) level[k] >= L) && victim[L] == i); }} public void release(int i) { level[i] = 0; }} Art of Multiprocessor Programming 73 Filter class Filter implements Lock { int level[n]; int victim[n]; public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void release(int i) { Thread enters level L when level[i] = 0; the loop }} Art of Multiprocessor Programming it completes 74 Claim • Start at level L=0 • At most n-L threads enter level L • Mutual exclusion at level L=n-1 ncs L=0 L=1 L=n-2 cs L=n-1 Art of Multiprocessor Programming 75 Induction Hypothesis • No more than n-L+1 at level L-1 or above • Induction step: by contradiction • Assume all at level L-1 enter level L • A last to write victim[L] • B is any other thread at level L ncs assume L-1 has n-L+1 L has n-L cs Art of Multiprocessor Programming prove 76 Proof Structure ncs A B Assumed to enter L-1 n-L+1 = 4 Last to write victim[L] n-L+1 = 4 cs By way of contradiction all enter L A must have seen B in level[L] and since victim[L] == A could not have entered Art of Multiprocessor Programming 77 No Starvation • Filter Lock satisfies properties: – Just like Peterson Alg at any level – So no one starves • But what about fairness? – Threads can be overtaken by others Art of Multiprocessor Programming 78 Bounded Waiting • Want stronger fairness guarantees • Thread not “overtaken” too much • Need to adjust definitions …. Art of Multiprocessor Programming 79 Bounded Waiting • Divide lock() method into 2 parts: – Doorway interval: • Written DA • always finishes in finite steps – Waiting interval: • Written WA • may take unbounded steps Art of Multiprocessor Programming 80 First-Come First-Served • For threads A and B: – If DAk DB j • A’s k-th doorway precedes B’s j-th doorway – Then CSAk CSBj • A’s k-th critical section precedes B’s j-th critical section • B cannot overtake A Art of Multiprocessor Programming 81 Break! Art of Multiprocessor Programming 82 Bakery Algorithm • Provides First-Come-First-Served • How? – Take a “number” – Wait until lower numbers have been served • Lexicographic order – (a,i) > (b,j) • If a > b, or a = b and i > j Art of Multiprocessor Programming 83 Bakery Algorithm class Bakery implements Lock { boolean[] flag; Label[] label; public Bakery (int n) { flag = new boolean[n]; label = new Label[n]; for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } } … Art of Multiprocessor Programming 84 Bakery Algorithm class Bakery implements Lock { boolean[] flag; 6 Label[] label; 2 0 n-1 public Bakery (int n) { flag = new boolean[n]; f f t f f t f f label = new Label[n]; 0 0 4 0 0 5 0 0 for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } } … CS Art of Multiprocessor Programming 85 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 86 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Doorway lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 87 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { I’m interested lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 88 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Take increasing label (read labels in some arbitrary order) lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 89 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Someone is interested lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 90 Bakery Algorithm class Bakery implements Lock { boolean flag[n]; Someone int label[n]; is interested public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } With lower (label,i) in lexicographic order Art of Multiprocessor Programming 91 Bakery Algorithm class Bakery implements Lock { … public void unlock() { flag[i] = false; } } Art of Multiprocessor Programming 92 Bakery Algorithm class Bakery implements Lock { … No longer interested public void unlock() { flag[i] = false; } } labels are always increasing Art of Multiprocessor Programming 93 No Deadlock • There is always one thread with earliest label • Ties are impossible (why?) Art of Multiprocessor Programming 94 First-Come-First-Served • If DA DBthen A’s label is smaller • And: – writeA(label[A]) readB(label[A]) writeB(label[B]) readB(flag[A]) • So B is locked out while flag[A] is true class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 95 Mutual Exclusion • Suppose A and B in CS together • Suppose A has earlier label • When B entered, it must have seen class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } – flag[A] is false, or – label[A] > label[B] Art of Multiprocessor Programming 96 Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false Art of Multiprocessor Programming 97 Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false • LabelingB readB(flag[A]) writeA(flag[A]) LabelingA Art of Multiprocessor Programming 98 Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false • LabelingB readB(flag[A]) writeA(flag[A]) LabelingA • Which contradicts the assumption that A has an earlier label Art of Multiprocessor Programming 99 Bakery Y232K Bug class Bakery … public void flag[i] = label[i] = implements Lock { lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 100 Bakery Y232K Bug class Bakery … public void flag[i] = label[i] = Mutex breaks if label[i] overflows implements Lock { lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 101 Does Overflow Actually Matter? • Yes – Y2K – 18 January 2038 (Unix time_t rollover) – 16-bit counters • No – 64-bit counters • Maybe – 32-bit counters Art of Multiprocessor Programming 102 Is this Optimal Solution? • The Bakery Algorithm is – Succinct, – Elegant, and – Fair. • Q: So why isn’t it practical? • A: Well, you have to read N distinct variables Art of Multiprocessor Programming 103 Shared Memory • Shared read/write memory locations called Registers (historical reasons) • Come in different flavors – Multi-Reader-Single-Writer (Flag[]) – Multi-Reader-Multi-Writer (Victim[]) – Not that interesting: SRMW and SRSW Art of Multiprocessor Programming 104 Theorem At least N MRSW (multireader/single-writer) registers are needed to solve deadlock-free mutual exclusion. N registers like Flag[]… Art of Multiprocessor Programming 105 Proving Algorithmic Impossibility •To show no algorithm exists: • assume by way of contradiction C write one does, • show a bad execution that CS violates properties: • in our case assume an alg for deadlock free mutual exclusion using < N registers Art of Multiprocessor Programming 106 Proof: Need N-MRSW Registers Each thread must write to some register A CS B C write write CS CS …can’t tell whether A is in critical section Art of Multiprocessor Programming 107 Upper Bound • Bakery algorithm – Uses 2N MRSW registers • So the bound is (pretty) tight • But what if we use MRMW registers? – Like victim[] ? Art of Multiprocessor Programming 108 Bad News Theorem At least N MRMW multireader/multi-writer registers are needed to solve deadlock-free mutual exclusion. (So multiple writers don’t help) Art of Multiprocessor Programming 109 Theorem (For 2Threads) Theorem: Deadlock-free mutual exclusion for 2 threads requires at least 2 multi-reader multi-writer registers Proof: assume one register suffices and derive a contradiction Art of Multiprocessor Programming 110 Two Thread Execution A B R Write(R) CS CS • Threads run, reading and writing R • Deadlock free so at least one gets in Art of Multiprocessor Programming 111 Covering State B Write(R) A covering state for a Lock object is one in which there is at least one thread about to write to each shared location, but the object’s locations appear as if no thread is in the critical section or trying to enter the critical section. Art of Multiprocessor Programming 112 Covering State for One Register Always Exists B Write(R) In any protocol B has to write to the register before entering CS, so stop it just before Art of Multiprocessor Programming 113 Proof: Assume Cover of 1 A B Write(R) CS A runs, possibly writes to the register, enters CS Art of Multiprocessor Programming 114 Proof: Assume Cover of 1 A B Write(R) CS CS Art of Multiprocessor Programming B Runs, first obliterating any trace of A, then also enters the critical section 115 Theorem Deadlock-free mutual exclusion for 3 threads requires at least 3 multireader multi-writer registers Art of Multiprocessor Programming 116 Proof: Assume Cover of 2 A B C Write(RB) Write(RC) Only 2 registers Art of Multiprocessor Programming 117 Run A Solo A B C Write(RB) Write(RC) Writes to one or both CS registers, enters CS Art of Multiprocessor Programming 118 Obliterate Traces of A A CS B C Write(RB) Write(RC) Other threads obliterate evidence that A entered CS Art of Multiprocessor Programming 119 Mutual Exclusion Fails A CS B C Write(RB) Write(RC) CS CS looks empty, so another thread gets in Art of Multiprocessor Programming 120 Proof Strategy • Proved: a contradiction starting from a covering state for 2 registers • Claim: a covering state for 2 registers is reachable from any state where CS is empty Art of Multiprocessor Programming 121 Covering State for Two A B Write(RA) Write(RB) • If we run B through CS 3 times, B must return twice to cover some register, say RB Art of Multiprocessor Programming 122 Covering State for Two A B Write(RA) Write(RB) • Start with B covering register RB for the 1st time • Run A until it is about to write to uncovered RA • Are we done? Art of Multiprocessor Programming 123 Covering State for Two A B Write(RA) Write(RB) • NO! A could have written to RB • So CS no longer looks empty Art of Multiprocessor Programming 124 Covering State for Two A B Write(RA) Write(RB) • Run B obliterating traces of A in RB • Run B again until it is about to write to RB • Now we are done Art of Multiprocessor Programming 125 Inductively We Can Show • There is a covering state – Where k threads not in CS cover k distinct registers – Proof follows when k = N-1 • Reference: J. Burns, N. Lynch : Bounds on shared memory for mutual exclusion. Inf. And Comp. 1993 Art of Multiprocessor Programming 126 Summary of Lecture • In the 1960’s many incorrect solutions to starvation-free mutual exclusion using RW-registers were published… • Today we know how to solve FIFO N thread mutual exclusion using 2N RW-Registers Art of Multiprocessor Programming 127 Summary of Lecture • N RW-Registers inefficient – Because writes “cover” older writes • Need stronger hardware operations – that do not have the “covering problem” Art of Multiprocessor Programming 128