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.
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
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
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
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
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
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
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
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
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
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
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
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
Relaxed program logics ◮ RSL (relaxed separation logic, OOPSLA’13) ◮ FSL (fenced separation logic, VMCAI’16) ◮ GPS (ghosts & protocols, OOPSLA’14, PLDI’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
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
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
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
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
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
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
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
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
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
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
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