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

Verifying Optimistic Concurrency: Prophecy Variables and Backwards Reasoning

  • Upload
    zeke

  • View
    50

  • Download
    0

Embed Size (px)

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

Citation preview

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.