verifying optimistic concurrency: prophecy variables and backwards reasoning

60
Verifying Optimistic Concurrency: Prophecy Variables and Backwards Reasoning Serdar Tasiran Koç University Istanbul, Turkey Tayfun Elmas Shaz Qadeer Ali Sezgin Koç University Microsoft Research Koç University Istanbul, Turkey Redmond, WA Istanbul, Turkey

Upload: zeke

Post on 22-Feb-2016

50 views

Category:

Documents


0 download

DESCRIPTION

Verifying Optimistic Concurrency: Prophecy Variables and Backwards Reasoning . Serdar Tasiran Koç University Istanbul, Turkey Tayfun Elmas Shaz Qadeer Ali Sezgin Koç University Microsoft Research Koç University Istanbul , Turkey Redmond, WA Istanbul, Turkey. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Verifying Optimistic Concurrency: Prophecy Variables and Backwards Reasoning

Serdar TasiranKoç University

Istanbul, Turkey

Tayfun Elmas Shaz Qadeer Ali Sezgin Koç University Microsoft Research Koç University

Istanbul, Turkey Redmond, WA Istanbul, Turkey

Page 2: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

2Static Reduction Proofs for Optimistic Concurrency

– Goal: Verify programs that use optimistic concurrency• Transactional memory, non-blocking data structures, …• “A Compositional Method for Verifying Software

Transactional Memory Implementations” [MSR Tech. Report ’07]

– Optimistic concurrency: Proceed assuming non-interference• Abort, undo and/or retry if interference detected

• Approach: Static proof system QED [POPL ‘09, PADTAD ‘09]

– Challenge in applying QED to optimistic concurrency:• Same code, different reduction proofs for different futures• Need mechanism for referring to execution’s future

➡ Prophecy variables and backwards reasoning in QED

Page 3: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Outline

• Forward reasoning overview • Lock-protected increment• QED proof

• History variables, “assert” annotations

• Backward reasoning: Temporal dual• Optimistic concurrency example: Copy

• Why forward reasoning doesn’t work• Temporally dual approach

• Prophecy variables, “tressa” annotations• Generalized (back and forth) QED

• Examples

3

Page 4: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

QED Proof for Blocking Concurrency

local int t;acquire (lock);t := x;t := t + 1;x := t;release (lock);

global int x;

x := 0;

||

assert (x == 2);

local int t;acquire (lock);t := x;t := t + 1;x := t;release (lock);

• Example: Lock-protected increment

4

Page 5: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

5

Idea: Proof by reduction

acquire (lock);

t := x;

t := t + 1;

x := t;

release(lock);

R

B

B

B

L

acquire (lock);

t := x;

t := t + 1;

x := t;

release(lock);

REDUCE-SEQUENTIAL

Page 6: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

6

Static mover check fails: Apparent conflict

acquire (lock);

t1 := x;

t1 := t1 + 1;

x := t1;

release(lock);

acquire (lock);

t2 := x;

t2 := t2 + 1;

x := t2;

release(lock);

• Static mover check is local, fails!

• Individual actions do not locally contain the information:• “Whenever this action executes, this thread holds the lock”

• Annotate action with local assertion: • Express belief about non-interference

Page 7: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

7

Auxiliary variable: Which thread holds the lock?

inc (): int t; acquire (lock);

t = x;

t = t + 1

x = t;

release(lock);

inc (): int t; acquire (lock); a := tid;

t = x;

t = t + 1

x = t;

release(lock); a := 0;

AUX-ANNOTATE

New invariant: (lock == true) (a != 0)

• Auxiliary variable a is a history variable• Summarizes relevant part of execution history

Page 8: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

8

Annotating Actions with Assertions

acquire (lock); a := tid;

assert a == tid; t = x;

t = t + 1

assert a == tid; x = t;

assert a == tid; release(lock); a := 0;

acquire (lock); a := tid;

t = x;

t = t + 1

x = t;

release(lock); a := 0;

ABSTRACT

Invariant: (lock == true) (a != 0)

• Assertions indicate belief about non interference• Annotate actions locally with global information about execution

Page 9: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

History Variable Annotations Make Static Mover Check Pass

9

Thread 1

acquire (lock); a := tid1;

assert a == tid1; t1 = x;

t1 = t1 + 1

assert a == tid1; x = t1;

assert a == tid1; release(lock); a := 0;

R

B

B

B

L

Thread 2 acquire (lock); a := tid2;

assert a == tid2; t2 = x;

t2 = t2 + 1

assert a == tid2; x = t2;

assert a == tid2; release(lock); a := 0;

• assert a == tid1; x = t1; and assert a == tid2; x = t2; commute

• α β ≤ β α • Because α β and β α result in assertion violations.

Page 10: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

10

Borrowing and paying back assertions

inc (): int t; acquire (lock); a := tid;

assert a == tid; t = x;

t = t + 1

assert a == tid; x = t;

assert a == tid; release(lock); a := 0;

inc (): int t; acquire (lock); a := tid;

assert a == tid; t = x;

t = t + 1

assert a == tid; x = t;

assert a == tid; release(lock); a := 0;

REDUCE & RELAX

R

B

B

B

L

Dischargesthe assertions

Invariant: (lock == true) (a != 0)

Page 11: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Outline• Forward reasoning overview

– Lock-protected increment– QED proof

• History variables, “assert” annotations

• Backward reasoning: Temporal dual– Optimistic concurrency example: Copy

• Why forward reasoning doesn’t work– Temporally dual approach

• Prophecy variables, “tressa” annotations– Generalized (back and forth) QED

• Examples

11

Page 12: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Optimistic Concurrency Example

12

Copy(fr: Obj, to: Obj){

atomic{ version := fr.ver; value := fr.val;}

atomic{ if (version == fr.ver) {to.val := value; to.ver := to.ver + 1;} }}

Wrt(to: Obj, newVal: int){ atomic{ to.val := newVal; to.ver := to.ver + 1;}}

Page 13: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Optimistic Concurrency Example

13

Copy(fr: Obj, to: Obj){

action SS(fr): atomic{ version := fr.ver; value := fr.val;}

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) {to.val := value; to.ver := to.ver + 1;} }}

Wrt(to: Obj, newVal: int){ atomic{ to.val := newVal; to.ver := to.ver + 1;}}

Page 14: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Optimistic Concurrency Example

14

Copy(fr: Obj, to: Obj){

action SS(fr): atomic{ version := fr.ver; value := fr.val;}

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) {to.val := value; to.ver := to.ver + 1;} }}

Wrt(to: Obj, newVal: int){ atomic{ to.val := newVal; to.ver := to.ver + 1;}}

Goal: Prove that SS(fr) is a right mover

Page 15: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Reduction for Optimistic Concurrency

• Copy(x, to_y) running concurrently with Wrt(x)– Does SS always commute to the right of Wrt?

• Failing Copy (Wrt interferes with Copy)

T1: SS(x) ConfNWrt(x, to_y) T2: Wrt(x, val)

• Succeeding Copy (No interference)

T1: SS(x) ConfNWrt(x, to_y) T2: Wrt(x, val)

15

Page 16: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Reduction Argument for Optimistic Concurrency

• Failing Copy T1: SS(x) ConfNWrt(x, to_y) T2: Wrt(x, val)

• Snapshot taken but ConfNWrt does not write to to_y.

➡ Abstract SS:

action SS(fr): atomic{ version := fr.ver; value := fr.val;}

action SS_Abs(fr): atomic{ havoc version, value; }

16

Page 17: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Copy Example After AbstractionCopy(fr: Obj, to: Obj){

action SS_Abs(fr): atomic{ havoc version, value; }

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) {to.val := value; to.ver := to.ver + 1;} }}

Wrt(to: Obj, newVal: int){ atomic{ to.val := newVal; to.ver := to.ver + 1;}}

17

Page 18: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Problem: Too much abstraction

• Succeeding Copy (No interference)

T1: SS_Abs(x) ConfNWrt(x, to_y) T2: Wrt(x, val)

• Arbitrary value written to to_y!• Want to abstract SS(x) to SS_Abs(x) only in executions

in which interference occurs (later).

• But, SS_Abs doesn’t yet know whether interference will occur.– Need mechanism to refer to the future of the execution.

18

Page 19: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Prophecy Variables• Prophecy variable: Auxiliary variable, encodes future non-determinism

– Allows actions to refer to future locally– Can use in annotations, abstraction.

• Different reduction proofs for different futures• Concurrent systems: Non-determinism due to thread interleaving

19

p = R, G or B

Page 20: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Introducing a Prophecy Variableaction ConfNWrt(fr, to):

atomic{ if (version == fr.ver)

{to.val := value; to.ver := to.ver + 1;}

}

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) { p =: true; to.val := value; to.ver := to.ver + 1; } else { p =: false; } }}

20

Page 21: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Backwards Assignment “=:”

21

• Backwards assignment p =: x; • Shorthand for atomic{ assume p == x; havoc p;}

• p should match x

• p’ can have any value• Thinking backwards in time: Assigns the value of x to p

• In the execution, up to the point the following action is taken

if (version == fr.ver) { p =: true; to.val := value; to.ver := to.ver + 1; } else { p =: false;}

p is true iff the version number check (later) succeeds.

Page 22: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Prophecy Variable Introduction: Soundness

22

• Annotating action α(s,s’) with prophecy variable p

α(s,s’) becomes β(s,p, s’,p’)

• Must satisfy • p’. p. β(s,p, s’,p’) (History variables: h. h’. β(s,h, s’,h’) )• Backwards assignment satisfies this

• Soundness:• Every state of every execution can be annotated with a value of p.

τ

Page 23: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Abstraction Constrained by Prophecy Variable

23

action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} }

Page 24: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

24

Reduction Proof of Optimistic Concurrency

• Succeeding Copy

T1: SS(x) ConfNWrt(x, to_y)

T2: Wrt(x, val)

• SS(x) commutes to the right of Wrt(x, val)• Copy succeeds Wrt(x, val) never immediately follows SS(x)• Need to annotate SS(x) with this fact.

• Similar case:

assert a == tid1; x = t1; and assert a == tid2; x = t2;

• These two actions cannot follow each other

Page 25: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

25

Reduction Proof of Optimistic Concurrency

• Copy succeeds Wrt(x, val) never immediately follows SS(x)

• Need to annotate SS(x) with this fact.

• But SS(x) doesn’t yet know whether this is a succeeding Copy.

• Think backwards:• Walk back from the end of an execution, • When we reach s2, we know whether Copy has been successful.• Restated fact: If Copy succeeded,

at s2, the version number snapshot should be up-to-date.

s0 s2s1

SS(x)……

ConfNWrt(x)…

Page 26: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Putting it all together

26

Copy(fr: Obj, to: Obj){

action SS_P(fr): atomic{ if (p) {version := fr.ver; value := fr.val;} else { havoc version, value;} tressa p ==> (version >= fr.ver); }

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) { p =: true; to.val := value; to.ver := to.ver + 1; } else { p =: false; } }}

Page 27: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

tressa : Temporal Dual of assert

• tressa: Mechanism to annotate actions with assertions that can refer to prophecy variables

• assert: Discharged by reasoning about history of execution.

• tressa: Temporal dual of assert

• Example:

y := y+1; z := z-1; assume (x == 0);

27

Page 28: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

tressa : Temporal Dual of assert

• Example: y := y+1; // x == 0 or execution blocks z := z-1; // x == 0 or execution blocks assume (x == 0);

• But

atomic{ assert x == 0; y := y+1;} atomic{ assert x == 0; z := z-1;} assume (x == 0);

does not work!

• Cannot discharge the assertions!

28

Page 29: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

tressa : Temporal Dual of assert

• Example: y := y+1; // x == 0 or execution blocks z := z-1; // x == 0 or execution blocks assume (x == 0);

• tressa φ: Either φ holds in the post state, or execution does not terminate (blocks).

atomic{ y := y+1; tressa x == 0;} atomic{ z := z-1; tressa x == 0;} assume (x == 0);

• tressa annotations discharged by backwards reasoning within an atomic block.

• Discharged tressa φ: You cannot come back from a final state of the program and violate φ

29

Page 30: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

30

Discharging tressa’s

inc (): int t; acquire (lock); p =: 0

tressa a == tid; t = x;

t = t + 1

tressa a == tid; x = t;

release(lock); p =: tid;

inc (): int t; acquire (lock); p =: 0;

tressa p == tid; t = x;

t = t + 1

tressa a == tid; x = t;

release(lock); p =: tid;

REDUCE & RELAX

R

B

B

B

L

Page 31: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Actions with assert’s and tressa’s

• Canonical action α: {assert a1; τ1; tressa p1} – τ1( s, s’) : Transition predicate– a1(s): assert predicate on the pre-state– p1(s’): tressa predicate on the post-state

• Operational semantics:– assert and tressa predicates have no effect on execution

• Execution has assert violation if any αi’s assert predicate is violated.• Execution has tressa violation if any αi’s tressa predicate is violated.• QED± preserves assert and tressa violations

31

s0 sn-1s3s2s1 sn

α0 α2α1 …αn-1

Page 32: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Abstraction and Mover Checks with tressa’s

{assert a1; τ1; tressa p1} ≤ {assert a2; τ2; tressa p2}

• Preserve assert violations: a2 a1

• Preserve assert violations: p2 p1

• Forward simulate or replace with assert violation: τ1 (s,s’) τ2 (s,s’) ∨ a2(s)

• Backward simulate orreplace with tressa violation: τ1 (s,s’) τ2 (s,s’) ∨ p2(s’)

• Does α commute to the right of β ? α β ≤ β α

32

abstracts

Page 33: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Putting it all together

33

Copy(fr: Obj, to: Obj){

action SS_P(fr): atomic{ if (p) {version := fr.ver; value := fr.val;} else { havoc version, value;} tressa p ==> (version >= fr.ver); }

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) { p =: true; to.val := value; to.ver := to.ver + 1; } else { p =: false; } }}

Page 34: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == false

Wrt(x) SS_P (x):havoc version, value

action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_P Wrt ≤ Wrt SS_P (Case 1)

34

Page 35: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == false SS_P(x):havoc version, valueWrt(x)

Wrt(x) SS_P (x):havoc version, value

action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_P Wrt ≤ Wrt SS_P (Case 1)

35

Page 36: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

Wrt(x)

SS_P Wrt ≤ Wrt SS_P (Case 2)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_Proph(x):tressa(version>=x.ver)

36

Page 37: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

Wrt(x)

SS_P Wrt ≤ Wrt SS_P (Case 2)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_Proph(x):tressa(version>=x.ver)version < x.ver (Case 2)

37

Page 38: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

Wrt(x)version < x.ver

SS_P Wrt ≤ Wrt SS_P (Case 2)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_Proph(x):tressa(version>=x.ver)version < x.ver (Case 2)

38

Page 39: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

Wrt(x)version < x.ver

SS_P Wrt ≤ Wrt SS_P (Case 2)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_Proph(x):tressa(version>=x.ver)version < x.ver (Case 2)

SS_P (x):tressa(version>=x.ver)

39

Page 40: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

SS_P Wrt ≤ Wrt SS_P (Case 3)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

Wrt(x)SS_Proph(x):tressa(version>=x.ver)

✔40

Page 41: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

SS_P Wrt ≤ Wrt SS_P (Case 3)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

Wrt(x)SS_Proph(x):tressa(version>=x.ver)

version == x.ver

✔41

Page 42: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

SS_P Wrt ≤ Wrt SS_P (Case 3)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

Wrt(x)SS_Proph(x):tressa(version>=x.ver)

version == x.ver

version+1 == x.ver✔42

Page 43: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

p == true

SS_P Wrt ≤ Wrt SS_P (Case 3)action SS_P(x): atomic{ if (p) {version := x.ver; value := x.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

Wrt(x) { atomic{ x.val := newVal; x.ver := x.ver + 1;} }

SS_Proph(x):tressa(version>=x.ver)Wrt(x)

SS_Proph(x):tressa(version>=x.ver)version == x.ver

version+1 == x.ver

43

Page 44: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Copy is Atomic

44

Copy(fr: Obj, to: Obj){

action SS_P(fr): atomic{ if (p) {version := fr.ver; value := fr.val;} else { havoc version, value;} tressa p ==> (version >= ver); }

action ConfNWrt(fr, to): atomic{ if (version == fr.ver) { p =: true; to.val := value; to.ver := to.ver + 1; } else { p =: false; } }}

R

Page 45: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Proving Optimistic Concurrency in QED

• tressa’s allow one to express the following fact locally– If action b immediately follows action a, then this execution will eventually block

• Optimistic concurrency proof template:– Introduce prophecy variables– Backwards assign them when non-determinism is resolved– Annotate earlier actions with tressa’s– Perform a case split in the proof based on possible futures– When blocks are large enough, discharge tressa’s by reasoning

backwards in time.

45

Page 46: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Example 2: ReadPairprocedure ReadPair(a: int, b: int)returns (s: bool, da: Obj, db: Obj){ var va: int, vb: int;

1: atomic { va := m[a].v; da := m[a].d; }2: atomic { vb := m[b].v; db := m[b].d; }3: s := true;4: atomic { if (va < m[a].v) { s:= false; } }5: atomic { if (vb < m[b].v) { s:= false; } }6: if (!s) { da := nil; db := nil; }}

procedure Write(a: int, d: Obj){ atomic { m[a].d := d; m[a].v := m[a].v+1; }}

46

Page 47: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Example 3: Multiset (Insert/Lookup)procedure Lookup(x: data) returns result: bool;{ f := false; i := 0;

while (i<n && !f) { f := (q[i] == x); i := i+1; } result = f;}

procedure Insert(x: data) returns result: bool;{ havoc i; assume i<n; cnt := 0; result := false;

while (cnt<n && !f) { if (q[i]==-1) {q[i] := x; result := true; } else if (q[i]== x) { result := true; } else { i := (i+1) mod n; cnt := cnt+1; } }}

47

Page 48: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Example 3: Multiset (Insert/Lookup)procedure Lookup(x: data) returns result: bool;{ … while (i<n && !f) { f := (q[i] == x); i := i+1; } result = f;}procedure Insert(x: data) returns result: bool; { ... }

• Lookup’s that return true commit when they find x.• Lookup’s that return false commit when they read q[0].• Different reduction proofs needed for the two cases• Replace Lookup(x) with

if (*) { Lookup(x); assume result} else { Lookup(x); assume !result}

• Use return value as prophecy variable• Perform different reduction proofs on the two branches

48

Page 49: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Summary

• QED: Proof system for concurrent software – Iteration of abstraction and reduction surprisingly powerful– Intricate algorithms verified

• Reduction proofs for optimistic concurrency– Actions need to refer to the future: prophecy variables– Annotate actions locally with info about future: tressa

• QED + prophecy variables, tressa’s, forward & backward reasoning– Generalized definition of simulation– Soundness proof

• Proved examples making use of optimistic concurrency• Future work: Verify transactional memory algorithms,

non-blocking data structures.

49

Page 50: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

50

Page 51: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

51

Page 52: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Multiset

• Multiset data structureM = { 2, 3, 3, 9, 8, 8, 5 }

• Represented by M[1..n]– elt: The element– vld: Is it in the set?

52

M 9

✔8

✔6

✗8

✔5

✔3

✗3

✔3

✔2

✔elt

vld

LookUp (x)for i = 1 to n acq (M[i]); if (M[i].elt==x && M[i].vld) rel (M[i]); return true; else rel (M[i]); return false;

Page 53: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

FindSlot and InsertPair

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); if (M[i].elt == null) { M[i].elt= x; rel (M[i]); r = i; } else { rel (M[i]);

} i = i + 1;}return r;

InsertPair (x, y)

i = FindSlot (x);if (i == -1) { return failure;}j = FindSlot (y);if (j == -1) { M[i].elt= null; return failure;}acq (M[i])acq (M[j]) M[i].vld = true; M[j].vld = true;rel (M[i]);rel (M[j]);return success;

Page 54: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Rewriting the “if” statement54

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); if (M[i].elt == null) { M[i].elt= x; rel (M[i]); r = i; } else { rel (M[i]);

} i = i + 1;}return r;

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

acq (A[i]); assume (M[i] != null); rel (M[i]); i = i + 1;}return r;

Page 55: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

mutex (M[i].lock == tid)55

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

acq (A[i]); assume (M[i] != null); rel (M[i]); i = i + 1;}return r;

□REDUCE

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

acq (A[i]); assume (M[i] != null); rel (M[i]); i = i + 1;}return r;

Page 56: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Read abstraction56

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

acq (A[i]); assume (M[i] != null); rel (M[i]); i = i + 1;}return r;

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

acq (A[i]); skip rel (M[i]); i = i + 1;}return r;

□SIMULATE

Page 57: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

“Collapse”57

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

acq (A[i]); skip; rel (M[i]); i = i + 1;}return r;

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) { acq (A[i]); assume (M[i].elt == null); M[i].elt= x; rel (M[i]); r = i;

skip

i = i + 1;}return r;

Page 58: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Reducing the loop (Peel out last iteration)58

FindSlot (x)r = -1; i = 0;while(i < N && r == -1) {

skip; i = i + 1; } havoc i; assume (0 <= i < N) && r ==-1;acq (A[i]); assume (M[i].elt == null); M[i].elt= x;rel (M[i]);r = i;

skip;return r;

R

FindSlot (x)i = 0;

havoc i;assume (0 <= i < N); assume (M[i].elt == null); M[i].elt = x; return i;

return -1;

Page 59: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

59

InsertPair (x, y)

i = FindSlot (x);if (i == -1) return failure;

j = FindSlot (y);if (j == -1) M[i].elt= null; return failure;

acq (M[i])acq (M[j]) M[i].vld = true; M[j].vld = true;rel (M[i]);rel (M[j]);return success;

InsertPair (x, y)

i = FindSlot (x);if (i == -1) return failure;res[i] := tid;

j = FindSlot (y);if (j == -1) M[i].elt= null; return failure;res[j] := tid;

acq (M[i])acq (M[j]) M[i].vld = true; M[j].vld = true;rel (M[i]);rel (M[j]); return success;

R

R

Page 60: Verifying Optimistic Concurrency:  Prophecy Variables and Backwards Reasoning

Reduce60

InsertPair (x, y)

i = FindSlot (x);if (i == -1) return failure;res[i] = tid;

j = FindSlot (y);if (j == 0) M[i].elt= null; return failure;res[j] = tid;

acq (M[i])acq (M[j]) M[i].vld = true; M[j].vld = true;rel (M[i]);rel (M[j]); return success;

R

R

InsertPair (x, y)

i = FindSlot (x);if (i == -1) return failure;res[i] = tid;

j = FindSlot (y);if (j == 0) M[i].elt= null; return failure;res[j] = tid;

acq (M[i])acq (M[j]) M[i].vld = true; M[j].vld = true;rel (M[i]);rel (M[j]); return success;

REDUCE-SEQ.