proving a concurrent program correct by
play

Proving a Concurrent Program Correct by Demonstrating It Does - PowerPoint PPT Presentation

Proving a Concurrent Program Correct by Demonstrating It Does Nothing Bernhard Kragl IST Austria doi: 10.1007/978-3-319-96145-3_5 https://github.com/boogie-org/boogie Shaz Qadeer Microsoft https://www.rise4fun.com/civl Credits Cormac


  1. Proving a Concurrent Program Correct by Demonstrating It Does Nothing Bernhard Kragl IST Austria doi: 10.1007/978-3-319-96145-3_5 https://github.com/boogie-org/boogie Shaz Qadeer Microsoft https://www.rise4fun.com/civl

  2. Credits Cormac Flanagan Stephen N. Freund Serdar Tasiran Tayfun Elmas Chris Hawblitzel

  3. Program verification Program 𝒬 Verifier Is 𝒬 safe? Error report Proof

  4. Program verification Invariants Program Templates 𝒬 Proof structure … Verifier Is 𝒬 safe? Error report Proof

  5. Reasoning about transition systems β€’ Transition system π‘Šπ‘π‘ , π½π‘œπ‘—π‘’, 𝑂𝑓𝑦𝑒, 𝑇𝑏𝑔𝑓 π‘Šπ‘π‘  (Variables) π½π‘œπ‘—π‘’ (Initial state predicate over π‘Šπ‘π‘  ) 𝑂𝑓𝑦𝑒 (Transition predicate over π‘Šπ‘π‘  βˆͺ π‘Šπ‘π‘ β€² ) 𝑇𝑏𝑔𝑓 (Safety predicate over π‘Šπ‘π‘  ) β€’ Inductive invariant π½π‘œπ‘€ π½π‘œπ‘—π‘’ β‡’ π½π‘œπ‘€ (Initialization) π½π‘œπ‘€ ∧ 𝑂𝑓𝑦𝑒 β‡’ π½π‘œπ‘€ β€² (Preservation) π½π‘œπ‘€ β‡’ 𝑇𝑏𝑔𝑓 (Safety)

  6. Structured program vs. Transition relation Init: π‘žπ‘‘ = π‘žπ‘‘ 1 = π‘žπ‘‘ 2 = 𝑏 Next: π‘žπ‘‘ = 𝑏 ∧ π‘žπ‘‘ β€² = π‘žπ‘‘ 1 β€² = π‘žπ‘‘ 2 β€² = 𝑐 ∧ 𝑦 β€² = 0 ∧ π‘“π‘Ÿ π‘š, 𝑒 1 , 𝑒 2 a: x := 0 β€² = 𝑑 ∧ Β¬π‘š ∧ π‘š β€² ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 2 , 𝑦, 𝑒 1 , 𝑒 2 π‘žπ‘‘ 1 = 𝑐 ∧ π‘žπ‘‘ 1 b: acquire(l) acquire(l) β€² = 𝑒 ∧ 𝑒 1 β€² = 𝑦 ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 2 , π‘š, 𝑦, 𝑒 2 π‘žπ‘‘ 1 = 𝑑 ∧ π‘žπ‘‘ 1 c: t1 := x t2 := x β€² = 𝑓 ∧ 𝑒 1 β€² = 𝑒 1 + 1 ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 2 , π‘š, 𝑦, 𝑒 2 π‘žπ‘‘ 1 = 𝑒 ∧ π‘žπ‘‘ 1 d: t1 := t1+1 t2 := t2+1 β€² = 𝑔 ∧ 𝑦 β€² = 𝑒 1 ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 2 , π‘š, 𝑒 1 , 𝑒 2 π‘žπ‘‘ 1 = 𝑓 ∧ π‘žπ‘‘ 1 e: x := t1 x := t2 β€² = 𝑕 ∧ Β¬π‘š β€² ∧ π‘“π‘Ÿ(π‘žπ‘‘, π‘žπ‘‘ 2 , 𝑦, 𝑒 1 , 𝑒 2 ) π‘žπ‘‘ 1 = 𝑔 ∧ π‘žπ‘‘ 1 f: release(l) release(l) β€² = 𝑑 ∧ Β¬π‘š ∧ π‘š β€² ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 1 , 𝑦, 𝑒 1 , 𝑒 2 π‘žπ‘‘ 2 = 𝑐 ∧ π‘žπ‘‘ 2 β€² = 𝑒 ∧ 𝑒 2 β€² = 𝑦 ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 1 , π‘š, 𝑦, 𝑒 1 g: assert x = 2 π‘žπ‘‘ 2 = 𝑑 ∧ π‘žπ‘‘ 2 β€² = 𝑓 ∧ 𝑒 2 β€² = 𝑒 2 + 1 ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 1 , π‘š, 𝑦, 𝑒 1 π‘žπ‘‘ 2 = 𝑒 ∧ π‘žπ‘‘ 2 β€² = 𝑔 ∧ 𝑦 β€² = 𝑒 2 ∧ π‘“π‘Ÿ π‘žπ‘‘, π‘žπ‘‘ 1 , π‘š, 𝑒 1 , 𝑒 2 π‘žπ‘‘ 2 = 𝑓 ∧ π‘žπ‘‘ 2 β€² = 𝑕 ∧ Β¬π‘š β€² ∧ π‘“π‘Ÿ(π‘žπ‘‘, π‘žπ‘‘ 1 , 𝑦, 𝑒 1 , 𝑒 2 ) π‘žπ‘‘ 2 = 𝑔 ∧ π‘žπ‘‘ 2 Procedures and dynamic thread creation π‘žπ‘‘ 1 = π‘žπ‘‘ 2 = 𝑕 ∧ π‘žπ‘‘β€² = 𝑕 ∧ π‘“π‘Ÿ(π‘žπ‘‘ 1 , π‘žπ‘‘ 2 , π‘š, 𝑦, 𝑒 1 , 𝑒 2 ) complicate transition relation further! Safe: π‘žπ‘‘ = 𝑕 β‡’ 𝑦 = 2

  7. Interference freedom and Owicki-Gries Ξ¨ 1 : 𝑄 1 𝐷 1 {𝑅 1 } Ξ¨ 2 : 𝑄 2 𝐷 2 𝑅 2 Ξ¨ 1 , Ξ¨ 2 interference free 𝑄 1 ∧ 𝑄 2 𝐷 1 βˆ₯ 𝐷 2 𝑅 1 ∧ 𝑅 2 β€’ Example: 𝑦 = 0 𝑦 ≔ 𝑦 + 1 βˆ₯ 𝑦 ≔ 𝑦 + 2 𝑦 = 3 𝑦 = 0 𝑦 = 0 𝑦 = 0 Interference freedom: 𝑄 1 : {𝑦 = 0 ∨ 𝑦 = 2} 𝑄 2 : {𝑦 = 0 ∨ 𝑦 = 1} 𝑄 1 ∧ 𝑄 2 𝑦 ≔ 𝑦 + 2 𝑄 𝑄 2 ∧ 𝑄 1 𝑦 ≔ 𝑦 + 1 𝑄 2 1 𝑦 ≔ 𝑦 + 1 𝑦 ≔ 𝑦 + 2 𝑅 1 ∧ 𝑄 2 𝑦 ≔ 𝑦 + 2 𝑅 1 𝑅 2 ∧ 𝑄 1 𝑦 ≔ 𝑦 + 1 𝑅 2 𝑅 1 : 𝑦 = 1 ∨ 𝑦 = 3 𝑅 2 : 𝑦 = 2 ∨ 𝑦 = 3 𝑅 1 ∧ 𝑅 2 𝑦 = 3

  8. Ghost variables Need to refer to other thread’s state β€’ local variables β€’ program counter β€’ Example: 𝑦 = 0 𝑦 ≔ 𝑦 + 1 βˆ₯ 𝑦 ≔ 𝑦 + 1 𝑦 = 2 𝑦 = 0 π‘’π‘π‘œπ‘“ 1 ≔ π‘”π‘π‘šπ‘‘π‘“; π‘’π‘π‘œπ‘“ 2 ≔ π‘”π‘π‘šπ‘‘π‘“ 𝑄 1 : Β¬π‘’π‘π‘œπ‘“ 1 ∧ Β¬π‘’π‘π‘œπ‘“ 2 β‡’ 𝑦 = 0 ∧ π‘’π‘π‘œπ‘“ 2 β‡’ 𝑦 = 1 𝑄 2 : Β¬π‘’π‘π‘œπ‘“ 2 ∧ Β¬π‘’π‘π‘œπ‘“ 1 β‡’ 𝑦 = 0 ∧ π‘’π‘π‘œπ‘“ 1 β‡’ 𝑦 = 1 𝑦 ≔ 𝑦 + 1; π‘’π‘π‘œπ‘“ 1 ≔ 𝑒𝑠𝑣𝑓 𝑦 ≔ 𝑦 + 1; π‘’π‘π‘œπ‘“ 2 ≔ 𝑒𝑠𝑣𝑓 𝑅 1 : π‘’π‘π‘œπ‘“ 1 ∧ Β¬π‘’π‘π‘œπ‘“ 2 β‡’ 𝑦 = 1 ∧ π‘’π‘π‘œπ‘“ 2 β‡’ 𝑦 = 2 𝑅 2 : π‘’π‘π‘œπ‘“ 2 ∧ Β¬π‘’π‘π‘œπ‘“ 1 β‡’ 𝑦 = 1 ∧ π‘’π‘π‘œπ‘“ 1 β‡’ 𝑦 = 2 𝑦 = 2

  9. Rely/Guarantee Rely/Guarantee specifications 𝐷 ⊨ (𝑄, 𝑆, 𝐻, 𝑅) for individual threads and composition rule allow for modular proofs of loosely-coupled systems. 𝑦 β‰₯ 0 𝑆 = 𝐻 = 𝑦 β€² β‰₯ 𝑦 𝑦 ≔ 𝑦 + 1 βˆ₯ 𝑦 ≔ 𝑦 + 1 𝑄 = 𝑅 = 𝑦 β‰₯ 0 𝑦 β‰₯ 0

  10. Multi-layered refinement proofs [skip] || 𝑄 1 β‰Ό 𝑄 2 β‰Ό β‹― β‰Ό 𝑄 π‘œβˆ’1 β‰Ό 𝑄 𝑄 π‘œ is safe π‘œ 𝑄 1 is safe Advantages of structured proofs: Better for humans: easier to construct and maintain Better for computers: localized/small checks οƒ  easier to automate Programs that do nothing cannot go wrong

  11. Refinement is well-studied β€’ Logic β€’ 𝑄 𝑦, 𝑦 β€² β‡’ 𝑅(𝑦, 𝑦 β€² ) β€’ Labeled transition systems β€’ Language containment β€’ Simulation (forward, backward, upward, downward, diagonal, sideways, …) β€’ Bisimulation (vanilla, mint, lavender, barbed, triangulated, complicated, …) β€’ …

  12. Refinement is difficult for programs β€’ Programs are complicated β€’ Complex control and data β€’ Gap between program syntax and abstractions β€’ … especially for concurrent programs β€’ … especially for interactive proof construction

  13. CIVL: Construct correct concurrent programs layer by layer procedure P(…) { S } β€’ Operates on program syntax S1; S2 β€’ Organizes proof as a sequence of program if (e) S1 else S2 layers with increasingly coarse-grained while (e) S atomic actions call P β€’ All layers and supporting invariants async call P expressed together in one textual unit call P1 || P2 β€’ Automatically-generated verification call A conditions

  14. Gated atomic actions [Elmas, Q, Tasiran 2009] (Gate, Transition) single-state predicate two-state predicate Command Gate Transition Lock specification 𝑦 β€² = 𝑦 + 𝑧 ∧ 𝑧 β€² = 𝑧 𝑒𝑠𝑣𝑓 x := x+y var lock : ThreadID βˆͺ {nil} 𝑧 β€² = 𝑧 𝑒𝑠𝑣𝑓 havoc x Acquire(): [assume lock == nil; lock := tid] 𝑦 β€² = 𝑦 ∧ 𝑧 β€² = 𝑧 𝑦 < 𝑧 assert x<y Release(): [assert lock == tid; lock := nil] 𝑦 < 𝑧 ∧ 𝑦 β€² = 𝑦 ∧ 𝑧 β€² = 𝑧 𝑒𝑠𝑣𝑓 assume x<y β€’ Unifies precondition and postcondition β€’ Primitive for modeling a (concrete or abstract) concurrent program

  15. Operational semantics β„“, 𝑑 β‹… β€’ Program configuration 𝑕, 𝑔 ⊎ 𝒰 β€’ Transition relation β‡’ between configurations (and failure configuration βŠ₯ ) β‡’ βˆ— βŠ₯ β€’ Safety: Β¬βˆƒπ‘•β„“: 𝑕, β„“, π‘π‘π‘—π‘œ β‡’ βˆ— βŠ₯ β€’ 𝐻𝑝𝑝𝑒 𝑄 = 𝑕 Β¬βˆƒβ„“: 𝑕, β„“, π‘π‘π‘—π‘œ β‡’ βˆ— 𝑕 β€² , βˆ… 𝑕, 𝑕 β€² β€’ π‘ˆπ‘ π‘π‘œπ‘‘ 𝑄 = βˆƒβ„“: 𝑕, β„“, π‘π‘π‘—π‘œ β€’ 𝑄 1 β‰Ό 𝑄 2 : (1) 𝐻𝑝𝑝𝑒 𝑄 2 βŠ† 𝐻𝑝𝑝𝑒 𝑄 (2) 𝐻𝑝𝑝𝑒(𝑄 2 ) ∘ π‘ˆπ‘ π‘π‘œπ‘‘ 𝑄 1 βŠ† π‘ˆπ‘ π‘π‘œπ‘‘(𝑄 2 ) 1 𝑄 2 preserves failures 𝑄 2 preserves final states

  16. var x; IncrBy2() = call IncrBy2() [ x := x + 2 ] var x; Incr() = Op() { call Op() || Op() [ x := x + 1 ] call Incr() } var lock; Acquire() = Release() = Op() { call Op() || Op() var x; [ assume lock == nil; [ assert lock == tid; var t; lock := tid; ] lock := nil; ] call Acquire(); t := x; x := t + 1; call Release(); } var b; Acquire() { Release() { Op() { call Op() || Op() var x; while (true) b := 0; var t; if (CAS(b, 0, 1)) break; } call Acquire(); } t := x; x := t + 1; call Release(); }

  17. const c >= 0; var x; call Main(); Main() { // Create c threads // each executing Incr  [assert x β‰₯ 0] } Incr() { acquire(); assert x β‰₯ 0; x := x + 1; release(); }

  18. const c >= 0; var x; call Main(); Main() { x := 0; // Create c threads  [ ] // each executing Incr } Incr() { acquire(); assert x β‰₯ 0; x := x + 1; release(); }

  19. Programs constructed with CIVL β€’ Concurrent garbage collector [Hawblitzel, Petrank, Q, Tasiran 2015] β€’ FastTrack2 race-detection algorithm [Flanagan, Freund, Wilcox 2018] β€’ Lock-protected memory atop TSO [Hawblitzel] β€’ Thread-local heap atop shared heap [Hawblitzel, Q] β€’ Two-phase commit [K, Q, Henzinger 2018] β€’ Work-stealing queue, Treiber stack, Ticket, …

  20. Program layers in CIVL β€’ A CIVL program denotes a sequence of concurrent programs (layers) β€’ chained together by a refinement-preserving transformation β€’ Transformation between program layers combines β€’ Atomization: Transform statement S into atomic block [S] β€’ Summarization: Transform atomic block [S] into atomic action A β€’ Abstraction: Replace atomic action A with atomic action B

  21. Right and left movers [Lipton 1975] Integer a β€œSemaphore” β€œwait” β€œsignal” P(a) = [assume a > 0; a := a - 1] V(a) = [a := a + 1] right mover (R) left mover (L) Y V(a) P(a) X S 1 S 2 S 3 S 1 S 2 S 3 V(a) Y X P(a) S 1 T 2 S 3 S 1 T 2 S 3 Sequence R*;(N+ ο₯ ); L* is atomic . . . . R* X N Y L* S 0 S 5 . . . . R* X N L* Y S 0 S 5

Recommend


More recommend