1 / 50

Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach

Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach. http ://qed.codeplex.com [POPL ’ 09, TACAS ‘ 10, PADTAD ‘ 10, VSTTE ‘ 10]. Shaz Qadeer Microsoft Research Redmond, WA. Serdar Taşıran , Tayfun Elmas , Ali Sezgin

trina
Download Presentation

Generalizing Reduction and Abstraction to Simplify Concurrent Programs: The QED Approach

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Generalizing Reduction and Abstraction to Simplify Concurrent Programs:The QED Approach http://qed.codeplex.com [POPL ’09, TACAS ‘10, PADTAD ‘10, VSTTE ‘10] ShazQadeer Microsoft ResearchRedmond, WA Serdar Taşıran, TayfunElmas, Ali Sezgin Koç UniversityIstanbul, Turkey

  2. QED: Simplify (coarsen), then verify P1 P2 Pn . . . check Correct

  3. Coarser Atomic Actions • Difficult to prove • Fine-grain concurrency • Annotations at every • interleaving point • Easy to prove • Larger atomic blocks • Local, sequential analysis • within atomic blocks P1 P2 Pn . . . check Correct

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

  5. Owicki-Gries proof, fine-grain actions Thread A Thread B x := 0; assert 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 } { 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 } 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 ||

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

  7. Soundness P1 P2 Pn . . . check Soundness theorem: IfPn is correct (satisfies all assertions) then 1. all P1 ≤ i ≤n are correct. 2. Pnpreserves behaviors of all P1 ≤ i ≤n . Completeness: Subsumes Owicki-Gries [Nieto, 2007] Correct

  8. QED: Simplifier; complements other methods x := 0; assert x == 2; 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); } acquire(lock); t := x; t := t + 1; x := t; release(lock); acquire(lock); k := x; k := k + 1; x := k; release(lock); x := 0; x := x + 1; x := x + 1; assert x == 2; || || Owicki-Gries (12 location invariants) Simpler Owicki-Gries (4 location invariants) Sequential analysis Correct Correct Correct

  9. QED-verifier http://qed.codeplex.com P1 P2 Pn ... P1 QEDPL program Correct Pn reduce abstract ..... reduce check Boogie 2, Z3 Proof script

  10. Automation using SMT solver P1 P2 Pn . . . reduce abstract reduce VC VC VC Valid Valid Valid check Correct VC Valid

  11. ActionPL Syntax: Procedure bodies Global variables Program’s main body Program:

  12. Gated actions Gate: Assertion on pre-state Transition: Two-store relation x = x + 1; assert (x != 0); y = y / x; x = x + 1; assert (x != 0); y = y / x;

  13. Semantics of ActionPL Current dynamic statement Current store Execution: Atomic transitions: Pre- and post-store satisfies transition Pre-store violates assertion Pre-store satisfies assertion

  14. Operational semantics

  15. Proof method Proof context Program invariant (proof ensures this) Each execution starts from invariant Each transition preserves invariant Current program • Proof step: Governed by a proof rule • May strengthen invariant • May rewrite program

  16. QED Program Transformations

  17. QED: Deciding Mover Types

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

  19. QED’s Idea of Abstraction 19 abstracted by   s1 If for all :   s1 s1 1. If error error then   s1 s2 s1 s2 2. If then  s1 or error • Going wrong more often is sound for assertion checking

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

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

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

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

  24. Mover check in QED: Static, local, semantic A B S1 S2 S3 A Right-mover ? All actions in program run by different thread B A S1 T2 S3 ... For each : ... B ... ; ; A B B A First-order verification condition

  25. Traditional use of reduction [Lipton, 1975] locked access release x x S1 S1 S2 S2 S3 S3 locked access release x x S1 S1 T2 T2 S3 S3 locked access acquire y y S1 S1 S2 S2 S3 S3 y y locked-access acquire S1 S1 T2 T2 S3 S3 Left-mover Right-mover Both-mover Both-mover

  26. 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

  27. x release S1 S2 S3 release x S1 T2 S3 acquire y S1 S2 S3 y acquire S1 T2 S3 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 aboutacq(L) acq(L) acq(L) acq(L) • Both LHS and RHS block • No execution has two consecutive acq(L)’s

  28. 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?

  29. Static mover check fails: Apparent conflict 29 • 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 acquire (lock); t1 := x; t1 := t1 + 1; x := t1; release(lock); acquire (lock); t2 := x; t2 := t2 + 1; x := t2; release(lock);

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

  31. Annotating Actions with Assertions 31 Invariant: (lock == true) (a != 0) 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 • Assertions indicate belief about non interference • Annotate actions locally with global information about execution

  32. 32 History Variable Annotations Make Static Mover Check Pass 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; 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; R B B B L • assert a == tid1; x := t1; andassert a == tid2; x := t2; commute • α  β β α • Because both α  β and β  α result in assertion violations.

  33. Borrowing and paying back assertions 33 Invariant: (lock == true) (a != 0) Discharges the 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; R B B B L REDUCE-SEQUENTIAL, DISCHARGE ASSERTIONS

  34. 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 withactions already in the data structure • Currently thread local access with all actions • Assertions annotate action with reason for non-interference

  35. 35 Semantic Reduction: Ruling out Apparent Interference • 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;  assert !possiblyInList[t1]; t1.next := n1; assert possiblyInList[p2]; n2:= p2.next;  • If p2 and t1 refer to the same node: • LHS and RHS lead to assertion violations (i.e., not possible) • Otherwise, no conflict.

  36. Atomic Snapshot

  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 intdb) { intva, 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; } } }

  38. 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 intdb) { intva, 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; } } } Right Mover Right Mover Left Mover Left Mover

  39. 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 intdb) { intva, 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; } } }

  40. 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 intdb) { intva, 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; } } }

  41. 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 intdb) { atomic { havoc da, db, s; if (s) { da := m[a].d; db := m[b].d; } } } Hide va, vb

  42. 42 Abstraction + Reduction: Increment with CAS 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; } ]

  43. 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 [Treiber86] • 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]

  44. 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);

  45. tressa : Temporal Dual of assert • Example:y := y+1; // x == 0 or execution blocksz := 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!

  46. tressa : Temporal Dual of assert • Example:y := y+1; // x == 0 or execution blocksz := 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 φ

  47. 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; R B B B L REDUCE & RELAX

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

  49. if TrySnapshot ends with s == true TrySnapshot(inta, 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; } } a not written to (da,db) isa consistentsnapshot b not written to

  50. Other Work on QED • Variable hiding • Linearizability-preserving soundness theorem • Annotation assistance: • Automating proofs for simple programs • Common synchronization idioms • Handling relaxed memory models [Ongoing]

More Related