Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . even ( n ) } 12
Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } allocate ∃ n . x �→ n ∧ even ( n ) fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . even ( n ) } 12
Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } allocate ∃ n . x �→ n ∧ even ( n ) { True } { True } fetchandadd ( x , 2) fetchandadd ( x , 2) { True } { True } ! x { n . even ( n ) } 12
Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } allocate ∃ n . x �→ n ∧ even ( n ) { True } { True } { x �→ n ∧ even ( n ) } fetchandadd ( x , 2) fetchandadd ( x , 2) { x �→ n + 2 ∧ even ( n + 2) } { True } { True } ! x { n . even ( n ) } 12
Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } allocate ∃ n . x �→ n ∧ even ( n ) { True } { True } { x �→ n ∧ even ( n ) } { x �→ n ∧ even ( n ) } fetchandadd ( x , 2) fetchandadd ( x , 2) { x �→ n + 2 ∧ even ( n + 2) } { x �→ n + 2 ∧ even ( n + 2) } { True } { True } ! x { n . even ( n ) } 12
Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } allocate ∃ n . x �→ n ∧ even ( n ) { True } { True } { x �→ n ∧ even ( n ) } { x �→ n ∧ even ( n ) } fetchandadd ( x , 2) fetchandadd ( x , 2) { x �→ n + 2 ∧ even ( n + 2) } { x �→ n + 2 ∧ even ( n + 2) } { True } { True } { x �→ n ∧ even ( n ) } ! x { n . x �→ n ∧ even ( n ) } { n . even ( n ) } 12
Invariants in action Let us consider a simpler problem first: { True } let x = ref (0) in { x �→ 0 } allocate ∃ n . x �→ n ∧ even ( n ) { True } { True } { x �→ n ∧ even ( n ) } { x �→ n ∧ even ( n ) } fetchandadd ( x , 2) fetchandadd ( x , 2) { x �→ n + 2 ∧ even ( n + 2) } { x �→ n + 2 ∧ even ( n + 2) } { True } { True } { x �→ n ∧ even ( n ) } ! x { n . x �→ n ∧ even ( n ) } { n . even ( n ) } Problem: still cannot prove it returns 4 12
Ghost variables Consider the invariant: ∃ n . x �→ n ∗ . . . How to relate the quantified value to the state of the threads? 13
Ghost variables Consider the invariant: ∃ n . x �→ n ∗ . . . How to relate the quantified value to the state of the threads? Solution: ghost variables 13
Ghost variables Consider the invariant: ∃ n . x �→ n ∗ . . . How to relate the quantified value to the state of the threads? Solution: ghost variables Ghost variables are allocated in pairs: ∗ True ≡ − ∃ γ. γ ֒ → ∗ γ ֒ → • n ◦ n � �� � � �� � in the invariant in the Hoare triple 13
Ghost variables Consider the invariant: ∃ n 1 , n 2 . x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 How to relate the quantified value to the state of the threads? Solution: ghost variables Ghost variables are allocated in pairs: ∗ True ≡ − ∃ γ. γ ֒ → ∗ γ ֒ → • n ◦ n � �� � � �� � in the invariant in the Hoare triple 13
Ghost variables Consider the invariant: ∃ n 1 , n 2 . x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 How to relate the quantified value to the state of the threads? Solution: ghost variables Ghost variables are allocated in pairs: ∗ True ≡ − ∃ γ. γ ֒ → ∗ γ ֒ → • n ◦ n � �� � � �� � in the invariant in the Hoare triple When you own both parts you obtain that the values are equal and can update both parts: γ ֒ → • n ∗ γ ֒ → ⇒ n = m ◦ m ∗ • n ′ ∗ γ ֒ ◦ n ′ γ ֒ → • n ∗ γ ֒ → ◦ m ≡ − γ ֒ → → 13
Ghost variables in action { True } let x = ref (0) in fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ 4 ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ 4 ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • 2 } ! x { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ 4 ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • 2 } ! x { n . n = 4 ∧ γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ 4 ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • 2 } { n . n = 4 } 14
Ghost variables in action { True } let x = ref (0) in { x �→ 0 } { x �→ 0 ∗ γ 1 ֒ → • 0 ∗ γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → • 0 ∗ γ 2 ֒ → ◦ 0 } allocate ∃ n 1 , n 2 . x �→ n 1 + n 2 ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 { γ 1 ֒ → ◦ 0 ∗ γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 } { γ 2 ֒ → ◦ 0 } { γ 1 ֒ → ◦ 0 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 0 ∗ x �→ n 2 ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) { γ 1 ֒ → ◦ 0 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 0 ∗ γ 2 ֒ → • n 2 } { . . . } { γ 1 ֒ → ◦ 2 ∗ x �→ (2+ n 2 ) ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 } { γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ ( n 1 + n 2 ) ∗ γ 1 ֒ → • n 1 ∗ γ 2 ֒ → • n 2 } { γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ 4 ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • 2 } ! x { n . n = 4 ∧ γ 1 ֒ → ◦ 2 ∗ γ 2 ֒ → ◦ 2 ∗ x �→ 4 ∗ γ 1 ֒ → • 2 ∗ γ 2 ֒ → • 2 } { n . n = 4 } 14
Ghost variables with fractional permissions [Boyland] What if we have n threads? Using n different ghost variables, results in different proofs for each thread. That is not modular. Better way: ghost variables with a fractional permission (0 , 1] Q : π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 15
Ghost variables with fractional permissions [Boyland] What if we have n threads? Using n different ghost variables, results in different proofs for each thread. That is not modular. Better way: ghost variables with a fractional permission (0 , 1] Q : π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 You only get the equality when you have full ownership ( π = 1): 1 γ ֒ → • n ∗ γ ֒ − → ◦ m ⇒ n = m 15
Ghost variables with fractional permissions [Boyland] What if we have n threads? Using n different ghost variables, results in different proofs for each thread. That is not modular. Better way: ghost variables with a fractional permission (0 , 1] Q : π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 You only get the equality when you have full ownership ( π = 1): 1 γ ֒ → • n ∗ γ ֒ − → ◦ m ⇒ n = m Updating is possible with partial ownership (0 < π ≤ 1): ∗ π π γ ֒ → • n ∗ γ ֒ − → ◦ m ≡ − γ ֒ → • ( n + i ) ∗ γ ֒ → − ◦ ( m + i ) 15
Ghost variables with fractional permissions [Boyland] What if we have n threads? Using n different ghost variables, results in different proofs for each thread. That is not modular. Better way: ghost variables with a fractional permission (0 , 1] Q : π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 You only get the equality when you have full ownership ( π = 1): 1 γ ֒ → • n ∗ γ ֒ → − ◦ m ⇒ n = m Updating is possible with partial ownership (0 < π ≤ 1): ∗ π π γ ֒ → • n ∗ γ ֒ → − ◦ m ≡ − γ ֒ → • ( n + i ) ∗ γ ֒ − → ◦ ( m + i ) � n i π i Keeps the invariant that all γ ֒ − → ◦ n i sum up to γ ֒ → • 15
Fractional ghost variables in action { True } let x = ref (0) in fetchandadd ( x , 2) fetchandadd ( x , 2) . . . ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } fetchandadd ( x , 2) fetchandadd ( x , 2) . . . ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 fetchandadd ( x , 2) fetchandadd ( x , 2) . . . ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n fetchandadd ( x , 2) fetchandadd ( x , 2) . . . ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n � � � � 1 / 1 / k k γ ֒ − → ◦ 0 γ ֒ − → ◦ 0 fetchandadd ( x , 2) fetchandadd ( x , 2) . . . � � � � 1 / 1 / k k γ ֒ − → ◦ 2 γ ֒ − → ◦ 2 ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n � � � � 1 / 1 / k k γ ֒ − → ◦ 0 γ ֒ − → ◦ 0 � � 1 / k γ ֒ − → ◦ 0 ∗ x �→ n ∗ γ ֒ → • n fetchandadd ( x , 2) fetchandadd ( x , 2) . . . � � � � 1 / 1 / k k γ ֒ − → ◦ 2 γ ֒ − → ◦ 2 ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n � � � � 1 / 1 / k k γ ֒ − → ◦ 0 γ ֒ − → ◦ 0 � � 1 / k γ ֒ − → ◦ 0 ∗ x �→ n ∗ γ ֒ → • n fetchandadd ( x , 2) fetchandadd ( x , 2) . . . � � 1 / k γ ֒ − → ◦ 2 ∗ x �→ (2+ n ) ∗ γ 1 ֒ → • (2+ n ) � � � � 1 / 1 / k k γ ֒ − → ◦ 2 γ ֒ − → ◦ 2 ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n � � � � 1 / 1 / k k γ ֒ − → ◦ 0 γ ֒ − → ◦ 0 � � 1 / k γ ֒ − → ◦ 0 ∗ x �→ n ∗ γ ֒ → • n { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) . . . � � 1 / { . . . } k γ ֒ − → ◦ 2 ∗ x �→ (2+ n ) ∗ γ 1 ֒ → • (2+ n ) � � � � 1 / 1 / k k γ ֒ − → ◦ 2 γ ֒ − → ◦ 2 ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n � � � � 1 / 1 / k k γ ֒ − → ◦ 0 γ ֒ − → ◦ 0 � � 1 / k γ ֒ − → ◦ 0 ∗ x �→ n ∗ γ ֒ → • n { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) . . . � � 1 / { . . . } k γ ֒ − → ◦ 2 ∗ x �→ (2+ n ) ∗ γ 1 ֒ → • (2+ n ) � � � � 1 / 1 / k k γ ֒ − → ◦ 2 γ ֒ − → ◦ 2 � � 1 γ ֒ − → ◦ 2 k ∗ x �→ n ∗ γ ֒ → • n ! x { n . n = 2 k } 16
Fractional ghost variables in action { True } let x = ref (0) in { x �→ 0 } � � 1 x �→ 0 ∗ γ ֒ → • 0 ∗ γ ֒ − → ◦ 0 allocate ∃ n . x �→ n ∗ γ ֒ → • n � � � � 1 / 1 / k k γ ֒ − → ◦ 0 γ ֒ − → ◦ 0 � � 1 / k γ ֒ − → ◦ 0 ∗ x �→ n ∗ γ ֒ → • n { . . . } fetchandadd ( x , 2) fetchandadd ( x , 2) . . . � � 1 / { . . . } k γ ֒ − → ◦ 2 ∗ x �→ (2+ n ) ∗ γ 1 ֒ → • (2+ n ) � � � � 1 / 1 / k k γ ֒ − → ◦ 2 γ ֒ → − ◦ 2 � � 1 γ ֒ − → ◦ 2 k ∗ x �→ n ∗ γ ֒ → • n ! x � � 1 n . n = 2 k ∧ γ ֒ − → ◦ 2 k ∗ x �→ 2 k ∗ γ ֒ → • 2 k { n . n = 2 k } 16
Part #2: generalizing ownership [Ralf Jung, David Swasey, Filip Sieczkowski, Kasper Svendsen, Aaron Turon, Lars Birkedal and Derek Dreyer. Iris: Monoids and Invariants as an Orthogonal Basis for Concurrent Reasoning. In POPL’15] [Ralf Jung, Robbert Krebbers, Lars Birkedal and Derek Dreyer. Higher-Order Ghost State. In ICFP’16] 17
Mechanisms for concurrent reasoning We have seen so far: N ◮ Invariants R ◮ Ghost variables γ ֒ → • n and γ ֒ → ◦ n π ◮ Fractional ghost variables γ ֒ → • n and γ ֒ − → ◦ n Where do these mechanisms come from? 18
There are many CSLs with more powerful mechanisms. . . Owick i-Gries (1976) RS L (2013) Rely -Gua ra ntee (1983) CS L (2004) Borna t-a l (2005) FS L (2016) RGS ep (2007) Bell-a l (2010) S AGL (2007) Hobor -a l (2008) Den y -Gua ra ntee (2009) Gots m a n-a l (2007) LRG (2009) CAP (2010) Ja cobs -Pies s ens (2011) HLRG (2010) RGS im (2012) HOCAP (2013) S CS L (2013) Lia ng -Feng (2013) T a DA (2014) iCAP (2014) Ca ReS L (2013) FTCS L (2015) CoLoS L (2015) FCS L (2014) Iris (2015) GPS (2014) T ota l-T a DA (2016) LiLi (2016) Iris 2.0 (2016) Iris 3 .0 (2016) Picture by Ilya Sergey 19
. . . and very complicated primitive rules 20
The Iris story Owick i-Gries (1976) RS L (2013) Rely -Gua ra ntee (1983) CS L (2004) Borna t-a l (2005) FS L (2016) RGS ep (2007) Bell-a l (2010) S AGL (2007) Hobor -a l (2008) Den y -Gua ra ntee (2009) Gots m a n-a l (2007) LRG (2009) CAP (2010) Ja cobs -Pies s ens (2011) HLRG (2010) RGS im (2012) HOCAP (2013) S CS L (2013) Lia ng -Feng (2013) T a DA (2014) iCAP (2014) Ca ReS L (2013) FTCS L (2015) CoLoS L (2015) FCS L (2014) Iris (2015) GPS (2014) T ota l-T a DA (2016) LiLi (2016) Iris 2.0 (2016) Iris 3 .0 (2016) Picture by Ilya Sergey The Iris story: all of these mechanisms can be encoded using a simple mechanism of resource ownership 21
Generalizing ownership All forms of ownership have common properties: ◮ Ownership of different threads can be composed For example: π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 22
Generalizing ownership All forms of ownership have common properties: ◮ Ownership of different threads can be composed For example: π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 ◮ Composition of ownership is associative and commutative Mirroring that parallel composition and separating conjunction is associative and commutative 22
Generalizing ownership All forms of ownership have common properties: ◮ Ownership of different threads can be composed For example: π 1 + π 2 π 1 π 2 γ ֒ − − − → ◦ ( n 1 + n 2 ) ⇔ γ ֒ − → ◦ n 1 ∗ γ ֒ − → ◦ n 2 ◮ Composition of ownership is associative and commutative Mirroring that parallel composition and separating conjunction is associative and commutative ◮ Combinations of ownership that do not make sense are ruled out For example: 1 / 1 / 2 2 γ ֒ → • 5 ∗ γ ֒ − → ◦ 3 ∗ γ ֒ − → ◦ 4 ⇒ False (because 5 � = 3 + 4) 22
Resource algebras Resource algebra with carrier M : ◮ Composition ( · ) : M → M → M ◮ Validity predicate V ⊆ M Satisfying: a · b = b · a a · ( b · c ) = ( a · b ) · c ( a · b ) ∈ V ⇒ a ∈ V 23
Resource algebras Resource algebra with carrier M : ◮ Composition ( · ) : M → M → M ◮ Validity predicate V ⊆ M Satisfying: a · b = b · a a · ( b · c ) = ( a · b ) · c ( a · b ) ∈ V ⇒ a ∈ V γ for each resource algebra M Iris has ghost variables a : M ∗ ∃ γ. a γ ∗ b γ ⇔ a · b γ ⇒ V ( a ) γ γ a ∈ V ≡ − a a ∀ a f . a · a f ∈ V ⇒ b · a f ∈ V ∗ b γ ≡ γ a − 23
Ghost variables revisited Resource algebra for ghost variables: M � • n | ◦ n | ⊥ | • ◦ n V � { a � = ⊥ | a ∈ M } � if n = n ′ • ◦ n • n · ◦ n ′ = ◦ n ′ · • n � ⊥ otherwise other combinations � ⊥ And define: γ γ • n � • n ◦ n � ◦ n γ ֒ → γ ֒ → 24
Ghost variables revisited Resource algebra for ghost variables: M � • n | ◦ n | ⊥ | • ◦ n V � { a � = ⊥ | a ∈ M } � if n = n ′ • ◦ n • n · ◦ n ′ = ◦ n ′ · • n � ⊥ otherwise other combinations � ⊥ And define: γ γ • n � • n ◦ n � ◦ n γ ֒ → γ ֒ → The ghost variable rules follow directly from the general rules: ∗ ∃ γ. γ ֒ True ≡ − → • n ∗ γ ֒ → ◦ n 24
Ghost variables revisited Resource algebra for ghost variables: M � • n | ◦ n | ⊥ | • ◦ n V � { a � = ⊥ | a ∈ M } � if n = n ′ • ◦ n • n · ◦ n ′ = ◦ n ′ · • n � ⊥ otherwise other combinations � ⊥ And define: γ γ • n � • n ◦ n � ◦ n γ ֒ → γ ֒ → The ghost variable rules follow directly from the general rules: ∗ ∃ γ. • ∗ ∃ γ. γ ֒ γ ≡ True ≡ − ◦ n − → • n ∗ γ ֒ → ◦ n 24
Ghost variables revisited Resource algebra for ghost variables: M � • n | ◦ n | ⊥ | • ◦ n V � { a � = ⊥ | a ∈ M } � if n = n ′ • ◦ n • n · ◦ n ′ = ◦ n ′ · • n � ⊥ otherwise other combinations � ⊥ And define: γ γ • n � • n ◦ n � ◦ n γ ֒ → γ ֒ → The ghost variable rules follow directly from the general rules: ∗ ∃ γ. • ∗ ∃ γ. γ ֒ γ ≡ True ≡ − ◦ n − → • n ∗ γ ֒ → ◦ n γ ֒ → • n ∗ γ ֒ → ◦ m ⇒ n = m 24
Ghost variables revisited Resource algebra for ghost variables: M � • n | ◦ n | ⊥ | • ◦ n V � { a � = ⊥ | a ∈ M } � if n = n ′ • ◦ n • n · ◦ n ′ = ◦ n ′ · • n � ⊥ otherwise other combinations � ⊥ And define: γ γ • n � • n ◦ n � ◦ n γ ֒ → γ ֒ → The ghost variable rules follow directly from the general rules: ∗ ∃ γ. • ∗ ∃ γ. γ ֒ γ ≡ True ≡ − ◦ n − → • n ∗ γ ֒ → ◦ n γ ֒ → • n ∗ γ ֒ → ◦ m ⇒ ( • n · ◦ m ) ∈ V ⇒ n = m 24
Updating resources Resources can be updated using frame-preserving updates: ∀ a f . a · a f ∈ V ⇒ b · a f ∈ V ∗ b γ ≡ γ a − Key idea: a resource can be updated if the update does not invalidate the resources of concurrently-running threads Thread 1 Thread 2 . . . Thread n · · . . . · ∈ V a 1 a 2 a n � · · . . . · ∈ V b 1 a 2 a n 25
Updating resources Resources can be updated using frame-preserving updates: ∀ a f . a · a f ∈ V ⇒ b · a f ∈ V ∗ b γ ≡ γ a − Key idea: a resource can be updated if the update does not invalidate the resources of concurrently-running threads Thread 1 Thread 2 . . . Thread n · · . . . · ∈ V a 1 a 2 a n � · · . . . · ∈ V b 1 a 2 a n ∗ γ ֒ • n ′ ∗ γ ֒ ◦ n ′ follows directly The rule γ ֒ → • n ∗ γ ֒ → ◦ m ≡ − → → 25
In the papers ◮ The full definition of a resource algebra (RA) ◮ Combinators (fractions, products, finite maps, agreement, etc.) to modularly build many RAs ◮ Encoding of state transition systems as RAs γ in terms of something even simpler ◮ Encoding of a ◮ Higher order ghost state : RAs that circularly depend on iProp , the type of propositions Iris: Monoids and Invariants as an Higher-Order Ghost State Orthogonal Basis for Concurrent Reasoning Ralf Jung Robbert Krebbers Lars Birkedal Derek Dreyer MPI-SWS, Germany Aarhus University, Denmark Aarhus University, Denmark MPI-SWS, Germany Ralf Jung David Swasey Filip Sieczkowski Kasper Svendsen jung@mpi-sws.org mail@robbertkrebbers.nl birkedal@cs.au.dk dreyer@mpi-sws.org MPI-SWS & MPI-SWS Aarhus University Aarhus University Saarland University swasey@mpi-sws.org filips@cs.au.dk ksvendsen@cs.au.dk jung@mpi-sws.org f a r t i c t Abstract Aaron Turon Lars Birkedal Derek Dreyer A were tied to a “conditional critical region” construct for synchro- t n * o C m p t e l * * e t s e * A nization. Since O’Hearn’s pioneering (and Gödel-award-winning) i n s e W E The development of concurrent separation logic (CSL) has sparked a Mozilla Research Aarhus University MPI-SWS L C o l l C paper, there has been an avalanche of follow-on work extending O P * o D * long line of work on modular verification of sophisticated concurrent P e u s m u c aturon@mozilla.com birkedal@cs.au.dk dreyer@mpi-sws.org * R e o n t e E CSL with more sophisticated mechanisms for modular reasoning, d t s y E a d * e a v programs. Two of the most important features supported by several e t a u l which allow shared state to be accessed at a finer granularity ( e.g., existing extensions to CSL are higher-order quantification and atomic compare-and-swap instructions) and which support the ver- custom ghost state . However, none of the logics that support both ification of more “daring” (less clearly synchronized) concurrent of these features reap the full potential of their combination. In programs [40, 17, 16, 13, 18, 38, 35, 27, 11, 24]. Abstract TaDA [ 8 ], and others. In this paper, we present a logic called Iris that particular, none of them provide general support for a feature we explains some of the complexities of these prior separation logics in In this paper, we focus on two of the most important extensions We present Iris, a concurrent separation logic with a simple premise: dub “higher-order ghost state” : the ability to store arbitrary higher- to CSL— higher-order quantification and custom ghost state —and monoids and invariants are all you need . Partial commutative terms of a simpler unifying foundation, while also supporting some order separation-logic predicates in ghost variables. new and powerful reasoning principles for concurrency. observe that, although several logics support both of these exten- monoids enable us to express—and invariants enable us to enforce— In this paper, we propose higher-order ghost state as a interesting sions, none of them reap the full potential of their combination. In user-defined protocols on shared state, which are at the conceptual Before we get to Iris, however, let us begin with a brief overview and useful extension to CSL, which we formalize in the framework particular, none of them provide general support for a feature we of some key problems that arise in reasoning compositionally about of Jung et al. ’s recently developed Iris logic. To justify its soundness, core of most recent program logics for concurrency. Furthermore, shared state, and how prior approaches have dealt with them. dub “higher-order ghost state”. through a novel extension of the concept of a view shift , Iris supports we develop a novel algebraic structure called CMRAs (“cameras”), Higher-order quantification is the ability to quantify logical the encoding of logically atomic specifications , i.e., Hoare-style which can be thought of as “step-indexed partial commutative 1.1 Invariants and their limitations assertions (universally and existentially) over other assertions and, 26
Part #3: encoding Hoare triples [Robbert Krebbers, Ralf Jung, Aleˇ s Bizjak, Jacques-Henri Jourdan, Derek Dreyer, and Lars Birkedal. The Essence of Higher-Order Concurrent Separation Logic. In ESOP’17] 27
Encoding Hoare triples Step 1: define Hoare triple in terms of weakest preconditions: { P } e { w . Q } � � ( P − ∗ wp e { w . Q } ) where wp e { w . Q } gives the weakest precondition under which: ◮ all executions of e are safe ◮ all return values v of e satisfy the postcondition Q [ v / w ] 28
Encoding Hoare triples Step 1: define Hoare triple in terms of weakest preconditions: { P } e { w . Q } � � ( P − ∗ wp e { w . Q } ) where wp e { w . Q } gives the weakest precondition under which: ◮ all executions of e are safe ◮ all return values v of e satisfy the postcondition Q [ v / w ] Step 2: define weakest precondition: Q [ e / w ] if e ∈ Val ∀ σ. red ( e , σ ) ∧ if e �∈ Val wp e { w . Q } � ⊲ ( ∀ e 2 , σ 2 . ( e , σ ) → ( e 2 , σ 2 , ǫ ) − ∗ wp e 2 { w . Q } ) Recursive occurrence guarded by a later ⊲ 28
Adding the points-to connective How to connect the states to ℓ �− → v ? Q [ e / w ] if e ∈ Val ∀ σ. if e �∈ Val wp e { w . Q } � red ( e , σ ) ∧ ⊲ ( ∀ e 2 , σ 2 . ( e , σ ) → ( e 2 , σ 2 , ǫ ) − ∗ wp e 2 { w . Q } ) → v � ??? ℓ �− 29
Adding the points-to connective How to connect the states to ℓ �− → v ? Q [ e / w ] if e ∈ Val ∀ σ. if e �∈ Val wp e { w . Q } � red ( e , σ ) ∧ ⊲ ( ∀ e 2 , σ 2 . ( e , σ ) → ( e 2 , σ 2 , ǫ ) − ∗ wp e 2 { w . Q } ) → v � ??? ℓ �− Solution: ghost variables 29
Adding the points-to connective How to connect the states to ℓ �− → v ? ⇛ Q [ e / w ] | if e ∈ Val γ − ⇛ ∀ σ. • σ ∗ | if e �∈ Val wp e { w . Q } � red ( e , σ ) ∧ ⇛ ⊲ ( ∀ e 2 , σ 2 . ( e , σ ) → ( e 2 , σ 2 , ǫ ) − ∗ | γ ∗ wp e 2 { w . Q } ) • σ 2 γ → v � ◦ [ ℓ := v ] ℓ �− Solution: ghost variables Using an appropriate resource algebra we can obtain: γ ∗ ◦ [ ℓ := w ] γ ⇒ σ ( ℓ ) = w • σ γ ∗ ◦ [ ℓ := v ] γ ≡ ∗ • σ [ ℓ := w ] γ ∗ ◦ [ ℓ := w ] γ • σ − ∗ • σ [ ℓ := w ] γ ≡ γ ∗ ◦ [ ℓ := w ] γ • σ − if ℓ / ∈ dom ( σ ) 29
Recommend
More recommend