Presentation is loading. Please wait.

Presentation is loading. Please wait.

A Calculus of Atomic Actions Serdar Tasiran Koc University, Istanbul, Turkey Tayfun ElmasShaz Qadeer Koc University Microsoft Research.

Similar presentations


Presentation on theme: "A Calculus of Atomic Actions Serdar Tasiran Koc University, Istanbul, Turkey Tayfun ElmasShaz Qadeer Koc University Microsoft Research."— Presentation transcript:

1 A Calculus of Atomic Actions Serdar Tasiran Koc University, Istanbul, Turkey Tayfun ElmasShaz Qadeer Koc University Microsoft Research

2 Problem Verifying assertions in concurrent programs –Local conditions, program invariants, data integrity, absence of null pointer dereferences,... 2 static void transfer(Account from, Account to, int amount) { assert (from != null && to != null); assert (from.balance >= amount); old_total := from.balance + to.balance; tmp := from.balance; from.balance := tmp – amount; tmp := to.balance; to.balance := tmp + amount; assert (from.balance + to.balance == old_total); }

3 Our Approach: QED Proof method for verifying assertions Implementation: The QED tool Central idea: Atomicity Allows separation of concerns –Concurrency: Non-interference, synchronization mechanism –Data: Sequential reasoning within atomic blocks to prove assertions QED proof rules: Program transformation steps –Abstraction: To increase “non-interference” between actions –Reduction: Prove bigger blocks atomic –Grow atomic blocks Sequential reasoning within atomic blocks 3

4 Outline Motivating example Proof method Experience Full example: Multiset 4

5 Example – inc () 5 inc (): int t; acquire (lock); t = x; t = t + 1; x = t; release(lock); Main: assume (x == 0); inc() || inc() assert (x == 2)

6 Proof by Owicki-Gries A: x=0, B@L5=>x=1> L0: acquire(l); x=0, B@L5=>x=1, held(l,A)> L1: t := x; x=0, B@L5=>x=1, held(l,A), t=x> L2: t := t + 1; x=0, B@L5=>x=1, held(l,A), t=x+1> L3: x := t; x=1, B@L5=>x=2, held(l,A)> L4: release(l) x=1, B@L5=>x=2> B: x=0, A@L5=>x=1> L0: acquire(l); x=0, A@L5=>x=1, held(l,B)> L1: t := x; x=0, A@L5=>x=1, held(l,B), t=x> L2: t := t + 1; x=0, A@L5=>x=1, held(l,B), t=x+1> L3: x := t; x=1, A@L5=>x=2, held(l,B)> L4: release(l) x=1, A@L5=>x=2> 6 ||

7 Reduction α right mover (R) if for every execution ξ = ……. α β ……. ξ’ = ……. β α ……. is equivalent to ξ Static check for α being a right mover: –For all actions β in program, is α β always “simulated” by β α? –Easy case: β cannot follow α Example: α = β = lock.acquire() Reduction: Atomic patterns –RRRR N LLLLL –RRRRR –LLLLL –......

8 Proof by reduction - 1 8 inc (): int t; acquire (lock); t = x; t = t + 1 x = t; release(lock); R B B B L inc (): int t; acquire (lock); t = x; t = t + 1 x = t; release(lock); inc (): x = x + 1; REDUCE-SEQUENTIAL

9 Proof by reduction - 2 9 assume (x == 0); inc() || inc() assert (x == 2) assume (x == 0); x = x + 1 || x = x + 1 assert (x == 2) assume (x == 0); x = x + 1; assert (x == 2) B B INLINE-CALL REDUCE-PARALLEL

10 Non-blocking increment 10 inc (): int t; while(true) { t = x; if(CAS(x, t, t+1)) break; } CAS(x, t, t + 1): assume (x == t); x = t + 1; return true; assume (x != t); return false; □

11 Abstraction for reduction 11 inc (): int t; while(*) { t = x; assume x != t; } t = x; assume x == t; x = t + 1; inc (): int t; while(true) { t = x; if(CAS(x, t, t+1)) break; }

12 Abstraction for reduction 12 inc (): int t; while(*) { t = x; assume x != t; } t = x; assume x == t; x = t + 1; inc (): int t; while(*) { havoc t; skip; } havoc t; assume x == t; x = t + 1; SIMULATE

13 Proof by reduction 13 inc (): int t; while(*) { havoc t; skip; } havoc t; assume x == t; x := t + 1; inc (): int t; havoc t; x := x + 1; REDUCE-LOOP B

14 ActionPL 14 Program: Procedure bodies Program’s main body Global variables Syntax:

15 Gated actions 15 x = x + 1; assert (x != 0); y = y / x; x = x + 1; assert (x != 0); y = y / x; Transition: Two-store relation Gate: Assertion on pre-state

16 Semantics of ActionPL 16 Pre-store violates assertion Pre-store satisfies assertion Pre- and post-store satisfies transition Current dynamic statement Current store Execution: Atomic transitions:

17 Operational semantics 17

18 Proof method 18 Current program Program invariant (proof ensures this) Each execution starts from invariant Each transition preserves invariant Proof context Proof step: Governed by a proof rule May strengthen invariant May rewrite program

19 Soundness Theorem [Preservation] –Each proof step: Let. If goes from to then – goes from to, or – goes wrong from Theorem [Soundness] –Each proof: If goes from to such that then: – goes from to, or – goes wrong from 19 skip, error, other dyn. stmt.

20 Validating assertions 20 Proof succeeds if For all in, holds. Verifying each assertion is local & sequential

21 Invariants 21 Each action either goes wrong or preserves new invariant New invariant is stronger x = y; x = x + 1; assert (x > 0); y = y / x; true x = y; x = x + 1; assert (x > 0); y = y / x; (y >= 0) Does not touch y Preserves invariant if assertion is not violated

22 Validating assertions - example 22 (y >= 0) x = y; x = x + 1; assert (x > 0); y = y / x; assert (y > -1); x = y; x = x + 1; assert (x > 0); y = y / x; (y >= 0) assert (true); x = y; x = x + 1; y = y / x; (y >= 0)  (y > -1)

23 Auxiliary variables 23 inc (): int t; acquire (lock); a := tid; t := x; t := t + 1 x := t; release(lock); a := 0;

24 Auxiliary variables 24 We may modify all actions New transitions preserve invariant We add an auxiliary variable New transition modifies new aux. variable Auxiliary variable does not affect rest of transition predicate, cannot block.

25 Simulation 25 if (x == 1) y = y + 1; if (*) y = y + 1; y = y / x; assert (x > 0); y = y / x; From each store satisfying invariant, goes wrong or simulates. New action preserves invariant Adding behaviors that go wrongAdding non-determinism New action simulates the former

26 Read abstraction 26 inc (): int t; while(*) { t = x; assume x != t; } t = x; assume x == t; x = t + 1; inc (): int t; while(*) { havoc t; skip; } havoc t; assume x == t; x = t + 1; SIMULATE

27 Abstraction with assertions 27 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

28 Abstraction with assertions 28 inc (): int t; acquire (lock); a := tid; assert a == tid; t := x; assert a == tid; t := t + 1 assert a == tid; x := t; assert a == tid; release(lock); a := 0; inc (): int t; acquire (lock); a := tid; t := x; t := t + 1 x := t; release(lock); a := 0; SIMULATE

29 Abstraction with assertions 29 inc (): int t; acquire (lock); a := tid; assert a == tid; t := x; assert a == tid; 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; assert a == tid; t := t + 1 assert a == tid; x := t; assert a == tid; release(lock); a := 0; REDUCE & RELAX R B B B L Discharges the assertions “Borrowing assertions”: Introduce assertions, use them to prove larger blocks atomic Discharge later, when atomic blocks are large enough.

30 Reduction 30 Moving to the left makes the execution either - go to same end state or - makes execution go wrong Actions executed by different threads

31 Reduce - sequential 31

32 Reduce – nondet. choice 32 CAS(x, t, t + 1): assume (x == t); x = t + 1; return true; assume (x != t); return false; □ CAS(x, t, t + 1): assume (x == t); x = t + 1; return true; assume (x != t); return false; □ DIV (x, y): assert (x != 0); y = y / x; return y; □ DIV(x, y): assert (y != 0); x = x / y; return x; y = y / x; return y; □ x = x / y; return x; assert (x != 0 && y != 0);

33 Reduce - loop 33 Loop body is either left or right mover Specification preserves invariant Specification is reflexive Specification simulates zero or more iterations

34 Reduce - parallel 34 Explicitly expand the parallel statement to its possible executions Reduces parallel composition to sequential composition

35 Experience Implementation: Spec#  BoogiePL  QED –Generate verification condition (VC) for validity of each proof step –VC fed to the Z3 theorem prover Purity benchmarks [Flanagan et.al, 2005] Non-blocking algorithms –Obstruction-free deque [Herlihy et.al. 2003] –Non-blocking stack [Michael, 2004] –Bakery [Lamport, 1974] Multiset Conclusion: –Iteration of abstraction and reduction is powerful –Growing atomic code blocks useful approach 35

36 Multiset Multiset data structure M = { 2, 3, 3, 9, 8, 8, 5 } Represented by M[1..n] –elt: The element –vld: Is it in the set? 36 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;

37 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;

38 Rewriting the “if” statement 38 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; □

39 mutex (M[i].lock == true) 39 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; □

40 Read abstraction 40 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

41 Rewriting 41 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; □

42 □ Reducing loop 42 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; □ FindSlot (x) r = -1; i = 0; havoc i; assume (0 <= i < N); assume (M[i].elt == null); M[i].elt = x; r = i; skip; return r; R REDUCE-LOOP

43 Rewriting 43 □ FindSlot (x) r = -1; i = 0; havoc i; assume (0 <= i < N); assume (M[i].elt == null); M[i].elt = x; r = i; skip; return r; □ FindSlot (x) i = 0; havoc i; assume (0 <= i < N); assume (M[i].elt == null); M[i].elt = x; return i; return -1;

44 FindSlot 44 □ FindSlot (x) i = 0; havoc i; assume (0 <= i < N); assume (M[i].elt == null); M[i].elt = x; return i; return -1; Invariant:  (0 <= i < N): (M[i].elt == null)  (M[i].vld == false)

45 mutex (M[i].elt != null && M[i] == false) 45 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; a[i] = tid; j = FindSlot (y); if (j == -1) M[i].elt= null; return failure; a[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 SIMULATE

46 Reduce 46 InsertPair (x, y) i = FindSlot (x); if (i == -1) return failure; a[i] = tid; j = FindSlot (y); if (j == 0) M[i].elt= null; return failure; a[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; a[i] = tid; j = FindSlot (y); if (j == 0) M[i].elt= null; return failure; a[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.

47 Future work Proof script templates for encoding synchronization idioms –Guidelines for adding annotation and code transformations –Mutual-exclusion, readers/writers lock, barriers –Barriers, event synchronization –Optimistic concurrency Statically checking serializability of marked-atomic blocks Verifying STM implementations using QED 47

48

49

50

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

52 Invariant for “a” 52 InsertPair (x, y) i = FindSlot (x); if (i == -1) return failure; a[i] = tid; j = FindSlot (y); if (j == 0) M[i].elt= null; return failure; a[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 Invariant:  (0 <= i < N): (M[i].elt != null && M[i].vld == false)  (a[i] != 0)


Download ppt "A Calculus of Atomic Actions Serdar Tasiran Koc University, Istanbul, Turkey Tayfun ElmasShaz Qadeer Koc University Microsoft Research."

Similar presentations


Ads by Google