Presentation is loading. Please wait.

Presentation is loading. Please wait.

Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach Shaz Qadeer Microsoft Research Redmond, WA Serdar Taşıran Serdar.

Similar presentations


Presentation on theme: "Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach Shaz Qadeer Microsoft Research Redmond, WA Serdar Taşıran Serdar."— Presentation transcript:

1 Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach Shaz Qadeer Microsoft Research Redmond, WA Serdar Taşıran Serdar Taşıran, Tayfun Elmas, Ali Sezgin Koç University Istanbul, Turkey http://qed.codeplex.com

2 QED: What is it good for? Read(X) Write(X) Write(Y) Undo(Y) Want to verify: - Aborted transactions do not modify their write-set - Y is not modified here. - Straightforward if code were sequential 2

3 QED: What is it good for? t = X havoc(t) Write(X) Write(Y) Undo(Y) Read(X) Want to verify: - Aborted transactions do not modify their write-set - Y is not modified here. - Straightforward if code were sequential 3

4 QED-verified examples Fine-grained locking Linked-list with hand-over-hand locking [Herlihy-Shavit 08] Two-lock queue [Michael-Scott 96] Non-blocking algorithms Bakery [Lamport 74] Non-blocking stack [Treiber 86] Obstruction-free deque [Herlihy et al. 03] Non-blocking stack [Michael 04] Writer mode of non-blocking readers/writer lock [Krieger et al. 93] Non-blocking queue [Michael-Scott 96] Synchronous queue [Scherer-Lea-Scott 06] 4

5 QED: Simplify (coarsen), then verify 5... check P1P1 PnPn P2P2 Correct

6 Coarser Atomic Actions 6... check P1P1 PnPn P2P2 Correct Difficult to prove Fine-grain concurrency Annotations at every interleaving point Easy to prove Larger atomic blocks Local, sequential analysis within atomic blocks

7 Example: Concurrent increment 7 acquire(lock); t := x; t := t + 1; x := t; release(lock); acquire(lock); k := x; k := k + 1; x := k; release(lock); x := 0; assert x == 2; Thread AThread B || Main thread

8 Owicki-Gries proof, fine-grain actions 8 L0: acquire(lock); L1: t := x; L2: t := t + 1; L3: x := t; L4: release(lock); L5: // end of thread L0: acquire(lock); L1: k := x; L2: k := k + 1; L3: x := k; L4: release(lock); L5: // end of thread x := 0; assert x == 2; || { B@L0=>x=0, B@L5=>x=1 } { B@L0=>x=0, B@L5=>x=1, held(l,A) } { B@L0=>x=0, B@L5=>x=1, held(l,A), t=x } { B@L0=>x=0, B@L5=>x=1, held(l,A), t=x+1 } { B@L0=>x=1, B@L5=>x=2, held(l,A) } { B@L0=>x=1, B@L5=>x=2 } { A@L0=>x=0, A@L5=>x=1 } { A@L0=>x=0, A@L5=>x=1, held(l,B) } { A@L0=>x=0, A@L5=>x=1, held(l,B), k=x } { A@L0=>x=0, A@L5=>x=1, held(l,B), k=x+1 } { A@L0=>x=1, A@L5=>x=2, held(l,B) } { A@L0=>x=1, A@L5=>x=2 } Thread A Thread B

9 9 Reduction inc (): acquire (lock); t := x; t := t + 1; x := t; release(lock); Right mover Both mover B B Left mover inc (): acquire (lock); t := x; t := t + 1; x := t; release(lock); inc (): x := x + 1; REDUCE-SEQUENTIAL 9

10 Soundness 10 Soundness theorem: If P n is correct (satisfies all assertions) then 1. all P 1 ≤ i ≤ n are correct. 2. P n preserves behaviors of all P 1 ≤ i ≤ n. Completeness: Subsumes Owicki-Gries [Nieto, 2007]... check P1P1 PnPn P2P2 Correct

11 QED: Simplifier; complements other methods 11 acquire(lock); t := x; t := t + 1; x := t; release(lock); acquire(lock); k := x; k := k + 1; x := k; release(lock); x := 0; assert x == 2; || atomic { acquire(lock); t := x; t := t + 1; x := t; release(lock); } atomic { acquire(lock); k := x; k := k + 1; x := k; release(lock); } x := 0; assert x == 2; || x := 0; x := x + 1; assert x == 2; Simpler Owicki-Gries (4 location invariants) Correct Sequential analysis Correct Owicki-Gries (12 location invariants) Correct

12 QED-verifier reduce abstract..... reduce check http://qed.codeplex.com Correct 12... P1P1 PnPn P2P2 P1P1 PnPn Proof script Boogie 2, Z3 QEDPL program

13 Automation using SMT solver VC Valid 13 reduceabstractreduce check P1P1 PnPn P2P2 VC Valid VC Valid Correct VC Valid...

14 QED Transformations: Abstraction I,PI,P’ P’ : Atomic statement [ S ] in P replaced with [ S’ ] When? When atomic statement [S’] abstracts statement [S] 14

15 15 QED’s Idea of Abstraction  If for all : error s1s1 s1s1 1. If then s1s1 2. If then s2s2 s1s1 s2s2 or error s1s1 s1s1      –Going wrong more often is sound for assertion checking abstracted by 15

16 16 Flavors of Abstraction if (x == 1) y := y + 1; if ( * ) y := y + 1; Adding non-determinism Adding assertions (more “wrong” behaviors) t := x; havoc t; assume x != t; skip; assert (lock_owner == tid); x := t + 1; 16 “Read abstraction”

17 QED Transformations: Reduction [ S1; S2] [ S1 ] ; [ S2 ] [ S1 ] || [ S2 ] I,PI,P’ 17 If [S1] and [S2] are actions of correct mover types P P P’

18 18 Reduction  ;  ;  ...   1   2 ...   n   ;  ...  right-mover: For each execution: Exist equivalent executions:...     1   2 ...   n   ......   1     2 ...   n   .................   1   2 ...     n   ...  ;  18

19 Use of movers in reduction 19 reduce acquire(lock); k := x; k := k + 1; x := k; release(lock); atomic { acquire(lock); t := x; t := t + 1; x := t; release(lock); } acquire(lock)t := xt := t + 1;release(lock)... acquire(lock)t := xt := t + 1release(lock)... R B E1:E2:E1:E2: x := t... x := t E 1 ≈ E 2  Reason about only E 2 B BL Right-mover Both-mover Left-mover

20 Mover check in QED: Static, local, semantic 20... First-order verification condition For each ;... Right-mover ? A AB ; BA B : S1S1 S2S2 S3S3 S1S1 T2T2 S3S3 AB BA All actions in program run by different thread

21 Traditional use of reduction [Lipton, 1975] 21 S1S1 S2S2 S3S3 acquirey S1S1 T2T2 S3S3 y S1S1 T2T2 S3S3 releasex S1S1 S2S2 S3S3 x Right-mover Left-mover S1S1 S2S2 S3S3 locked accessy S1S1 T2T2 S3S3 locked-accessy S1S1 T2T2 S3S3 locked accessx S1S1 S2S2 S3S3 x Both-mover

22 22 Static mover check Static right-mover check between  and  : Simple cases –Mover check passes:  and  access different variables  and  disable each other –Fails:  writes to a variable and  reads it  and  both write to a variable, writes do not commute   22

23 Reduction: Syntactic to Semantic Notions of Commuting Accesses to independent variables y := 2 and x := z + t; Increment and increment x := x + 1 and x := x + 2 Acquire: Right mover Commutes to the right of any action But what about acq(L)  acq(L) acq(L)  acq(L) Both LHS and RHS block No execution has two consecutive acq(L)’s S1S1 S2S2 S3S3 acquirey S1S1 T2T2 S3S3 y S1S1 T2T2 S3S3 releasex S1S1 S2S2 S3S3 x

24 Reduction: Normal to Weird Notions of Commuting Lock protected accesses by two different threads p  q < q  p Why do they commute? q is never followed by p How is this captured in QED?

25 25 Static mover check fails: Apparent conflict acquire (lock); t1 := x; t1 := t1 + 1; x := t1; release(lock); acquire (lock); t2 := x; t2 := t2 + 1; x := t2; release(lock); Static mover check is local, fails! Individual actions do not locally contain the information: “Whenever this action executes, this thread holds the lock” Annotate action with local assertion: Express belief about non-interference 25

26 26 Auxiliary variable: Which thread holds the lock? inc (): acquire (lock); t1 = x; t1 = t1 + 1 x = t1; release(lock); inc (): acquire (lock); a := tid; t2 = x; t2 = t2 + 1 x = t2; release(lock); a := 0; AUX-ANNOTATE New invariant: (lock == true)  (a != 0) Auxiliary variable a is a history variable Summarizes relevant part of execution history 26

27 27 Annotating Actions with Assertions acquire (lock); a := tid; assert a == tid; t1 = x; t1 = t1+ 1 assert a == tid; x = t1; assert a == tid; release(lock); a := 0; acquire (lock); a := tid; t1= x; t1 = t1 + 1 x = t1; release(lock); a := 0; ABSTRACT Invariant: (lock == true)  (a != 0) Assertions indicate belief about non interference Annotate actions locally with global information about execution 27

28 History Variable Annotations Make Static Mover Check Pass 28 Thread 1 acquire (lock); a := tid1; assert a == tid1; t1 := x; t1 := t1 + 1 assert a == tid1; x := t1; assert a == tid1; release(lock); a := 0; R B B B L Thread 2 acquire (lock); a := tid2; assert a == tid2; t2 := x; t2 := t2 + 1 assert a == tid2; x := t2; assert a == tid2; release(lock); a := 0; assert a == tid1; x := t1; and assert a == tid2; x := t2; commute α  β β  α Because both α  β and β  α result in assertion violations. 28

29 29 Borrowing and paying back assertions inc (): acquire (lock); a := tid; assert a == tid; t1 = x; t1 = t1 + 1 assert a == tid; x = t1; assert a == tid; release(lock); a := 0; inc (): acquire (lock); a := tid; assert a == tid; t1 = x; t1 = t1 + 1 assert a == tid; x = t1; assert a == tid; release(lock); a := 0; REDUCE-SEQUENTIAL, DISCHARGE ASSERTIONS R B B B L Discharges the assertions Invariant: (lock == true)  (a != 0) 29

30 Reduction: Syntactic to Semantic Notions of Commuting What else commutes? Actions that operate on different parts of memory Different entries of a linked list Actions on nodes not yet inserted into a data structure with actions already in the data structure Currently thread local access with all actions Assertions annotate action with reason for non-interference

31 31 Semantic Reduction: Ruling out Apparent Interference assert !possiblyInList[t1]; t1.next := n1; assert possiblyInList[p2]; n2 := p2.next; possiblyInList[t] : False when a newly created node assigned to t. Set to true when p.next := t for some p. Remains true afterwards. assert possiblyInList[p2]; n2 := p2.next; assert !possiblyInList[t1]; t1.next := n1;   If p2 and t1 refer to the same node: LHS and RHS lead to assertion violations (i.e., not possible) Otherwise, no conflict. 31

32 Atomic Snapshot

33 class VersionedInteger { int v; int d; } VersionedInteger[] m; procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; } } procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb; atomic { va := m[a].v; da := m[a].d; } atomic { vb := m[b].v; db := m[b].d; } s := true; atomic { if (va < m[a].v) { s := false; } } atomic { if (vb < m[b].v) { s := false; } } }

34 class VersionedInteger { int v; int d; } VersionedInteger[] m; procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; } } procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb; atomic { havoc va, da; assume va <= m[a].v; if (va == m[a].v) { da := m[a].d; } } atomic { havoc vb, db; assume vb <= m[b].v; if (vb == m[b].v) { db := m[b].d; } } s := true; atomic { if (va < m[a].v) { s := false; } if (s) { havoc s; } } atomic { if (vb < m[b].v) { s := false; } if (s) { havoc s; } } } Left Mover Right Mover Left Mover

35 class VersionedInteger { int v; int d; } VersionedInteger[] m; procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; } } procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb; atomic { havoc va, da; assume va <= m[a].v; if (va == m[a].v) { da := m[a].d; } havoc vb, db; assume vb <= m[b].v; if (vb == m[b].v) { db := m[b].d; } s := true; if (va < m[a].v) { s := false; } if (s) { havoc s; } if (vb < m[b].v) { s := false; } if (s) { havoc s; } }

36 class VersionedInteger { int v; int d; } VersionedInteger[] m; procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; } } procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb; atomic { havoc va, da, vb, db, s; if (s) { va := m[a].v; da := m[a].d; vb := m[b].v; db := m[b].d; s := true; }

37 class VersionedInteger { int v; int d; } VersionedInteger[] m; procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; } } procedure Snapshot(int a, int b, out bool s, out int da, out int db) { atomic { havoc da, db, s; if (s) { da := m[a].d; db := m[b].d; } Hide va, vb

38 Abstraction + Reduction: Increment with CAS 38 t1 := x; s1 := CAS(x,t1,t1+1); t2 := x; s2 := CAS(x,t2,t2+1); || havoc t1; s1 := CAS(x,t1,t1+1); [ if (*) { s1:=false; } else { x:=x+1; s1:= true; } ] 38

39 QED-verified examples Fine-grained locking Linked-list with hand-over-hand locking [Herlihy-Shavit 08] Two-lock queue [Michael-Scott 96] Non-blocking algorithms Bakery [Lamport 74] Non-blocking stack [Treiber 86] Obstruction-free deque [Herlihy et al. 03] Non-blocking stack [Michael 04] Writer mode of non-blocking readers/writer lock [Krieger et al. 93] Non-blocking queue [Michael-Scott 96] Synchronous queue [Scherer-Lea-Scott 06] 39

40 QED and Optimistic Concurrency tressa: Mechanism to annotate actions with assertions that can refer to prophecy variables (future) assert: Discharged by reasoning about history of execution. tressa: Temporal dual of assert Example: y := y+1; z := z-1; assume (x == 0); 40

41 tressa : Temporal Dual of assert Example: y := y+1; // x == 0 or execution blocks z := z-1; // x == 0 or execution blocks assume (x == 0); But atomic{ assert x == 0; y := y+1;} atomic{ assert x == 0; z := z-1;} assume (x == 0); does not work! Cannot discharge the assertions! 41

42 tressa : Temporal Dual of assert Example: y := y+1; // x == 0 or execution blocks z := z-1; // x == 0 or execution blocks assume (x == 0); tressa φ: Either φ holds in the post state, or execution does not terminate (blocks). atomic{ y := y+1; tressa x == 0;} atomic{ z := z-1; tressa x == 0;} assume (x == 0); tressa annotations discharged by backwards reasoning within an atomic block. Discharged tressa φ: You cannot come back from a final state of the program and violate φ 42

43 43 Discharging tressa’s inc (): int t; acquire (lock); p =: 0 tressa a == tid; t = x; t = t + 1 tressa a == tid; x = t; release(lock); p =: tid; inc (): int t; acquire (lock); p =: 0; tressa p == tid; t = x; t = t + 1 tressa a == tid; x = t; release(lock); p =: tid; REDUCE & RELAX R B B B L

44 Pair Snapshot Example: Write public void Write(int a, int d) { atomic{ m[a].d = d; // Write data m[a].v++; // Increment version number } } 44

45 if TrySnapshot ends with s == true TrySnapshot(int a, int b) { atomic{ va = m[a].v; da = m[a].d; } atomic{ vb = m[b].v; db = m[b].d; } s = true; atomic{ if (va!=m[a].v) s = false; } atomic{ if (vb!=m[b].v) s = false; } } 45 a not written to b not written to (da,db) is a consistent snapshot

46 Other Work on QED Variable hiding Linearizability-preserving soundness theorem Annotation assistance: Automating proofs for simple programs Common synchronization idioms Verifying parallelizing compilers 46


Download ppt "Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach Shaz Qadeer Microsoft Research Redmond, WA Serdar Taşıran Serdar."

Similar presentations


Ads by Google