Presentation is loading. Please wait.

Presentation is loading. Please wait.

Thread Quantification for Concurrent Shape Analysis Josh BerdineMSR Cambridge Tal Lev-AmiTel Aviv University Roman ManevichTel Aviv University Mooly Sagiv.

Similar presentations


Presentation on theme: "Thread Quantification for Concurrent Shape Analysis Josh BerdineMSR Cambridge Tal Lev-AmiTel Aviv University Roman ManevichTel Aviv University Mooly Sagiv."— Presentation transcript:

1 Thread Quantification for Concurrent Shape Analysis Josh BerdineMSR Cambridge Tal Lev-AmiTel Aviv University Roman ManevichTel Aviv University Mooly Sagiv Tel Aviv University Ganesan RamalingamMSR India

2 2 Non-blocking stack [Treiber,‘86] void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); [7] } data_type pop(Stack *S){ [8] do { [9] Node *t = S->Top; [10] if (t == NULL) [11] return EMPTY; [12] Node *s = t->n; [13] data_type r = t->d; [14] } while (!CAS(&S->Top,t,s)); [15] return r; [16] } benign data races unbounded number of threads x points to valid memory? does list remain acyclic? stack linearizable? Automatic proof of linearizability for an unbounded number of threads

3 Linearizability [Herlihy and Wing, TOPLAS'90] Linearizable data structure Sequential specification defines legal sequential executions Concurrent operations allowed to be interleaved Operations appear to execute atomically External observer gets the illusion that each operation takes effect instantaneously at some point between its invocation and its response time push(4) pop():4push(7) push(4) pop():4push(7) Last In First Out Concurrent LIFO stack T1T1 T2T2 3

4 push2(4,5) pop2():8,5push2(7,8) 4 Non-linearizable pairs stack void push2(Stack *S, data_type v1, data_type * v2) { push(s, v1); push(s, v2); } void pop2(Stack *S, data_type * v1, data_type * v2) { *v2 = pop(s); *v1 = pop(s); } time push2(4,5) pop2():8,5push2(7,8) illegal sequential execution

5 push2(4,5) pop2():8,5push2(7,8) 5 Non-linearizable pairs stack void push2(Stack *S, data_type v1, data_type * v2) { push(s, v1); push(s, v2); } void pop2(Stack *S, data_type * v1, data_type * v2) { *v2 = pop(s); *v1 = pop(s); } time push2(4,5) pop2():8,5push2(7,8) illegal sequential execution

6 6 Main results New parametric shape analysis Universally quantified shape abstractions Extra level of quantification over shape abstraction Fine-grained concurrency Unbounded number of threads Thread-modular aspects Sound transformers Application Checking linearizability of concurrent data structures

7 7 Outline Motivation + what is linearizability Universally quantified shape abstractions Checking linearizability via conjoined execution and delta abstraction Experimental results

8 Universally Quantified Shape Abstractions 8

9 9 Concurrent heaps [Yahav, POPL’01] Heaps contain both threads and objects Logical structure, or Formula in subset of FO TC [Yorsh et al., TOCL‘07] thread object with program counter thread-local variable list field list object pc=6 pc=2 x n x Top t

10 10 Heaps contain both threads and objects Logical structure, or Formula in subset of FO TC [Yorsh et al., TOCL‘07] pc=6 pc=2 x n x Top t pc(tr 1 )=6  pc(tr 2 )=2   v 1,v 2,v 3. Top(v 1 )  x(tr 1,v 2 )  t(tr 1,v 1 )  x(tr 2,v 3 )  n(v 2,v 1 ) … v1v1 v3v3 v2v2 tr 1 tr 2 Concurrent heaps [Yahav, POPL’01]

11 Unbounded concurrent heaps 11 void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); [7] } pc=6 pc=4 x n x Top pc=1 pc=2 x x t pc=4 x t pc=6 x n t t pc=1 Unbounded parallel composition: push(Top,?) ||... || push(Top,?) n n

12 Local heaps Each local heap Presents a view of heap relative to one thread Can be instantiated ≥0 times 12 pc=4 t pc=2 x x pc=1 Top pc=6 t n x Top n n n n n n n n

13 Bounded local heaps Each local heap Presents a view of heap relative to one thread Can be instantiated ≥0 times Bounded by finitary abstraction (Canonical Abstraction) 13 pc=4 t pc=2 x x pc=1 Top pc=6 t n x Top n n n n n n n n

14 14 pc(tr 1 )=6  pc(tr 2 )=2   v 1,v 2,v 3. Top(v 1 )  x(tr 1,v 2 )  t(tr 1,v 1 )  x(tr 2,v 3 )  n(v 2,v 1 ) … Concurrent heap pc=6 pc=2 x n x Top t v1v1 v3v3 v2v2 tr 1 tr 2

15 pc=2 x Top pc(t)=6   v 1,v 2. Top(v 1 )  x(t,v 2 )  t(t,v 1 )  n(v 2,v 1 ) …  t. pc(t)=2   v 1,v 3. Top(v 1 )  x(t,v 3 ) …  Universally quantified local heaps pc=6 x n Top t overlapping local heaps 15 t t v1v1 v1v1 v2v2 v3v3 symbolic thread

16 pc(t)=6   v 1,v 2. Top(v 1 )  x(t,v 2 )  t(t,v 1 )  n(v 2,v 1 ) …  t. pc(t)=2   v 1,v 3. Top(v 1 )  x(t,v 3 ) …  Meaning of quantified invariant pc=6 x n Top t x pc=1 pc=6 pc=2 t Information maintained (dis)equalities between local variables of each thread and global variables Objects reachable from global variables Information lost Number of threads (dis)equalities between local variables of different threads 16 pc=2 x Top x pc=1 pc=6 pc=3 t pc=1 ×m×m n×n× 

17 Loss of non-aliasing information pc(t)=6   v 1,v 2. Top(v 1 )  x(t,v 2 )  t(t,v 1 )  n(v 2,v 1 ) …  t. pc=6 x n Top pc=6 x n t t x n t x t unwanted aliasing consider x->n=t Remedy: record non-aliasing information explicitly 17 n

18 Adding non-aliasing information pc=6 P x n Top pc=6 P x n t t x n t x Referenced by exactly one thread pc(t)=6   v 1,v 2. Top(v 1 )  x(t,v 2 )  t(t,v 1 )  n(v 2,v 1 )  Private(v 1 )  Private(v 2 ) …  t. P t 18 n

19 Adding non-aliasing information pc(t)=6   v 1,v 2. Top(v 1 )  x(t,v 2 )  t(t,v 1 )  n(v 2,v 1 )  Private(v 1 )  Private(v 2 ) …  t. pc=6 P x n Top pc=6 P x n t t x n t P x P t Operation on private objects invisible to other threads 19 n

20 Recap Add universal quantification on top of finitary heap abstractions Handle unbounded number of threads Local heaps can overlap Handle fine-grained concurrency Strengthen local heaps by Private predicate Private objects cannot be affected by actions of other threads Missing: transformers (see paper) 20

21 Checking linearizability for an unbounded number of threads 21

22 Verification of fixed linearization points [Amit et al., CAV’07] Compare each concurrent execution to a specific sequential execution Show that every (terminating) concurrent operation returns the same result as its sequential counterpart linearization point operation Concurrent Execution Sequential Execution compare results... linearization point Conjoined Execution compare results 22

23 23 Linearization points for Treiber’s stack void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // @LINEARIZE on CAS [7] } data_type pop(Stack *S){ [8] do { [9] Node *t = S->Top; // @LINEARIZE [10] if (t == NULL) [11] return EMPTY; [12] Node *s = t->n; [13] data_type r = t->d; [14] } while (!CAS(&S->Top,t,s)); // @LINEARIZE on CAS [15] return r; [16] }

24 Shape analysis with delta abstraction [Amit et al., CAV’07] Tracks bounded differences between concurrent and sequential execution Abstracts two heaps together  Limited to bounded number of threads Tracks correlations between all threads  Feasible up to 4 threads 24 What about an unbounded number of threads?

25 25 Our approach Tracks bounded differences between concurrent and sequential execution per thread Handles unbounded number of threads Abstracts correlations between threads Thread-modular characteristics

26 Top pc=1 26 Conjoined execution for push concurrent state sequential view isomorphism relation Top void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // LINEARIZE on CAS [7] }

27 Top pc=1 27 Conjoined execution for push conjoined state duo-object void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // LINEARIZE on CAS [7] }

28 28 Conjoined execution for push Top pc=2 P x delta object Top pc=1 void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // LINEARIZE on CAS [7] }

29 29 Conjoined execution for push void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // LINEARIZE on CAS [7] } Top pc=2 P x Top pc=1 Top pc=5 P x t … Top pc=6 P x t n if (S  Top == t) S  Top = x; evaluate to true; else evaluate to false; Top pc=7 n

30 30 Run operation sequentially void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // LINEARIZE on CAS [7] } Top pc=7 n Top pc=7 n x Top pc=7 n x t Top pc=7 n x t n Top pc=7 nn

31 31 Run operation sequentially Top pc=7 n Top pc=7 n x Top pc=7 n x t Top pc=7 n x t n Top pc=7 n But how do you handle unboundedness due to recursive data structures? Employ Canonical Heap Abstraction void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); // LINEARIZE on CAS [7] }

32 32 An unbounded state void push(Stack *S, data_type v) { [1] Node *x = alloc(sizeof(Node)); [2] x->d = v; [3] do { [4] Node *t = S->Top; [5] x->n = t; [6] } while (!CAS(&S->Top,t,x)); LINEARIZE on CAS [7] } pc=6 pc=4 P x n P x Top pc=1 pc=2 P x P x t pc=4 P x t pc=6 P x n t t pc=1 unbounded number of delta objects n n

33 Top pc=1 n n Top pc=2 P x n n pc=4 P x Top t n n pc=6 P x n Top t n n 33 Bounded local states number of delta objects per local heap bounded

34 Observations used Unbounded number of heap objects Number of delta objects created per thread is bounded Objects in recursive data structures bounded by known shape abstractions Delta objects always referenced by local variables + global variables Captured by local heaps Threads mutate data structure near global access points 34

35 35 Verified Programs#statestime (sec.) Treiber’s stack [1986] 764 7 Two-lock queue [Michael & Scott, PODC’96] 3,415 17 Non-blocking queue [Doherty & Groves, FORTE’04] 10,333 252 Experimental results First automatic verification of linearizability for unbounded number of threads

36 36 What’s missing from the talk? Generic technique for lifting abstract domains with universal quantifiers Abstract transformers Thread instantiation Combining universal quantification with heap decomposition

37 37 Related work [Yahav, POPL’01] Shape analysis with counter abstraction [Gotsman et al., PLDI’07] Thread-modular shape analysis for coarse-grained concurrency [Amit et al., CAV’07] Linearizability for a bounded number of threads [Vafeiadis et al.,’06,’07,’08] Linearizability for an unbounded number of threads with Rely-Guarantee reasoning w. separation logic Requires user annotations [Gulwani et al., POPL’08] Lifting abstract interpreters to quantified logical domains [Pnueli et al., TACAS’01] [Clarke et al., TACAS’08] [Namjoshi, VMCAI’07] Model checking concurrent systems shape analysis model checking concurrency +

38 38 Conclusion Parametric shape abstraction for an unbounded number of threads Fine-grained concurrency Thread-modular aspects Integrated into TVLA Automatically proves linearizability of fine-grained concurrent implementations

39 39 Thank You

40 Can you handle mutex? Yes with Canonical Abstraction  t 1. { ….  t 2. … } Not with Boolean Heaps Only one level of quantification 40

41 Requirements from base domain Support free variables  (u,v,w) Support join and meet operations 41

42 42 Thread-modular analysis Single global resource invariant [Flanagan & Qadeer, SPIN 03] pc=1 Separated resource invariants [Gotsman et al., PLDI 07] Coarse-grained concurrency pc=1 Non-disjoint resource invariants [this paper] Fine-grained concurrency pc=1

43 Constructing the correlation relation Incrementally constructed during execution Nodes allocated by matching push operations are correlated Correlated nodes have equal data values Show that matching pops return data values of correlated nodes

44 Fixed linearization points Every operation has (user-specified) fixed linearization point Statement at which the operation appears to take effect Show that these linearization points are correct for every concurrent execution User may specify Several (alternative) linearization points Certain types of conditional linearization points e.g., successful CAS operations 44

45 Stack's most-general client void client (Stack  S) { do { if (?) push(S, rand()); else pop(S); } while ( 1 ); }


Download ppt "Thread Quantification for Concurrent Shape Analysis Josh BerdineMSR Cambridge Tal Lev-AmiTel Aviv University Roman ManevichTel Aviv University Mooly Sagiv."

Similar presentations


Ads by Google