software verification under weak memory consistency
play

Software verification under weak memory consistency Viktor - PowerPoint PPT Presentation

Software verification under weak memory consistency Viktor Vafeiadis Max Planck Institute for Software Systems (MPI-SWS) January 2016 Joint work with Soham Chakraborty, Derek Dreyer, Marko Doko, Nick Giannarakis, Ori Lahav, Chinmay Narayan,


  1. Software verification under weak memory consistency Viktor Vafeiadis Max Planck Institute for Software Systems (MPI-SWS) January 2016 Joint work with Soham Chakraborty, Derek Dreyer, Marko Doko, Nick Giannarakis, Ori Lahav, Chinmay Narayan, Joseph Tassarotti, Aaron Turon.

  2. Sequential consistency Sequential consistency (SC): ◮ The standard model for concurrency. ◮ Interleave each thread’s atomic accesses. ◮ Almost all verification work assumes it. Initially, x = y = 0. x := 1; y := 1; a := y b := x In SC, this program cannot return a = b = 0. Viktor Vafeiadis Software verification under weak memory consistency 2

  3. Store buffering in x86-TSO . . . cpu 1 cpu n write . . . read write-back Memory Initially, x = y = 0. x := 1; y := 1; a := y ; b := x ; This program can return a = b = 0. Viktor Vafeiadis Software verification under weak memory consistency 3

  4. Owicki-Gries method (1976) OG = Hoare logic + rule for parallel composition { P 1 } c 1 { Q 1 } { P 2 } c 2 { Q 2 } the two proofs are non-interfering { P 1 ∧ P 2 } c 1 � c 2 { Q 1 ∧ Q 2 } Non-interference R ∧ P ⊢ R { u / x } for every: ◮ assertion R in the proof outline of one thread ◮ assignment x := u with precondition P in the proof outline of the other thread Viktor Vafeiadis Software verification under weak memory consistency 4

  5. Standard OG is unsound for WM � � a � = 0 x := 1; y := 1; a := y b := x � � a � = 0 ∨ b � = 0 Viktor Vafeiadis Software verification under weak memory consistency 5

  6. Standard OG is unsound for WM � � a � = 0 � � � � a � = 0 ⊤ x := 1; y := 1; � � � � x � = 0 y � = 0 a := y b := x � � � � x � = 0 y � = 0 ∧ ( a � = 0 ∨ b = x ) � � a � = 0 ∨ b � = 0 Viktor Vafeiadis Software verification under weak memory consistency 5

  7. Standard OG is unsound for WM � � a � = 0 � � � � a � = 0 ⊤ x := 1; y := 1; � � � � x � = 0 y � = 0 a := y b := x � � � � x � = 0 y � = 0 ∧ ( a � = 0 ∨ b = x ) � � a � = 0 ∨ b � = 0 To regain soundness, strengthen the non-inference check. = ⇒ OGRA: Owicki-Gries for release-acquire (ICALP’15) Viktor Vafeiadis Software verification under weak memory consistency 5

  8. Outline ◮ Introduction to the C11 weak memory model ◮ Release-acquire synchronization ◮ Per-location coherence ◮ Reasoning about WMM using program logics ◮ RSL (relaxed separation logic) ◮ FSL (fenced separation logic) ◮ GPS (ghosts, protocols and separation) ◮ Avoiding to reason about WMM ◮ Use reduction theorems Viktor Vafeiadis Software verification under weak memory consistency 6

  9. The C11 memory model: Atomics Two types of locations Ordinary Atomic (Non-Atomic) Welcome to the Races are errors expert mode Viktor Vafeiadis Software verification under weak memory consistency 7

  10. The C11 memory model: Hierarchy of atomics A spectrum of atomic accesses: Seq. consistent full memory fence Release write Acquire read no fence (x86); lwsync (PPC) no fence (x86); isync (PPC) Relaxed no fence Explicit primitives for fences Viktor Vafeiadis Software verification under weak memory consistency 8

  11. Store buffering in C11 Initially x = y = 0. x . store(1 , rlx ); y . store(1 , rlx ); print ( y . load( rlx )); print ( x . load( rlx )); Can print 00 with the following execution: [ x = y = 0] po po rlx ( x , 1) rlx ( y , 1) W W rf rf po po R rlx ( y , 0) R rlx ( x , 0) Viktor Vafeiadis Software verification under weak memory consistency 9

  12. Release-acquire synchronization Initially a = x = 0. a = 5; while ( x . load( acq ) == 0); x . store(1 , release ); print( a ); One possible execution: na ( a , 0) na ( x , 0) W W na ( a , 5) R acq ( x , 0) W sw W rel ( x , 1) R acq ( x , 1) R na ( a , 5) Happens before: hb = ( po ∪ sw ) + Viktor Vafeiadis Software verification under weak memory consistency 10

  13. Coherence Programs with a single shared variable behave as under SC. x . store(1 , rlx ); x . store(2 , rlx ); a = x . load( rlx ); b = x . load( rlx ); The outcome a = 2 ∧ b = 1 is forbidden. mo rlx ( x , 1) rlx ( x , 2) W W reads-before R rlx ( x , 2) R rlx ( x , 1) ◮ Modification order, mo x , total order of writes to x . ◮ Reads-before : rb � ( rf − 1 ; mo ) ∩ ( � =) ◮ Coherence : hb ∪ rf x ∪ mo x ∪ rb x is acyclic for all x . Viktor Vafeiadis Software verification under weak memory consistency 11

  14. Relaxed program logics ◮ RSL (relaxed separation logic, OOPSLA’13) ◮ FSL (fenced separation logic, VMCAI’16) ◮ GPS (ghosts & protocols, OOPSLA’14, PLDI’15)

  15. Separation logic Key concept of ownership : ◮ Resourceful reading of Hoare triples. { P } C { Q } ◮ To access a non-atomic location, you must own it: { x �→ v } ∗ x { t . t = v ∧ x �→ v } { x �→ v } ∗ x = v ′ ; { x �→ v ′ } ◮ Disjoint parallelism: { P 1 } C 1 { Q 1 } { P 2 } C 2 { Q 2 } { P 1 ∗ P 2 } C 1 � C 2 { Q 1 ∗ Q 2 } Viktor Vafeiadis Software verification under weak memory consistency 13

  16. Rules for release/acquire accesses Ownership transfer by rel-acq synchronizations. ◮ Atomic allocation � pick loc. invariant Q . {Q ( v ) } x = alloc( v ); { W Q ( x ) ∗ R Q ( x ) } ◮ Release write � give away permissions. {Q ( v ) ∗ W Q ( x ) } x . store( v , rel ); { W Q ( x ) } ◮ Acquire read � gain permissions. { R Q ( x ) } t = x . load( acq ); {Q ( t ) ∗ R Q [ t :=emp] ( x ) } Viktor Vafeiadis Software verification under weak memory consistency 14

  17. Release-acquire synchronization: message passing Initially a = x = 0. Let J ( v ) � v = 0 ∨ & a �→ 5. { & a �→ 0 ∗ W J ( x ) } { R J ( x ) } a = 5; while ( x . load( acq ) == 0); { & a �→ 5 ∗ W J ( x ) } { & a �→ 5 } x . store( release , 1); print( a ); { W J ( x ) } { & a �→ 5 } PL consequences: Ownership transfer works! Viktor Vafeiadis Software verification under weak memory consistency 15

  18. Relaxed accesses Basically, disallow ownership transfer. ◮ Relaxed reads: { R Q ( x ) } t := x . load( rlx ) { R Q ( x ) ∧ ( Q ( t ) �≡ false ) } ◮ Relaxed writes: Q ( v ) = emp { W Q ( x ) } x . store( v , rlx ) { W Q ( x ) } Unsound because of dependency cycles! Viktor Vafeiadis Software verification under weak memory consistency 16

  19. Dependency cycles Initially x = y = 0. if ( x . load ( rlx ) == 1) if ( y . load ( rlx ) == 1) y . store (1 , rlx ); x . store (1 , rlx ); C11 allows the outcome x = y = 1. Justification: R rlx ( x , 1) R rlx ( y , 1) Relaxed accesses don’t synchronize rlx ( y , 1) rlx ( x , 1) W W Viktor Vafeiadis Software verification under weak memory consistency 17

  20. Dependency cycles Initially x = y = 0. if ( x . load ( rlx ) == 1) if ( y . load ( rlx ) == 1) y . store (1 , rlx ); x . store (1 , rlx ); C11 allows the outcome x = y = 1. What goes wrong: Non-relational invariants are unsound. x = 0 ∧ y = 0 The DRF-property does not hold. Viktor Vafeiadis Software verification under weak memory consistency 17

  21. Dependency cycles Initially x = y = 0. if ( x . load ( rlx ) == 1) if ( y . load ( rlx ) == 1) y . store (1 , rlx ); x . store (1 , rlx ); C11 allows the outcome x = y = 1. How to fix this: Don’t use relaxed writes ∨ Strengthen the model Viktor Vafeiadis Software verification under weak memory consistency 17

  22. Incorrect message passing int a ; atomic_int x = 0;   a = 5; if ( x . load( rlx ) � = 0) {     x . store(1 , rlx ); print ( a ); } na ( a , 5) R rlx ( x , 1) W race W rlx ( x , 1) R na ( a , ? ) Viktor Vafeiadis Software verification under weak memory consistency 18

  23. Message passing with C11 memory fences int a ; atomic_int x = 0;   a = 5; if ( x . load( rlx ) � = 0) { fence( release ); fence( acq );     x . store(1 , rlx ); print ( a ); } na ( a , 5) R rlx ( x , 1) W sw F rel F acq W rlx ( x , 1) R na ( a , 5) Viktor Vafeiadis Software verification under weak memory consistency 18

  24. Reasoning about fences ◮ Introduce two ‘modalities’ in the logic { P } fence( release ) {△ P } { W Q ( x ) ∗ △Q ( v ) } x . store( v , rlx ) { W Q ( x ) } { R Q ( x ) } t := x . load( rlx ) { R Q [ t :=emp] ( x ) ∗ ▽Q ( t ) } {▽ P } fence( acq ) { P } Viktor Vafeiadis Software verification under weak memory consistency 19

  25. Reasoning about fences Let Q ( v ) � v = 0 ∨ & a �→ 5. { & a �→ 0 ∗ W Q ( x ) ∗ R Q ( x ) } t = x . load( rlx );  { & a �→ 0 ∗ W Q ( x ) }  {▽ ( t = 0 ∨ & a �→ 5) } a = 5;     { & a �→ 5 ∗ W Q ( x ) } if ( t � = 0)      fence( release );  fence( acq );     {△ ( & a �→ 5) ∗ W Q ( x ) } { & a �→ 5 }     x . store(1 , rlx ); print ( a ); }     {⊤} {⊤} Viktor Vafeiadis Software verification under weak memory consistency 20

  26. GPS: A better logic for release-acquire Three key features: ◮ Location protocols ◮ Ghost state/tokens ◮ Escrows for ownership transfer Example (Racy message passing) Initially, x = y = 0. x . store(1 , rlx ); x . store(1 , rlx ); t = y . load( acq ); t ′ = x . load( rlx ); y . store(1 , rel ); y . store(1 , rel ); Cannot get t = 1 ∧ t ′ = 0. Viktor Vafeiadis Software verification under weak memory consistency 21

Recommend


More recommend