Rely/guarantee

An introduction to rely/guarantee reasoning about concurrency

Pre I assume that this lecture starts at 8:30am Ian J. Hayes (and Cliff B. Jones) Guarantee you will understand to rely/guarantee reasoning Rely that you ask questions when you don’t understand The University of Queensland, Australia (and Newcastle University, UK) Post finish this lecture at 9:30am SETSS Spring School Chongqing, China 2017-04-17–19

1 / 1 2 / 1

Overview Your background

Logic and set theory

I Propositional logic: , and ∧ ∨ ¬ I Predicate logic: and I Deriving sequential programs ∀ ∃ I Set theory: , , , and ... I Example: Sieve of Eratosthenes ∈ ⊆ ∪ ∩ { } I Deriving concurrent programs I Specification languages: VDM, Z, B and TLA

I Example: Sieve of Eratosthenes Reasoning about programs I Example: Communicating through a circular buffer I : p c q I Semantics of concurrent programs { } { } î ó I Refinement calculus or B or Event-B: , x : p , q v I Rely/guarantee concurrency

I Separation logic

I Concurrent separation logic

3 / 1 4 / 1 Reasoning about (concurrent) software Compositional reasoning

Our main tool is abstraction: Reasoning about the whole is decomposed into reasoning about the components

sequential specify components using pre/post conditions Why? I Make reasoning tractable I e.g. sorting I Partition the work (e.g. for multiple people to work on different I precondition noduplicates(s) components) 0 0 I postcondition ordered(s ) items(s ) = items(s) I Avoid reasoning about paths ∧ data use abstractions such as sets and maps j := 0; I decouple the specification of what the user sees from the while j = N do 6 implementation if p then s else t; I avoid the details of the implementations, such as, linked lists and j := j + 1 trees N process due to interference between processes need more than pre and post I 2 possible paths

5 / 1 6 / 1

Hoare logic is compositional Parallel composition

Structured reasoning about programs Interference possible before or after every atomic step si and ti

I Sequential composition s ; s ; ... ; sn t ; t ; ... ; tn 1 2 k 1 2 p s q q t r { } { }{ } { } p s ; t r { } { } I The number of paths in terms of n explodes

I While loop using a p I If there is no interference between s and t

p b s p p s q p t q { ∧ } { } { 1} { 1}{ 2} { 2} p while b do s p b p p s t q q { } { ∧ ¬ } { 1 ∧ 2} k { 1 ∧ 2}

For termination one needs to add a loop variant or well-founded relation I But this is the easy case

7 / 1 8 / 1 Example: Sieve of Eratosthenes (sequential) REM(2)

I Determine primes up to some given n I Illustrates: I starting with abstract type (a set) 1 2 3 4 5 6 7 8 9 10 11 12 ... I using guarantees (even for a sequential program) I introducing loops I data refinement to an array of small sets that can each fit in a word

REM(3)

9 / 1 10 / 1

Specification in refinement calculus style Sieve of Eratosthenes - sequential Concrete syntax

I Precondition s 2 .. n holds initially ⊆ I Assume that C is the set of all composite numbers (non-primes) 0 I Postcondition s = s C − VDM Refinement calculus î ó s : s 2 .. n , s0 = s C ⊆ − SIEVE SIEVE =“ = equivalent post condition (set theory) î 0 ó î ó ext wr s : FN1 s 2 .. n s : s = s C s : s 2 .. n , s0 s s s0 C s0 C = pre s 2 .. n { ⊆ } − ⊆ ⊆ ∧ − ⊆ ∧ ∩ ∅ ⊆ guarantee on every step post s0 = s C v î ó − (guar s0 s s s0 C) s : s 2 .. n , s0 C = ⊆ ∧ − ⊆ e ⊆ ∩ ∅ The guarantee condition is 0 0 0 I reflexive, i.e. s = s s s s s C 0 ⇒00 ⊆ ∧ 00− ⊆ 00 0 0 0 I transitive, i.e. s s s s s C s s C s s s s C ⊆ ⊆ ∧ − ⊆ ∧ − ⊆ ⇒ ⊆ ∧ − ⊆

11 / 1 12 / 1 First some set theory Then some number theory

Assume ci is the set of all multiples of i, excluding i

s0 C = If 2 i 2 j and if i j n then either ≤ ∧ ≤ ∗ ≤ 0 ∩ S ∅ 2 2 s j N 2 j cj = I i n j n or ≡ ∩ { ∈ | ≤ · } ∅ S 0 2 ≤ ∧ 2 ≥ j N 2 j (s cj ) = I j n i n ≡ { ∈ | ≤ · 0 ∩ } ∅ j N 2 j s cj = ≤ ∧ ≥ ≡ ∀ ∈ · ≤ ⇒ ∩ ∅ Hence one only has to remove multiples of i up to the (integer part of) the square Therefore root of i 2 0 0 s 0 .. n n i ( j 2 .. i s c = ) (guar s s s s C) e ⊆ ∧ ≤ ∧ ∀ ∈ · ∩ j ∅ î ⊆ ∧ − 0⊆ ó s : s 2 .. n , s C = ⇒ ⊆ ∩ ∅ ( j N 2 j s cj = ) by above set theory ∀ ∈ · ≤ ⇒ ∩ ∅ v 0 0 (guar s s s s C) e î ⊆ ∧ − ⊆ ó The predicate ( j 2 .. i s cj = ) holds if i is 1 s : s 2 .. n , j 2 j s0 c = ∀ ∈ · ∩ ∅ ⊆ ∀ · ≤ ⇒ ∩ j ∅ The refinement now focuses on just the specification (the second line)

13 / 1 14 / 1

Introducing a loop Refining the loop body

ñs 2 .. n (i + 1)2 n i < i0 ô i, s : ⊆ ∧ ≤ ∧ , ∧ 0 j 2 .. i s c = j 2 .. i s cj = ∀ ∈ · ∩ j ∅ ∀ ∈ · ∩ ∅ î ó introduce sequential composition s : s 2 .. n , j 2 j s0 c = v ⊆ ∀ · ≤ ⇒ ∩ j ∅ i := i + 1; introduce variable i to be used as loop index ñ 2 ô v s 2 .. n i n var i := 1; s : ⊆ ∧ ≤ ∧ , 0 j 2 .. i 1 s cj = j 2 .. i s cj = ñs 2 .. n n < (i + 1)2 ô ∀ ∈ − · ∩ ∅ ∀ ∈ · ∩ ∅ i, s : ⊆ ∧ , ∧ j 2 .. i s c = j 2 .. i s0 c = Refining the specification: ∀ ∈ · ∩ j ∅ j introduce while loop ∀ ∈ · ∩ ∅ v 2 ñ 2 ô while(i + 1) n do s 2 .. n i n 0 ñ ≤ ô s : ⊆ ∧ ≤ ∧ , j 2 .. i s cj = s 2 .. n (i + 1)2 n i < i0 j 2 .. i 1 s cj = ∀ ∈ · ∩ ∅ i, s : ⊆ ∧ ≤ ∧ , ∧ 0 ∀ ∈ − · ∩ ∅ j 2 .. i s cj = j 2 .. i s cj = to achieve the post condition the elements in ci need to be removed ∀ ∈ · ∩ ∅ ∀ ∈ · ∩ ∅ v î 2 0 ó s : s 2 .. n i n , s ci = ⊆ ∧ ≤ ∩ ∅ recall that ci contains all the multiples of i, excluding i v î ó s : s 2 .. n i2 n , j 2 i j i n j i s0 ⊆ ∧ ≤ ∀ · ∗ ≤ ∗ ≤ ⇒ ∗ 6∈ Reminder: this is all in the context of (guar s0 s s s0 C) ⊆ ∧ − ⊆ 15 / 1 16 / 1 Introduce inner loop Refine the inner loop body

s 2 .. n 2 i k i n k < k 0  k, s :  j⊆ 2 i ∧j ∗i <≤k ∗i ≤ ∧ , j 2 ∧i j i < k i  î ó   s : s 2 .. n i2 n , j 2 i j i n j i s0 ∀ · j ∗i ≤s ∗ ∗ ⇒ ∀ · j ∗i ≤s0∗ ∗ ⇒ ⊆ ∧ ≤ ∀ · ∗ ≤ ∗ ≤ ⇒ ∗ 6∈ ∗ 6∈ ∗ 6∈ introduce variable k to be used as a loop index introduce sequential composition v v var k := 2; s 2 .. n 2 i k i n    s 2 .. n i2 n n < k i  ⊆ ∧ ∗ ≤ ∗ ≤ ∧  s :  j 2 i j i < k i , j 2 i j i < (k + 1) i ;  ⊆ ∧ ≤ ∧ ∗ ∧  ∀ · ∗ ≤ ∗ ∗ ⇒ ∀ · ∗ ≤ 0∗ ∗ ⇒ k, s :  j 2 i j i < k i , j 2 i j i < k i  j i s j i s ∀ · ∗ ≤ ∗ ∗ ⇒ ∀ · ∗ ≤ 0∗ ∗ ⇒ ∗ 6∈ ∗ 6∈ j i s j i s k := k + 1 ∗ 6∈ ∗ 6∈ introduce inner loop v while k i n do Now refine the specification ∗ ≤ 0  s 2 .. n 2 i k i n k < k   k, s :  j⊆ 2 i ∧j ∗i <≤k ∗i ≤ ∧ , j 2 ∧i j i < k i  s 2 .. n 2 i k i n ∀ · ∗ ≤ ∗ ∗ ⇒ ∀ · ∗ ≤ ∗ ∗ ⇒  ⊆ ∧ ∗ ≤ ∗ ≤ ∧  j i s j i s0 s :  j 2 i j i < k i , j 2 i j i < (k + 1) i  ∗ 6∈ ∗ 6∈ ∀ · j ∗i ≤s ∗ ∗ ⇒ ∀ · j ∗i ≤s0∗ ∗ ⇒ ∗ 6∈ ∗ 6∈ to achieve the post condition the element k i must be removed v î ó ∗ s : s 2 .. n 2 i k i n , k i s0 ⊆ ∧ ∗ ≤ ∗ ≤ ∗ 6∈

17 / 1 18 / 1

Bring back the guarantee Remove an element from the set

Define î ó Rem(m) = (guar s0 s s s0 m ) s : s 0 .. n m 0 .. n , m s0 “ ⊆ ∧ − ⊆ { } e ⊆ ∧ ∈ 6∈ Now recall that this was all in the context of a guarantee. The code so far is 0 0 î 0ó (guar s s s s C) e s : s 2 .. n 2 i k i n , k i s ⊆ ∧ − ⊆ ⊆ ∧ ∗ ≤ ∗ ≤ ∗ 6∈ var i := 1; strengthen guarantee and weaken precondition v î ó while(i + 1)2 n do (guar s0 s s s0 k i ) s : s 0 .. n k i 0 .. n , k i s0 ≤ ⊆ ∧ − ⊆ { ∗ } e ⊆ ∧ ∗ ∈ ∗ 6∈ i := i + 1; var k := 2; while k i n do Rem∗ (k≤ i); k := k +∗ 1

19 / 1 20 / 1 Data refinement: representing the set as an array of words Remove an element from the set

Define î ó Rem(m) = (guar s0 s s s0 m ) s : s 0 .. n m 0 .. n , m s0 “ ⊆ ∧ − ⊆ { } e ⊆ ∧ ∈ 6∈ † £ I A finite set contained in 0 .. n can be represented by a bit map of n + 1 bits Using the representation as an array v : array 0 .. n+1 1 of (0 .. ws 1) ws − − I Assume a word has ws bits 0 0 (guar retr(v ) retr(v) retr(v) retr(v ) m ) e I A word can represent a set with ws elements î ⊆ ∧ − ⊆ó { } v : retr(v) 0 .. n m 0 .. n , m retr(v 0) I A word can represent a set contained in the set 0 .. ws 1 ⊆ ∧ ∈ 6∈ † n+1 £ − I For a large set one needs a vector v of ws words From the definition of retr I The retr(v) retrieves the set represented by v m retr(v 0) (m mod ws) v 0(m div ws) 6∈ ⇔ 6∈ retr(v) = j 0 .. n (j mod ws) v(j div ws) “ { ∈ | ∈ } Hence the specification can be written as î ó v : retr(v) 0 .. n m 0 .. n , (m mod ws) v 0(m div ws) ⊆ ∧ ∈ 6∈ v î ó v(m div ws): m 0 .. n , (m mod ws) v 0(m div ws) ∈ 6∈

21 / 1 22 / 1

Removing an element from a set represented as a single word Conclusions

RemW (var w : F(0 .. ws 1), i : 0 .. ws 1) =“ 0 − 0 − (guar w w w w i ) e î ⊆ ∧ − ⊆ { } ó w : w 0 .. ws 1 i 0 .. ws 1 , i / w 0 ⊆ − ∧ ∈ − ∈ I Importance of data abstraction

Therefore I Guarantee allows one to focus on the interesting part Rem(m)

v RemW (v(m div ws), m mod ws)

RemW can be implemented using bit-wise operations on a word (exercise)

23 / 1 24 / 1 Example: Parallel SIEVE of Eratosthenes

I Determine primes up to some given n I Illustrates:

? I starting with abstract type I need to document interference (R) I interplay between G/Q I development to code (using CAS) I symmetric processes (identical R/G)

25 / 1 26 / 1

Intuition REM(2)

I data abstraction: shared set of N1 I initialize: all (positive) natural numbers from 2 up to n

I remove all composites

I for sequential for i = 2 post condition of each RemMults(i) iteration is easy 1 2 3 4 5 6 7 8 9 10 11 12 ... 4 0 ··· RemMults(i) s :[s = s ci ] 4 − I for Sieve fi RemMults(i) 0 I need the rely of RemMults(i) to be s s ⊆ 0 I relax the equality in the postcondition of RemMults(i) to s ci = ∩ ∅0 I avoid removing too much with a guarantee of RemMults(i) of s s ci − ⊆ I because processes are identical, have to add a guarantee of no reinsertion REM(3)

27 / 1 28 / 1 Rely/Guarantee (R/G) idea is simple Interference between processes face interference (in specifications and design process)

An example of interference on process P by process Q

I One shared variable j pre rely z }| { I process Q may do atomic steps that either z}|{ 0 σ0 (σi σi+1) π(σj σj+1) σf I do not change j, i.e. j = j, or ··· ··· | {z } ··· 0 guar I increment j by one, i.e. j = j + 1 | {z } post I before or after each atomic step of process P, it may observe 0 I no steps of Q, i.e. j = j 0 0 I one step of Q, i.e. j = j j = j + 1 ∨0 I many steps of Q, i.e. j j ≤ I assumptions pre/rely 0 0 0 I Observing that both j = j and j = j + 1 imply j j ≤ I commitments guar/post 0 I Hence we can use j j to represent the possible interference from Q on P ≤ This abstract view of the interference becomes

rely conditions an abstraction of interference to be tolerated I a rely condition of P

relations are key to R/G I a guarantee condition of Q

29 / 1 30 / 1

R/G rethought R/G rethought “pulling apart” old R/G notation — literally!

R/G (old) Proof rules (also used a 5-tuple form) R/G (old) R/G decomposed [?, ?] RemMults(i) P, R s G , Q { l } l { l l } ext wr s : FN1 P, Rr sr Gr , Qr s 0 .. n { } { } { ⊆ 0 } pre s 0 .. n R Gr Rl guar(s s ) 0⊆ ∨ ⇒ ⊆ 0 ∧ · · · • rely s s R Gl Rr RemMults(i) rely s s 0⊆ ∨ ⇒ ⊆ 0 • guar s s Gl Gr G ext wr s : FN1 s :[s = s ci ] 0 ⊆ ∧ · · · ∨ ⇒ ∗ − post s = s c P Q Qr (R G Gr ) Q pre s 0 .. n − i ∧ l ∧ ∧ ∨ l ∨ ⇒ ⊆ P, R s s G, Q rely s0 s l r ⊆ Now [?] { } || { } guar s0 s ⊆ ∧ · · · post s0 = s c − i RemMults(i : N) s 0 .. n { ⊆ 0 } (rely s s) e 0⊆ 0 (guar s s s s ci ) e î ⊆ ∧ó − ⊆ s : s0 c = ∩ i ∅

31 / 1 32 / 1

Par I − R/G rethought (Some) Laws of the new algebraic R/G . . . a few of many!

Advantage of the new style: brings out (algebraic) properties

Distribute-G-seq Conjoin-G: (guar g ) (guar g ) = (guar g g ) 1 e 2 1 ∧ 2 (guar g) e (c ; d) = ((guar g) e c) ; ((guar g) e d) Strengthen-G: (guar g ) (guar g ) Distribute-G-par 1 v 2 (guar g) (c d) = ((guar g) c) ((guar g) d) if g2 g1 e k e k e ⇒ Conjunction-mono Distribute-G: ((guar g) e fi ci = fi (guar g) e ci c c d d c d c d 0 v 1 ∧ 0 v 1 ⇒ 0 e 0 v 1 e 1

33 / 1 34 / 1

Trading rely, guarantee and post Introducing a parallel composition

îV ó î ó î ó î ó Intro-multi-Par: (rely r) e i qi fi (guar ρ) e (rely ρ) e qi Trading-R-G-Post: (rely r) (r g)∗ q (rely r) (guar g) q v e ∨ ∧ v e e if r ρ (asymmetric version later) ⇒

35 / 1 36 / 1 Refinement calculus style development Onwards to code

s initially contains set of natural numbers from 2 up to some n The set ci contains all the multiples of i (except i 1) ∗ C is the set of all composite numbers RemMults(i : N) 0 î 0 ó s 0..n (rely s = s) e s : s = s C { ⊆ } î ó − (guar s0 s s s0 c ) (rely s0 s) s : s0 c = = set theory ⊆ ∧ − ⊆ i e ⊆ e ∩ i ∅ 0 î 0 0 0 ó (rely s = s) s : s s s s C s C = Can be implemented by successively removing each multiple e ⊆ ∧ − ⊆ ∧ ∩ ∅ by Trading-R-G-Post as s0 s s s0 C is reflexive and transitive v 0 0 ⊆ ∧0 − ⊆ î 0 ó var k := 2; (guar s s s s C) e (rely s = s) e s : s C = 0 ⊆ ∧ − 0⊆ S S 0 ∩ ∅ 0 while k i n do = as s C = s i ci = i (s ci ) = i . s ci = ∗ ≤ 0 ∩ ∅ ≡ 0 ∩ ∅ ≡0 ∩ î ∅0 ≡ ∀ ∩ó ∅ Rem(k i); (guar s s s s C) (rely s = s) s : i s ci = ∗ ⊆ ∧ − ⊆ e e ∀ · ∩ ∅ k := k + 1 by Intro-multi-Par v 0 0 0 0 î 0 ó (guar s s s s C) (f (guar s s) (rely s s) s : s ci = ) The interesting part is Rem. Its specification allows interference that removes ⊆ ∧ − ⊆ e i ⊆ e ⊆ e ∩ ∅ = Distribute-G and Conjoin-G elements from s. It guarantees to remove element m, only. 0 0 0 î 0 ó fi (guar s s s s C) e (rely s s) e s : s ci = ⊆ ∧ − ⊆ ⊆ ∩ ∅ Rem(m : N) Strengthen-G v î ó s 0 .. n m 0 .. n (guar s0 s s s0 c ) (rely s0 s) s : s0 c = { ⊆ ∧ ∈ } î ó fi i e e i (guar s0 s s s0 m ) (rely s0 s) s : m s0 ⊆ ∧ − ⊆ ⊆ ∩ ∅ ⊆ ∧ − ⊆ { } e ⊆ e 6∈

37 / 1 38 / 1

Removing an element from a set atomically Compare and swap

The specification of Rem allows interference that removes elements from s. It guarantees to remove element m, only. The implementation without locks makes use of a compare-and-swap (CAS) Rem(m : N) s 0 .. n m 0 .. n CAS(var w, lw, nw, var done) =“ { ⊆ 0 ∧ ∈ 0 } 0 î 0ó 0 0 0 (guar s s s s m ) e (rely s s) e s : m s (rely lw = lw nw = nw done = done) e ⊆ ∧ − ⊆ { } ⊆ 6∈ Æ (w∧ = lw w 0∧= nw done0) ∏ Represent the set s as an array v of words each representing part of the set w, done : (w = lw ⇒ w 0 = w ∧ done0)∧ n+1 6 ⇒ ∧ ¬ v : array 0.. ws 1 of F(0 .. ws 1) d e − − Under rely condition w 0 w assuming lw, nw and done are local Representation relation ⊆ Æ ∏ retr(v) = j 0 .. n j mod ws v(j div ws) w lw nw = lw i , w, done : { ∈ | ∈ } (w⊆= lw∧ w 0 = w− { i} ) (w = lw w 0 lw) Implementation using RemW which removes an element from set (as a word) ⇒ − { } ∧ 6 ⇒ ⊂ RemW (v(m div ws), m mod ws) v CAS(w, lw, nw, ); Specification Note that the first parameter is a var parameter, i.e. call-by-reference RemW (var w : F(0..ws 1), i : 0..ws 1) − − î ó (guar w 0 w w w 0 i ) (rely w 0 w) w : i w 0 ⊆ ∧ − ⊆ { } e ⊆ e 6∈ 39 / 1 40 / 1 Introduce loop Refine loop body

î ó (guar w 0 w w w 0 i ) (rely w 0 w) w : w w 0 i w 0 ⊆ ∧ − ⊆ { } e ⊆ e ⊃ ∨ 6∈ strengthen guarantee, introduce local variable lw w 0..ws 1 i 0..ws 1 v { ⊆ − ∧ ∈ − } î ó var lw ( 0 0 ) ( 0 ) : 0 · 0 0 0 guar w w w w i e rely w w e w i w (guar w = w w = w i ) e (rely w w ) e ⊆ ∧ − ⊆ { } 0 ⊆ 6∈ î ∨ ó −î { } ⊇ ó invariant true and variant w w (lw : w lw 0 w 0 ; w : lw w , lw w 0 i w 0 ) v ⊃ while i w do ⊇ ⊇ ⊇ ⊃ ∨ 6∈ ∈ 0 0 0 (guar w w w w i ) e (rely w w) e Refining the first specification î ⊆ ∧0 − ⊆0ó { } ⊆ w : w w i w î ó ⊃ ∨ 6∈ (guar w 0 = w w 0 = w i ) (rely w w 0) lw : w lw 0 w 0 ∨ − { } e ⊇ e ⊇ ⊇ v lw := w

41 / 1 42 / 1

Refining the second specification Introducing a Compare-and-Swap (CAS)

CAS(var w, lw, nw, var done) =“ 0 0 0 (rely lw = lw nw = nw done = done) e Æ (w∧ = lw w 0∧= nw done0) ∏ w, done : ⇒ ∧ ∧ î ó (w = lw w 0 = w done0) (guar w 0 = w w 0 = w i ) (rely w w 0) w : lw w , lw w 0 i w 0 6 ⇒ ∧ ¬ ∨ − { } e ⊇ e ⊇ ⊃ ∨ 6∈ introduce variable nw to contain the updated value v The variables lw and nw are local so the rely is satisfied; done isn’t used var nw := lw i ; 0 − { }0 0 0 0 0 (guar w = w w = w i ) e (rely w w ) e (guar w = w w = w i ) e (rely w w ) e î ∨ − { } ⊇ ó î ∨ − { } ⊇ ó w : lw w nw = lw i , lw w 0 i w 0 w : lw w nw = lw i , lw w 0 i w 0 ⊇ ∧ − { } ⊃ ∨ 6∈ ⊇ ∧ − { } ⊃ ∨ 6∈ v 0 0 0 (guar w = w w = w i ) e (rely w w ) e î ∨ − { } ⊇ ó w : lw w nw = lw i , (lw = w w 0 = nw) (lw = w w 0 = w) ⊇ ∧ − { } ⇒ ∧ 6 ⇒ v CAS(w, lw, nw, )

43 / 1 44 / 1 Removing an element from a (small) set atomically Termination

Specification Code

RemW (var w : F(0..ws 1), i : 0..ws 1) 0 0 − − î ó while i w do invariant true wf-relation (w w) OR (#w < #w) (guar w 0 w w w 0 i ) (rely w 0 w) w : i w 0 ∈ ⊂ ⊆ ∧ − ⊆ { } e ⊆ e 6∈ var lw := w; var nw := lw i ; – stable because variables local Code − { } ± ª lw w nw = lw i , ⊆ ∧ 0 − { } while i w do invariant true CAS(w, lw, nw, ); – refines w : (w = lw w w i ) ∈ ⇒ 0 ⊆ − { } ∧ var lw := w; (w = lw w lw) 6 ⇒ ⊂ var nw := lw i ; – stable because variables local i w − { } ± ª { 6∈ } w lw nw = lw i , Termination CAS(w, lw, nw, ); – refines w : (w⊆= lw∧ w 0 w− { i} ) ⇒ ⊆ − { } ∧ (w = lw w 0 lw) I If the CAS succeeds, i w and the loop terminates 6 ⇒ ⊂ 0 6∈ i w I If the CAS fails, w w and the hence the loop variant decreases { 6∈ } ⊂

45 / 1 46 / 1

Conclusions

I Rely/guarantee provides a simple but effective abstraction of concurrency I Importance of data abstraction ? I New algebraic style makes proving new laws simpler

I Interesting links/similarities to process algebras (SCCS)

I New style allows new forms of specifications

47 / 1 48 / 1 The With and Await statements Invariant under interference

The with x do c statement ensures that the updates of x are atomic. There is no interference on x during the update. For a rely relation r and predicate p, r maintains p if

0 with x do c = idle ; ((demand x0 = x) c); idle r (p p ) “ e V ⇒ with x do c = id ω ; ((demand x0 = x) c); idle “ h i e Examples: for integer x, sets s, and sequence buf

0 0 This allows id steps forever, even when x isn’t in use elsewhere. x x V (0 x 0 x ) The await statement delays until its condition evaluates to true. It may fail by ≤ 0 ≤ ⇒ ≤ 0 x = x V (0 x 0 x ) evaluating to false any number of times. ≤ ⇒ ≤ s s0 (s 0..n s0 0..n) ⊇ V ⊆ ⇒ ⊆ ω 0 0 await b =“ [[ b]] ; [[b]] s = s V (s 0..n s 0..n) ¬ 0 ⊆ ⇒ ⊆ 0 buf suffix buf V (#buf < N #buf < N) where [[b]] succeeds if and only if b evaluates to true. Equivalent to ⇒ buf prefix buf 0 (#buf = 0 #buf 0 = 0) V 6 ⇒ 6 await b = while b do nil ¬

49 / 1 50 / 1

Doing nothing under interference Multi-place buffer of size N

module Buffer The command idle only makes a finite number of program steps that do not var buf : seq Value change the environment invariant #buf N ≤ If r maintains p, i.e. r (p p0), then initially buf = [ ] V ⇒ î ∗ 0ó (rely r) e p , r p idle write(v : Value) ∧ v 0 rely buf suffix buf e – single writer 0 0 For example, the rely condition (buf suffix buf ) maintains #buf < N, and hence guar buf prefix buf e î ó with buf await #buf < N do (rely r) #buf < N , buf 0 suffix buf #buf 0 < N idle î ó e ∧ v buf : buf 0 = buf a [v] Similarly, if r maintains p, and r maintains b, read()res : Value 0 î ∗ 0 0ó rely buf prefix buf e – single reader (rely r) e p , r p b await b 0 ∧ ∧ v guar buf suffix buf e with buf await #buf = 0 do î 6 ó res, buf : buf = [res] a buf 0

51 / 1 52 / 1 Initial refinement of write Initial refinement of read

read()res : Value write(v : Value) 0 0 rely buf prefix buf e – single reader rely buf suffix buf e – single writer 0 0 guar buf suffix buf e guar buf prefix buf e with buf await #buf = 0 do with buf await #buf < N do î 6 ó î ó res, buf : buf = [res] a buf 0 buf : buf 0 = buf a [v]

v 0 v 0 rely buf prefix buf e rely buf suffix buf e 0 0 guar buf suffix buf e guar buf prefix buf e await #buf = 0; – await buffer not empty – stable under rely await #buf < N; – await buffer not full – stable under rely î 6 ó : 0 = ( ) with buf do res res hd buf î 0 ó with buf do buf : #buf < N , buf = buf a [v] î ó buf : #buf = 0 , buf 0 = tl(buf ) 6

53 / 1 54 / 1

Multi-place buffer implementation Write in a circular buffer

The buffer b has N + 1 slots but one is always unused. We define the notation a b = (a + b) mod (N + 1). The slots start at r and w is the index of the next slot write(v : Value) 0 to⊕ be written, so that rely buf suffix buf e 0 guar buf prefix buf e I if r = w the buffer is empty and await #buf < N; – await buffer not full – stable under rely I if r = w 1 the buffer is full. î ó ⊕ with buf do buf : #buf < N , buf 0 = buf a [v] – atomic update of buf The retrieve function is defined by is data refined by retr(b, r, w) = if r = w then [] else [b[r]] a retr(b, r 1, w) ⊕ rely w 0 = w b0 = b (r = w r 0 = r) ∧ ∧ ⇒ e guar r 0 = r (r = w 1 w 0 = w) retr(b, r, w) prefix retr(b0, r 0, w 0) ∧ ⊕ ⇒ ∧ e module BufferI implements Buffer var nw := w 1; ⊕ var b :(0 .. N) Value; await r = nw; – await buffer not full – stable under rely → r, w : 0 .. N; b[w] :=h iv 6 ; initially r = 0 w = 0; – Ensure b[w] is flushed before updating w ∧ representation buf = retr(b, r, w) with w do w := nw – atomic update of w

55 / 1 56 / 1 Read in circular buffer Multi-place buffer implementation with size

The buffer b has N slots and keeps a separate variable s to track its current size. read()res : Value The slots start at r and w is the index of the next slot to be written, so that 0 rely buf prefix buf e I if s = 0 the buffer is empty and guar buf 0 suffix buf e I if s = N the buffer is full. await #buf = 0; – await buffer not empty – stable under rely î 6 ó We define two retrieve functions, one for read and one for write. I have no idea res : res0 = hd(buf ) î ó what the theory is but the write and write processes have different views of the with buf do buf : #buf = 0 , buf 0 = tl(buf ) – atomic update of buf 6 buffer. is data refined by retr r(b, r, s) = (λ i 0 .. s 1 b[(r + i) mod N]) retr w(b, w, s) = (λ∈i 0 .. s− 1· b[(w + i + n s) mod N]) rely r 0 = r (r = w 1 w 0 = w) retr(b, r, w) prefix retr(b0, r 0, w 0) ∈ − · − ∧ ⊕ ⇒ ∧ e guar w 0 = w b0 = b (r = w r 0 = r) ∧ ∧ ⇒ e module BufferI implements Buffer await r = w ; – await buffer non-empty – stable under rely var b :(0 .. N 1) Value; res := b6 [rh]; i r, w : 0 .. N − 1; → var nr := r 1; s : 0 .. N; − – Ensure⊕ b[r] has been fully read before updating r initially s = 0 r = 0 w = 0; with r do r := nr – atomic update of r ∧ ∧ representation buf = retr r(b, r, s) = retr w(b, w, s)

57 / 1 58 / 1

Write in a circular buffer with size Read in circular buffer with size

write(v : Value) read()res : Value 0 0 rely buf prefix buf rely buf suffix buf e e await #buf < N; – stable under rely await #buf = 0; – stable under rely î 0 6 ó î 0 ó res : res = hd(buf ) with buf do buf : #buf < N , buf = buf a [v] î ó with buf do buf : #buf = 0 , buf 0 = tl(buf ) 6 is data refined using representation buf = retr w(b, w, s) by is data refined using representation buf = retr r(b, r, s) by rely w 0 = w b0 = b 0 s0 s ∧ ∧ ≤ ≤ e rely r 0 = r s s0 N retr r(b, r, s) prefix retr r(b0, r 0, s0) guar r 0 = r s s0 N retr r(b, r, s) prefix retr r(b0, r 0, s0) ∧ ≤ ≤ ∧ e ∧ ≤ ≤ ∧ e guar w 0 = w b0 = b 0 s0 s await s < N; – await buffer not full – stable under rely ∧ ∧ ≤ ≤ e await s = 0; – await buffer non-empty – stable under rely b[w] :=h iv; res :=h bi[ 6r]; – Ensure b[w] is flushed before updating s – Ensure b[r] has been fully read before updating s or r (w := (w + 1) mod N with s do s := s + 1) – atomic update of s k (r := (r + 1) mod N with s do s := s 1) – atomic update of s k − Note that the representation relation is broken during the last parallel assignment Note that the representation relation is broken during the last parallel assignment but restored on completion of both assignments. Contention on update of s via a but restored on completion of both assignments. Contention on update of s via a compare-and-swap bounded by reader decreasing size to 0. compare-and-swap bounded by reader increasing size to N. 59 / 1 60 / 1 Find least first element of an array that satisfies P Specification

The objective is, given an array v with indices in the range 0 .. N 1, to find the least index t for which a predicate P(v(t)) holds,1 or if P does not− hold for any element of v, to set t to N. î ó findp = t : (t0 = N satp(v, t0)) notp(v, 0 .. N 1, t0) î ó “ ∨ ∧ − C findp = (rely v 0 = v t0 = t) t : (t0 = N satp(v, t0)) notp(v, 0 .. N 1, t0) “ ∧ e ∨ ∧ − where

satp(v, t) = t 0 .. N 1 P(v(t)) “ ∈ − ∧ notp(v, s, t) = ( i s i < t P(v(i))) “ ∀ ∈ · ⇒ ¬

1For brevity, it is assumed here that P(x) is always defined (undefinedness is considered by [?] but it has little bearing on the actual design). 61 / 1 62 / 1

Representing the result using two variables Using a guarantee invariant

A guarantee invariant is a guarantee that states a predicate p is invariant.

(guar-inv p) = (guar p p0) “ ⇒ Two variables ot and et are introduced with the intention that on termination the minimum of ot and et will be the least index satisfying p. A guarantee invariant of î ó ( , ) = ( , ( , )) (rely v 0 = v t0 = t) t : (t0 = N satp(v, t0)) notp(v, 0 .. N 1, t0) min ot et N satp v min ot et (1) ∧ e ∨ ∧ − ∨ by Law variable-rely-guarantee for ot and et v can be employed; the invariant is established by setting both ot and et to N. var ot, et · 0 0 0 0 (rely v = v t = t ot = ot et = et) e (rely v 0 = v ot0 = ot et0 = et) ñ ∧ ∧ ∧ ô e (min(ot0, et0) = N satp(v, min(ot0, et0))) ñ(min∧(ot0, et0) =∧N satp(v, min(ot0, et0))) ô ot, et, t : ∨ 0 0 ∧ ; C ot, et : ; notp(v, 0 .. N 1, min(ot , et )) notp(v, 0 .. N 1,∨min(ot0, et0)) ∧ C − t := min(ot0, et0) by Law trade-rely-guarantee-invariant;− Law rely-sequential v ot := N ; et := N; ((guar-inv min(ot, et) = N satp(v, min(ot, et)))) e 0 0 ∨0 (rely v = v ot = ot et = et) e î ∧ ∧ ó ot, et : notp(v, 0 .. N 1, min(ot0, et0)) − C

63 / 1 64 / 1 Concurrency Refining the branches to code

The motivation for the parallel algorithm comes from the observation that the set of indices to be searched, 0 .. N 1, can be partitioned into the odd and even indices, − namely evens(N) and odds(N), respectively, which can be searched in parallel. For the first branch of the parallel, the guarantee et0 = et is equivalent to removing et from the frame of the branch. notp(v, odds(N), min(ot0, et0)) notp(v, evens(N), min(ot0, et0)) ∧ V notp(v, 0 .. N 1, min(ot0, et0)) 0 0 0 0 0 − (guar ot ot et = et) e (rely et et ot = ot v = v) e î ≤ ∧ 0 0 ≤ó ∧ ∧ The next step is the epitome of rely-guarantee refinement: splitting the ot, et : notp(v, odds(N), min(ot , et )) specification command. = 0 0 0 0 (guar ot ot) e (rely et et ot = ot v = v) e 0 0 0 î ≤ ≤ ∧ ó ∧ (rely v = v ot = ot et = et) e : ( , ( ), ( 0, 0)) î ∧ ∧ ó ot notp v odds N min ot et ot, et : notp(v, 0 .. N 1, min(ot0, et0)) − by Law introduce-parallel-spec-weaken-rely The body of this can be refined to sequential code, however, because the v 0 0 0 0 0 0 (guar ot ot et = et) e (rely et et ot = ot v = v) e specification refers to et it is subject to interference from the parallel (evens) î ≤ ∧ 0 0 ≤ó ∧ ∧ ot, et : notp(v, odds(N), min(ot , et )) C process which may update et. That interference is however bounded by the rely condition which assumes the parallel process never increases et. k 0 0 0 0 0 (guar et et ot = ot) e (rely ot ot et = et v = v) e î ≤ ∧ ≤ ó ∧ ∧ ot, et : notp(v, evens(N), min(ot0, et0))

65 / 1 66 / 1

(guar ot0 ot) (rely et0 et ot0 = ot v 0 = v) e e The guarantee invariant combined with the postcondition oc0 min(ot0, et0) î ≤ ≤ 0 ∧0 ó ∧ ot : notp(v, odds(N), min(ot , et )) C implies the postcondition of the above specification. The postcondition≥ by Law variable-rely-guarantee for oc 0 0 0 v oc min(ot , et ) uses “ ” rather than “=” because the parallel process may var oc decrease≥ et. ≥ · 0 0 0 0 (rely et et oc = oc ot = ot v = v) e î ≤ ∧ ∧ 0 ∧0 ó 0 0 0 0 oc, ot : notp(v, odds(N), min(ot , et )) C (rely et et oc = oc ot = ot v = v) e ≤ î ∧ ∧ ∧ ó oc, ot : notp(v, odds(N), min(ot0, et0)) At this point a guarantee invariant Laws rely-sequential, trade-rely-guarantee-invariant, assignment-rely-guarantee v oc := 1; notp(v, odds(N), oc) bnd(oc, N) (2) ∧ (guar-inv notp(v, odds(N), oc) bnd(oc, N)) e 0 0 ∧ 0 0 (rely et et oc = oc ot = ot v = v) e is introduced where the bounding conditions on oc follow. î ≤ ∧ ∧ó ∧ oc, ot : oc0 min(ot0, et0) ≥ C bnd(oc, N) = 1 oc N + 1 “ ≤ ≤ This guarantee invariant is established by setting oc to one.

67 / 1 68 / 1 Law for introducing a while loop

Given A while loop is introduced using Law rely-loop. Only the first conjunct of the loop I a loop invariant p that is a state predicate guard oc < ot oc < et is preserved by the rely condition because et may be decreased. Hence∧ the boolean expression b for this application of the law is I a rely condition r that is a reflexive, transitive relation on states 0 oc < ot. However, the loop termination condition oc ot oc et is preserved I a variant function v of type T and a binary relation on T ≥ ∨ ≥ by the rely condition as decreasing et will not falsify it. Hence b is a boolean expression b and predicates b and b 1 I 0 1 oc ot oc et, which ensures oc min(ot, et) as required. For loop if termination≥ ∨ a≥ well-founded relation reducing≥ the variant ot oc is used. 0 I p is r-stable, i.e. r V (p p ) − ⇒ 0 0 0 0 I is well-founded on p, i.e. p C ( ) is well-founded (rely et et oc = oc ot = ot v = v) e 0 ≤ î ∧0 ∧0 0 ó ∧ I v is non-increasing under r on p, i.e. p r v v oc, ot : oc min(ot , et ) ∧ V  ≥ b is single reference, i.e. it has only a single reference to a non-stable variable by Law rely-loop I v 0 while < < do I p b b and p r (b b ) oc ot oc et V 0 V 0 0 0 ∧ 0 0 0 ∧ ∧ ⇒ 0 (rely et et oc = oc ot = ot v = v) e I p b V b1 and p r V (b1 b1) ≤ î ∧ ∧ ∧ ó ∧ ¬ ∧ ⇒ oc, ot : oc < ot , 1 ot0 oc0 < ot oc then − ≤ − − C î 0 0 0 ó (rely r) e p , p b1 v v ∧ î∧  ó while b do((rely r) p b , p0 v 0 v v e ∧ 0 ∧ ≺

69 / 1 70 / 1

At this stage we bring back in the guarantee invariants introduced above. The refinement is now uses Law rely-conditional.

(guar-inv min(ot, et) = N satp(v, min(ot, et))) ∨ e The specification of the loop body only involves variables which are stable under (guar-inv notp(v, odds(N), oc) bnd(oc, N)) e 0 0 0 ∧ (rely oc = oc ot = ot v = v) e interference. î ∧ ∧ ó oc, ot : oc < ot , 1 ot0 oc0 < ot oc 0 0 0 0 − ≤ − − (rely et et oc = oc ot = ot v = v) e ≤ î ∧ ∧ ∧ ó v oc, ot : oc < ot , 1 ot0 oc0 < ot oc if P(v(oc))then − ≤ − − by Law weaken-rely (guar-inv min(ot, et) = N satp(v, min(ot, et))) e v 0 0 0 ∨ (rely oc = oc ot = ot v = v) e (guar-inv notp(v, odds(N), oc) bnd(oc, N)) e î ∧ ∧ ó 0 0 0 ∧ oc, ot : oc < ot , 1 ot0 oc0 < ot oc (rely oc = oc ot = ot v = v) e C î ∧ ∧ ó − ≤ − − oc, ot : P(v(oc)) oc < ot , 1 ot0 oc0 < ot oc ∧ − ≤ − − else (guar-inv min(ot, et) = N satp(v, min(ot, et))) ∨ e (guar-inv notp(v, odds(N), oc) bnd(oc, N)) e 0 0 0 ∧ (rely oc = oc ot = ot v = v) e î ∧ ∧ ó oc, ot : P(v(oc)) oc < ot , 1 ot0 oc0 < ot oc ¬ ∧ − ≤ − −

71 / 1 72 / 1 Collected code

The development of the “evens” branch of the parallel composition follows the same pattern as that of the “odds” branch given above but starts at zero. The Finally, Law assignment-rely-guarantee can be applied to each of the branches. collected code follows. Each assignment ensures the guarantee invariant (min(ot, et) = N satp(v, min(ot, et)) notp(v, odds(N), oc) bnd(oc, N) is ∨ ∧ ∧ var ot, et maintained. ot := N; · et := N; if P(v(oc)) then ot := oc else oc := oc + 2 â ì v var oc var ec · · oc := 1; ec := 0;

while oc < ot oc < et do while ec < ot ec < et do ; ∧ ∧ if P(v(oc)) then ot := oc if P(v(ec)) then et := ec

else oc := oc + 2 else ec := ec + 2 t := min(ot, et)

73 / 1 74 / 1

Treiber stack Treiber stack representation

Abstract state is a sequence of values

var A : seq Val Representation as a linked list Specification uses atomic step style type Node = data : Val; next : Node { ∗ } Push(v : Val) var : D E s Node id ω ; A : A0 = [v] a A ; id ∗ ∗ h i h i Abstraction relation t D E 0 ∗ 0 a ∗ rely A = A e ( id ; A : A = [v] A ; id ) stack(s : Node, A : seq Val) = h i h i ∗ (s = null A = [ ]) ( v, n s ∧ Node(v∨, n) head(A) = v stack(n, tail(A))) Pop()r :[Val] ∃ · 7→ ∧ ∧ D E id ω ; A, r : A = [r 0] a A0 (A = [ ] = A0 r 0 = null) ; id ∗ h i ∨ ∧ h i t D E rely A0 = A ( id ∗ ; A, r : A = [r 0] a A0 (A = [ ] = A0 r 0 = null) ; id ∗) e h i ∨ ∧ h i

75 / 1 76 / 1 Repeat Implementation

Repeat statement semantics Push(v : Val) repeat c until b =( id ∗ ; c ; [[ b]])ω ; id ∗ ; c ; [[b]] var x : Node; h i ¬ h i x := new∗ Node(); Push specification (possibly nonterminating) x data := v; → D E stack(s, A) x Node(v, ) ; ω 0 a ∗ { ∗ 7→ } id ; A : A = [v] A ; id var done : B; h i D h i E = ( id ∗)ω ; id ∗ ; A : A0 = [v] a A ; id ∗ repeat h i h i h i var t : Node; ∗ To implement this specification as a repeat statement, we want t := s ; hx nexti := t; ∗ ∗ id id ; c ; [[ b]] stack→ (s, A) (x Node(v, t)) D E h i vh i ¬ { ∗ 7→ } id ∗ ; A : A0 = [v] a A ; id ∗ id ∗ ; c ; [[b]] CAS(s, t, x, done) h i h i vh i until done but needs change of representation as well

77 / 1 78 / 1

Matching the refinement conditions Overview

x, done : true ∗ h i v id ∗ ; var t : Node; t := s ; x.next := t; CAS(s, t, x, done) ; [[ done]] Theory for rely/guarantee concurrency motivated by h i ∗ h i ¬ I Abstract algebra ± stack(s, A) ª I Program algebras ∧ x, done : true ∗ ; x, s, done : A, A0 A0 = [v] a A ; id ∗ I Aczel traces and their synchronous parallel operator h i ∃ · h i stack(s0, A0) ∧ v id ∗ ; var t : Node; t := s ; x.next := t; CAS(s, t, x, done) ; [[done]] h i ∗ h i

79 / 1 80 / 1 Your algebra background Monoids

From mathematics we have abstract algebras What algebras do you know? I Monoid (S, , e) over a set S with binary operator : S S S ⊕ ⊕ × → I Groups I Associative: x0 (x1 x2) = (x0 x1) x2 ⊕ ⊕ ⊕ ⊕ I Identity: x e = x = e x I Semi-groups ⊕ ⊕ I Examples of monoids I Monoids I (N, +, 0) I Lattices – ordered plus infimum (meet) and supremum (join) I (N, , 1) ∗ I Kleene Algebra – algebra of regular expressions I (Programs,;, nil) I (Programs, , skip) I Kleene Algebra with Tests (KAT) k I (Programs, e, chaos) I Concurrent Kleene Algebra (CKA) I All except (Programs,;, nil) are commutative monoids

I Commutative: x0 x1 = x1 x0 ⊕ ⊕

81 / 1 82 / 1

Kleene algebra - the algebra of regular expressions Structure of concurrent program algebra

I Concurrent refinement algebra ( , , ; , , )

u t k e ⊤ ⊑ I Plus tests – a subset of ⊑ Regular expressions Relations Programs commands that forms a boolean

...

... Alternatives e0 e1 r0 r1 c0 c1 algebra

algebra ⊑ | ∪o u ⊑ algebra Sequence e e r 9 r c ; c 0 1 0 1 0 1 I like Kozen’s Kleene Algebra of tests of atomic steps Kleene star e∗ r ∗ c∗ with Tests (KAT) nil α

Identity of sequence  id nil I Plus atomic steps – a subset of ⊑ Identity of alternation commands that forms a boolean ∅ ∅ > chaos algebra Basic elements a (x, y) Π(σ0, σ1) algebra

⊑ of commands (σ0, σ1) E I Program/environment steps – partitions atomic steps where a is a symbol; x and y are elements of the base type of the relation; and σ0 ⊥ and σ1 are program states. I Relational instantiation

83 / 1 84 / 1 Operators Complete lattice

c d non-deterministic choice (lattice infimum or meet) u (c c ) c = c (c c ) – associative 0 u 1 u 2 0 u 1 u 2 c c = c c – commutative 0 u 1 1 u 0 c c = c – idempotent u c = c = c – identity u > > u > For any set of commands C c d lattice supremum or join t I dC is the infimum (greatest lower bound) of the set of commands I associative, commutative, idempotent, identity ⊥ I F C is the supremum (least upper bound) of the set of commands c d parallel composition k I associative, commutative, identity skip c e d weak conjunction I associative, commutative, idempotent, identity chaos c ; d sequential composition (sometimes elided to c d below) I associative, identity nil and have the same precedence, which is lower than and e, which are lower thanu ; t k 85 / 1 86 / 1

Aczel traces Primitive atomic commands

For a binary relation r Σ Σ on states Represent ⊆ × π(r) can perform any single atomic program step Π(σ, σ0) for (σ, σ0) r I a program doing a step from σ0 to σ1 by Π(σ0, σ1) and ∈ (r) can perform any single atomic environment step (σ, σ0) for (σ, σ0) r I its environment doing a step from σ0 to σ1 by (σ0, σ1). E ∈ E For example, Every step of parallel synchronises steps of the two processes I π(id) is a single stuttering program step (id is the identity relation) (σ , σ ), Π(σ , σ ), (σ , σ ), (σ , σ ), (σ , σ5) E 0 1 1 2 E 2 3 E 3 4 E 4 k I π = π(univ) can perform any single program step (univ is the universal (σ , σ ), (σ , σ ), Π(σ , σ ), (σ , σ ), Π(σ , σ5) = relation) E 0 1 E 1 2 2 3 E 3 4 4 (σ , σ ), Π(σ , σ ), Π(σ , σ ), (σ , σ ), Π(σ , σ5) I  = (univ) can perform any single environment step E 0 1 1 2 2 3 E 3 4 4 I π( ) = ( ) = is infeasible (magic) Every step of a weak conjunction synchronises steps of the two processes ∅ ∅ > Atomic steps form a boolean algebra (σ , σ ), Π(σ , σ ), (σ , σ ), (σ , σ ), Π(σ , σ5) E 0 1 1 2 E 2 3 E 3 4 4 e π(r0) π(r1) = π(r0 r1) (σ0, σ1), Π(σ1, σ2), (σ2, σ3), (σ3, σ4), Π(σ4, σ5) = u ∪ E E E π(r0) π(r1) = π(r0 r1) (σ0, σ1), Π(σ1, σ2), (σ2, σ3), (σ3, σ4), Π(σ4, σ5) t ∩ E E E ! π(r) = π(r)  u

87 / 1 88 / 1 Tests as a boolean algebra Assumptions

For a set of states p Σ, ⊆ τ (p) terminates immediately if p holds but is infeasible otherwise For example, For a an atomic step command

I τ (Σ) = nil I assume a = a (! a); u ⊥ I τ ( ) = I !(π(r ) (r )) = π(r ) (r ) ∅ > 0 u 1 0 u 1 I τ (p1) τ (p2) = τ (p1 p2) I !(π (r)) = π( ) (r) = (r) = (r) u ∪ u ∅ u > u I τ (p1) τ (p2) = τ (p1); τ (p2) = τ (p1) τ (p2) = τ (p1 p2) I assume π (r) = π (r) (r); t k ∩ u u u ⊥ I τ (p) = τ (p) Note that program and environment steps partition atomic steps ¬ Assertions/preconditions: for a test t

I pre t = t t ; u ¬ ⊥ I p = pre τ (p) = τ (p) τ (p); { } u ⊥

89 / 1 90 / 1

Synchonise atomic steps For program and environment steps

For atomic commands a and b (think π and  commands) and arbitrary commands c and d

(a ; c) e (b ; d) = (a e b);(c e d) π(r1) π(r2) = π(r1) π(r2) = π(r1 r2) k > e ∩ (a ; c) e nil = π(r1) (r2) = π(r1 r2) π(r1) (r2) = > k ∩ e > a e = (r1) (r2) = (r1 r2) (r1) (r2) = (r1 r2) ⊥ ⊥ k ∩ e ∩ π(r) = π(r) = Laws k ⊥ ⊥ e ⊥ ⊥ (r) = (r) = ∗ ∗ ∗ e a e b = (a e b) k ⊥ ⊥ ⊥ ⊥ a∗ ; c b∗ ; d = (a b)∗((c d) (a ; a∗ ; c d) (c b ; b∗ ; d)) e e e u e u e

91 / 1 92 / 1 Interchange laws Iteration

Iteration zero or more times, cω, allows finite iteration, c∗, or infinite iteration, c∞

cω = c∗ c∞ (3) Weak conjunction interchange sequential u Examples (c0 ; c1) e (d0 ; d1) (c0 e d0);(c1 e d1) v π∗ performs a finite number of program steps Weak conjunction interchange parallel (π )∗ performs a finite number of steps u ∞ performs an infinite sequence of environment steps (c0 c1) e (d0 d1) (c0 e d0) (c1 e d1) k k v k skip is the identity of parallel and chaos is the identity of weak conjunction

skip = ω chaos = (π )ω u

93 / 1 94 / 1

Asynchronised atomic step Rely/guarantee

r

rr rr r = ω ; π(r); ω h i πππ pre For example

r r = ω ;(π(r ) π(r )) ; ω r ; r r ; r g g g h 1i k h 2i 1 k 2 u h 1i h 2i u h 2i h 1i = r ; r r ; r h 1i h 2i u h 2i h 1i post

95 / 1 96 / 1 Guarantee and rely Termination

The command term allows only a finite number of program steps but does not rule For relations g and r out infinite pre-emption by its environment. ω ∗ ω guar g = (π(g) )ω term = ( ; π) ;  (4) u rely r = (π (r) (¯r) )ω u u ⊥ The refinement = (assume ! (r))ω term c recalling assume a = a ! a ; and ! (r) = π (r) v u ⊥ u For example, c e guar g e rely r imposes a guarantee of g on c and assumes the states that c terminates if the environment does not interrupt it forever, e.g. environment steps satisfy r. term x := 1 v

97 / 1 98 / 1

Specification commands Parallel introduction

I Frames on commands î ó î ó ((rely r r1) e q1 e (guar r r2)) x : c = (guar id(x)) e c (rely r) e q1 q2 ∪ î ó ∪ k ∧ v ((rely r r2) e q2 e (guar r r1)) I Atomic operation ∪ ∪ q = ω ; π(q); ω Proof h i î ó I Non-atomic specification (relational post) (rely r) e q1 q2 î ó 0 0 ∧ î ó î ó î ó q = dσ∈Στ ( σ ); term ; τ ( σ Σ (σ, σ ) q ) as c e c = c and q1 q2 = q1 e q2 and weaken relies { } { ∈ | ∈ } v î ó ∧ î ó Lemmas for specifications (rely r r1) q1 (rely r r2) q2 ∪ e e ∪ e î ó by Lemma Y (twice) univ = term v î ó ((rely r r1) e q1 ) ((guar r r1) e term) e î ó î ó î ó ∪ k ∪ î ó q1 q2 = q1 q2 ((guar r r2) e term) ((rely r r2) e q2 ) e ∧ ∪ k ∪ î ó î ó conjunction-interchange-parallel (c1 c2) e (d1 d1) (c1 e d1) (c2 e d2) q e term = q v î ó k k v k î ó î ó ((rely r r1) e q1 e (guar r r2) e term) q term = q ∪ ∪ î ó k k ((guar r r1) e term e (rely r r2) e q2 ) î ó î ó ∪ ∪ q2 q1 q1 q2 by Lemma Q1 ⊆ ⇒ v v î ó î ó ((rely r r ) q (guar r r )) ((guar r r ) (rely r r ) q ) ∪ 1 e 1 e ∪ 2 k ∪ 1 e ∪ 2 e 2 99 / 1 100 / 1 Lemma Y Lemmas X and Q

Lemma X î ó î ó (rely r) q ((rely r) q ) ((guar r) term) e v e k e (rely r) (rely r) (guar r) v k Proof Lemma Q1 î ó î ó î ó (rely r) e q q e term = q by Lemmas X and Q2 v î ó Lemma Q2 ((rely r) (guar r)) e ( q term) k k î ó î ó conjunction-interchange-parallel (c1 c2) e (d1 d1) (c1 e d1) (c2 e d2) q term = q v î ó k k v k ((rely r) q ) ((guar r) term) k e k e

101 / 1 102 / 1

Applying to process algebras CSP

Synchronising on common events

I π(A) π(B) = π(A B) The above approach can also be applied to CSP-style processes. k ∩ I Π(a) is interpreted as an atomic event or action a Alphabet A for a command c - environment can do only events in A independently ω I (a) is a corresponding environment event I A : c = c (A) E t I π(A) allows any event Π(a) for any a A Hoare’s parallel for a process c with alphabet A and process d with alphabet B ∈ I A : c B : d I (A) allows any environment event (a) for any a A k E ∈ Roscoe’s parallel alphabetised by A

I c d = A : c A : d kA k

103 / 1 104 / 1 Iteration Some basic commands

Finite iteration zero or more times, c∗, possibly infinite iteration zero or more times, cω, and infinite iteration, c∞, are defined via their usual recursive equations and have the following unfolding and induction properties.

c∗ = νx nil c ; x “ · u c∗ = nil c ; c∗ update(x, v) = π(x0 = v id(x)) (6) u ∗ “ x d c ; x x c ; d ω ∧ v u ⇒ v skip =“  (7) c∗ = nil c∗ ; c u chaos = (π )ω (8) x d x ; c x d ; c∗ “ u v u ⇒ v ∗ term =“ (π ) ; skip (9) ω u c = µ x nil c ; x (5) idle = (π(id) )∗ ; skip (10) “ · u “ cω = nil c ; cω u r = skip ; π(r); skip (11) d c ; x x cω ;ud x h i “ u v ⇒ v ∞ c =“ µ x c ; x c∞ = c ; c·∞ c ; x x c∞ x v ⇒ v

105 / 1 106 / 1

Relies and guarantees Tests and steps

ω guar g =“ (π(g) ) (12) u τ (p1); τ (p2) = τ (p1 p2) (15) rely r = (π (r))ω ;(nil (r); ) (13) ∧ “ u u ⊥ τ (p); π(r) = π(p r) (16) x : c = (guar id(x)) e c (14) ∧ “ τ (p); (r) = (p r) (17) ∧ The process (guar g) c behaves as both (guar g) and as c, unless at some point π(r p0); τ (p) = π(r p0) (18) e ∧ ∧ c aborts, in which case (guar g) e c aborts; note that (guar g) cannot abort. For (r p0); τ (p) = (r p0) (19) example, the guarantee (guar w 0 w w w 0 i ) ensures that no step of the ∧ ∧ process may add elements to w or⊇ remove∧ − elements⊆ { } other than i.

107 / 1 108 / 1 Invariance Invariance over steps

If r (p p0), then both the following hold. V ⇒ If c ; τ (p) τ (p); c, then v π(r); τ (p) τ (p); π(r) (20) v τ (p); c ; τ (p) = τ (p); c . (r); τ (p) τ (p); (r) (21) v Proof. Proof. The assumption ensures p r p0 = p r. We give the proof for (??) which uses ∧ ∧ ∧ τ (p); c ; τ (p) τ (p); τ (p); c = τ (p); c = (??). The proof for (??) is similar but uses (??). v τ (p); c ; nil τ (p); c ; τ (p) . v π(r); τ (p) = nil ; π(r); τ (p) τ (p); π(r); τ (p) = π(p r); τ (p) v ∧ = π(p r p0); τ (p) = π(p r p0) = π(p r) = τ (p); π(r) ∧ ∧ ∧ ∧ ∧

109 / 1 110 / 1

Invariance over iterations Rely-invariant

0 If r V (p p ), then If c ; τ (p) τ (p); c, then both ⇒ v ((rely r) e idle); τ (p) τ (p) ; ((rely r) e idle) cω ; τ (p) τ (p); cω (22) v v c∗ ; τ (p) τ (p); c∗ (23) Proof. v The proof uses the definitions of rely r (??) and idle (??) and then pushes the test Proof. τ (p) left using applications of Lemma invariance-iteration. Note that the identity Property (??) holds by ω-induction (??) if τ (p) c ; τ (p); cω τ (p); cω, which relation id maintains any invariant p. can be proven using the assumption and ω-foldingu (??). v ((rely r) e idle); τ (p) ω ∗ ω ω ω ω ω = ((π (r)) ;(nil (¯r); ) (π(id) ) ;  ); τ (p) τ (p) c ; τ (p); c τ (p) τ (p); c ; c = τ (p);(nil c ; c ) = τ (p); c u u ⊥ e u u v u u = (π(id) (r))∗ ; (r)ω ;(nil (¯r); ); τ (p) u ∗ ω u ⊥ Property (??) holds by ∗-induction (??) if c∗ ;τ (p) τ (p) c∗ ;τ (p);c, which can = (π(id) (r)) ; (r) ;(τ (p) (¯r); ; τ (p)) u u ⊥ be proven using the assumption and ∗-folding (??).v u (π(id) (r))∗ ; (r)ω ; τ (p);(nil (¯r); ) v u u ⊥ (π(id) (r))∗ ; τ (p); (r)ω ;(nil (¯r); ) ∗ ∗ ∗ ∗ v u u ⊥ τ (p) c ; τ (p); c τ (p) c ; c ; τ (p) = (nil c ; c); τ (p) = c ; τ (p) τ (p);(π(id) (r))∗ ; (r)ω ;(nil (¯r); ) u w u u v u u ⊥ = τ (p) ; ((rely r) e idle)

111 / 1 112 / 1 Defining expressions Stable-expression

An expression is stable under r if its evaluation is not affected by interference satisfying r. For example, assuming access to x is atomic, the absolute value of x, x , is stable under interference satisfying x0 = x x0 = x, and (x mod N) is [[κ]] = idle ; τ (κ = v); idle (24) v “ |stable| under interference satisfying x0 = x x0 =∨x + N.− [[x]]v =“ idle ; τ (x = v); idle (25) ∨ Definition (stable-expression) [[ e]]v = l v v = eval( , v ) [[e]]v (26) “ { 1 | 1 · 1 } An expression e is stable under r if, for fresh v, [[ ]] = , = ( , , ) [[ ]] [[ ]] e1 e2 v “ l v1 v2 v eval v1 v2 e1 v1 e2 v2 (27) ⊕ { | ⊕ · k } r (e = v e0 = v) . V ⇒

113 / 1 114 / 1

Stable expression Rely stable expression

In the context of interference represented by a rely condition r, an expression e is If an expression e is stable under r, then for any value v where v does not occur stable if all the variables used in e are stable under r. If a variable x is not subject free in e, to change, access to it does not need to be atomic. (rely r) e (idle ; τ (e = v)) (rely r) e (τ (e = v); idle) I A constant κ is trivially stable. v 0 I A variable x is stable under r if for fresh v, r (x = v x = v). V ⇒ Proof. I A unary expression e is stable under r if e is. This lemma follows directly from Definition stable-expression and Law I A binary expression e e is stable under r if both e and e are. rely-invariant. 1 ⊕ 2 1 2

115 / 1 116 / 1 Single-reference expressions Single-reference expressions

Definition (single-reference-expression) Evaluating an expression in the context of interference may lead to anomalies The definition is based on the syntactic form of e.

because evaluation of an expression such as x + x may retrieve different values of I A constant κ is single reference. x for each of its occurrences and hence it is possible for x + x to evaluate to an I A variable x is single reference provided access to x is atomic. odd value even though x is an integer variable. Such anomalies may be avoided in I A unary expression e is single reference under r if e is. the case that expressions are single reference [?, ?]. If x is subject to modification then x + x is not single-reference but 2 x is. An expression being stable under r I A binary expression e1 e2 is single reference under r if either e1 is single ∗ ⊕ is considered a special case of it being single reference so, for example, if x is not reference under r and e2 is stable under r, or vice versa. subject to interference then x + x is single-reference. If an expression e is single-reference then for any evaluation of e, its value is the same as the evaluation of e in the single state σ in which the single-reference variable (x) is accessed.

117 / 1 118 / 1

Defining commands Rely sequential

A specification with a post condition which is the composition of two relations q1 x := e = l [[e]]v ; update(x, v) ; idle (28) and q may be refined by by a sequential composition of one command satisfying “ v∈Val } 2 q and a second satisfying q . if b then c else d =“ (([[b]]true ; c) ([[ b]]true ; d)) ; idle (29) 1 2 ω u ¬ For rely condition r, predicates p0, p1 and p2, and relations q1 and q2. while b do c = ([[b]]true ; c) ; [[ b]]true (30) “ ¬ î ó 0 0 î o 0 ó î 0 ó î 0 ó q = l τ ( σ ); term ; τ ( σ (σ, σ ) q ) (31) (rely r) p , (q 9 q ) p ((rely r) p , q p ) ; ((rely r) p , q p ) “ σ∈Σ { } { | ∈ } e 0 1 2 ∧ 2 v e 0 1 ∧ 1 e 1 2 ∧ 2 î ó î ó p , q = p ; q (32) “ { }

119 / 1 120 / 1 Single-reference test Rely idle

An expression e is single reference under interference satisfying the rely condition 0 If rely condition r is such that r V (p p ), r if the value of the expression corresponds to its value in one of the states during ⇒ î ∗ 0ó its evaluation and hence one can derive the following law. (rely r) e p , r p (rely r) e idle . If e is a single-reference expression under r, ∧ v Proof. (rely r) e (idle ; τ (e = κ); idle) [[e]]κ . v All environment steps of the right side are assumed to satisfy r and all program steps satisfy the identity relation, and hence the right side guarantees to maintain Proof. ∗ The proof is by structural induction of the structure of the expression. p and satisfies r .

121 / 1 122 / 1

Rely test Rely assignment

For a single-reference boolean expression b, predicates p and b0, and relation r, if r maintains p, p b b , and p r (b b0 ), ∧ V 0 ∧ V 0 ⇒ 0 î ∗ 0 0 ó Let r be a rely condition, x be a variable that is stable under r, and e be a (rely r) e p , r p b0 [[b]]true . ∧ ∧ v single-reference expression such that x does not occur free in e and “ ” a reflexive, transitive binary relation, such that r (e e0), then ≈ Proof. V ≈ î ó The proof uses Law rely-sequential and Law rely-idle. (rely r) x : e x0 e0 x := e e ≈ ≈ v î ∗ 0 0 ó (rely r) e p , r p b0 For example, the relation may be equality (so that e is stable) and we have î ∗∧ 0∧ó î 0 ó ((rely r) e p , r p ) ; ((rely r) e p , id p b ); e = x0 = e0, or the relation may be may be “ ”, so the postcondition becomes v î ∧ ∗ 0 0 ó ∧ ∧ 0 0 ⊇ ((rely r) e p b0 , r p b0 ) e x e . ∧ ∧ ∧ ⊇ ⊇ idle ; τ (b); idle v [[b]]true v

123 / 1 124 / 1 Handling tests under interference

To handle the possible instability of b within a test, a weaker but stable predicate Proof. b can be used, i.e. b b and r (b b0 ). More generally, if condition b is The proof uses Law rely-sequential and Law rely-idle and the definition of 0 V 0 V 0 0 only ever evaluated in states satisfying a⇒ precondition p that is maintained by r, assignment (??). these conditions can be relaxed to the following. î ó (rely r) x : e x0 e0 0 e p b V b0 p r V (b0 b0) î ≈ ≈ 0 0 ó ∧ ∧ ⇒ (rely r) e x : v e v e x = v v ∃ · î≈ ≈ ∧0 0 ó When handling the negation of the condition, one needs an additional stable (rely r) e dv∈Val x : e v e x = v v î ≈ ≈0ó ∧ î 0 0 ó predicate b1 that is implied by the negation of b. (rely r) e dv∈Val e v e ; x : e e x = v v î ≈ 0ó≈ î ≈0ó î∧ 0ó î 0 0 ó î 0ó 0 (rely r) e dv∈Val e e ; v = e = e ; e e ; x : e = e x = v ; e e p b b1 p r (b1 b ) v ≈ ≈ ∧ ≈ ∧ ¬ V ∧ V ⇒ 1 (rely r) e dv∈Val idle ; τ (v = e); idle ; update(x, v); idle v For example, the negation of the earlier example is oc ot oc et and that is (rely r) e dv∈Val [[e]]v ; update(x, v); idle ≥ ∨ ≥ v x := e maintained by interference that may only decrease et. Note that v p (p b) (p b) b b V ∧ ∨ ∧ ¬ V 0 ∨ 1 but there may be states in which both b0 and b1 hold. For the above example, taking b0 as oc < ot and b1 as oc ot oc et, both conditions hold in states satisfying oc < ot oc et. ≥ ∨ ≥ 125 / 1 ∧ ≥ 126 / 1

Loops The invariant and the variant

The law for while loops needs to be strengthened to rule out the interference The Hoare logic rule for reasoning about a loop, while b do c, for sequential invalidating the loop invariant p or increasing the variant v.The requirements on programs utilises an invariant p that is maintained by the loop body whenever b the invariant p and variant v to tolerate interference satisfying the rely condition r holds initially. To show termination a variant expression v is used. The loop body may be stated as follows. must strictly decrease v according to a well-founded relation ( ) whenever b r (p p0) (33) holds initially. V ⇒ p r v v 0 (34) ∧ V 

127 / 1 128 / 1 Rely finite iteration Rely well-founded iteration

For predicate p, variant expression v of type T , and a relation ( ) T T that is well-founded on p, if r maintains p, and v is non-increasing under r,∈ × î ó î ó For predicate p, and relation q, if r maintains p, (rely r) p , p0 v v 0 ((rely r) p , p0 v v 0 )ω e ∧  v e ∧ î 0 ∗ó î 0 ó ∗ (rely r) e p , p q ((rely r) e p , p q ) ∧ v ∧ Proof.

Proof. î 0 0ó ω ((rely r) e p , p v v ) The proof is via finite iteration induction (??) and the refinement holds if, ∧ = isolation, i.e. cω = c∗ c∞ î 0 u0ó ∗ î 0 0ó ∞ î 0 ∗ó î 0 ó î 0 ∗ó ((rely r) p , p v v ) ((rely r) p , p v v ) (rely r) e p , p q nil ((rely r) e p , p q ) ; ((rely r) e p , p q ) e ∧ u e ∧ ∧ v u ∧ ∧ = well-founded infinite iteration is infeasible

o ∗ ∗ î 0 0ó ∗ which holds by Law rely-sequential because q 9 q q . ((rely r) p , p v v ) V e ∧ by Law rely-finite-iteration w î ó (rely r) p , p0 v v 0 e ∧ 

129 / 1 130 / 1

Rely loop Proof. î ó (rely r) p , p0 b0 v v 0 e ∧ 1 ∧  by Law rely-sequential Given predicates p, b and b , a relation r, a variant expression v of type T and a v î 0 0ó î 0 0 0ó 0 1 ((rely r) e p , p v v ) ; ((rely r) e p , p b1 v v ) relation ( ) T T that is well-founded on states satisfying p, if b is a ∧  ∧ ∧  ⊆ × by Law rely-test using the assumptions on b1 single-reference boolean expression under interference satisfying r, and v î 0 0ó ((rely r) p , p v v ) ; [[ b]]true e ∧  ¬ 0 0 by Law rely-well-founded-iteration p r V p p b V b0 p r b0 V b0 v î 0 0ó ω ∧ 0 ∧ ∧ ∧ 0 ((rely r) p , p v v ) ; [[ b]]true p r v v p b b1 p r b1 b e V V V 1 ∧ ¬ 0 o 0 0 ∧  ∧ ¬ ∧ ∧ by Law rely-sequential as (v v ) 9 (v v ) V v v v î 0 0 0ó î 0 0ó ω then (((rely r) p , p b v v ) ; ((rely r) p b , p v v )) ; [[ b]]true e ∧ 0 ∧  e ∧ 0 ∧ ¬ î ó î ó by Law rely-test using the assumptions on b0 (rely r) p , p0 b0 v v 0 while b do((rely r) p b , p0 v v 0 ) v î 0 0ó ω e 1 e 0 ([[b]] ; ((rely r) p b , p v v )) ; [[ b]]true ∧ ∧  v ∧ ∧ e ∧ 0 ∧ ¬ = definition of loop (??) î ó while b do((rely r) p b , p0 v v 0 ) e ∧ 0 ∧

131 / 1 132 / 1 Rely loop early Some things I haven’t covered

Given predicates p, b0, b1 and b2, a relation r, a variant expression v of type T and a relation ( ) T T that is well-founded on states satisfying p, if b is a single-reference boolean ⊆ expression× under interference satisfying r, and

0 0 p r V p p b V b0 p r b0 V b0 ∧ 0 ∧ ∧ ∧ 0 I Local variables p r V v v p b V b1 p r b1 V b1 ∧  ∧ ¬ ∧ ∧ 0 p b b p r b b I Modules ∧ 2 V ¬ ∧ ∧ 2 V 2 then î ó î ó (rely r) p , p0 b0 while b do((rely r) p b , p0 (v v 0 b0 ) ) e ∧ 1 v e ∧ 0 ∧ ∨ 2 This rule may be shown using Law rely-loop by taking as the variant the ordered pair ( b , v) under the lexicographical ordering, where true false. ¬ 2

133 / 1 134 / 1

Conclusions

I One can develop algebras of programs

I Focus on the algebraic properties first, then semantics

I Need a semantics to show that the algebraic theories are consistent

I Start from a (refinement) lattice and add , , ; k e I For rely/guarantee, start with very primitive commands (τ (p), π(r), (r))

I Links to process algebras, in particular Milner’s Synchronous CCS (SCCS)

I We are developing Isabelle theories for the algebras

135 / 1