Download presentation
Presentation is loading. Please wait.
Published byOliver Reed Modified over 8 years ago
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
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)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.