Comparison Under Abstraction for Verifying Linearizability Daphna Amit Noam Rinetzky Mooly Sagiv Tom RepsEran Yahav Tel Aviv UniversityUniversity of Wisconsin IBM T.J. Watson Research Center
Verification Challenge Unbounded dynamically-allocated concurrent data structure Non blocking stack [Treiber, '86] Non blocking queue [Michael and Scott, PODC’96] … Challenge: automatically prove linearizability concurrent data structure T1T1 T2T2 TnTn...
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():4 push(7) Last In First Out concurrent LIFO stack T1T1 T2T2
Main Contributions A conservative automatic algorithm for verifying linearizability –Unbounded linked concurrent data structures –Fixed (arbitrary) number of threads –Implementation and experimental results A novel shape abstraction that allows comparison between mutable linked data structures
Our Approach Construct for every concurrent execution an “equivalent” sequential execution –Simultaneously manipulate 2 data structures Concurrent data structure (manipulated by interleaved operations) Sequential data structure (manipulated by atomic operations) –Executable sequential specification concurrent stack T1T1 T2T2 sequential stack T1T1 T2T2
Our Approach Construct for every concurrent execution an “equivalent” sequential execution –Compare results of matching operations time push(4) pop():4push(7) push(4)pop():4push(7) concurrent stack T1T1 T2T2 sequential stack T1T1 T2T2
Comparison under abstraction of unbounded state systems may be possible when the difference between the systems is bounded Why Is It Challenging?Main Observation Show that the observable behavior along every concurrent execution trace is equivalent to that of a corresponding sequential execution trace Comparison between two unbounded heaps over an unbounded number of traces of unbounded length Comparison under abstraction
Outline How to construct the sequential executions? How to compare unbounded heaps under abstraction?
Outline How to construct the sequential execution? Inspired by Flanagan, SPIN’04 How to compare unbounded heaps under abstraction?
Fixed Linearization Points Every operation has a (user-specified) fixed linearization point –A 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
Verification of Fixed Linearization Points 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
Treiber's Non-Blocking Stack Top
Push Operation if (S Top == t) S Top = x; evaluate to true; else evaluate to false; Top t 7 x void push (Stack S, data_type v) { Node x = alloc(sizeof(Node)); x d = v; do { Node t = S Top; x n = t; } while ( ! CAS(&S Top, t, x) ); }
Pop Operation Top s 7 t return 7 data_type pop (Stack S) { do { Node t = S Top; if (t == NULL) return EMPTY; Node s = t n; } while ( ! CAS(&S Top, t, s) ); data_type r = t d; return r; }
Example: Conjoined Execution (1) 1 3 Top x x t t 4 x B: push(7) A: push(4) Concurrent Stack Sequential Stack Linearization Point T1T1 T2T2
Example: Conjoined Execution (2) x t Top 4 failed CAS t 7 x 7 Top x Concurrent Stack Sequential Stack Linearization Point B: push(7) A: push(4) T1T1 T2T2
Example: Conjoined Execution (3) Top 4 s 7 7 t s t matching return values A: pop() Concurrent Stack Sequential Stack Linearization Point B: push(7) A: push(4) T1T1 T2T2
Conjoined Execution Concurrent Stack Sequential Stack linearization point Top Throughout conjoined execution, two stacks remain almost isomorphic Atomic Operation
Outline How to construct the sequential execution? How to compare unbounded heaps under abstraction? Delta Abstraction
Starting Point: Canonical Abstraction [ SRW'02 ] 1 34 x 7 n n n x n n summary node
Concretization 1 34 x 7 n n n n 8 x x 3 n n n 7 n x n n summary node
Comparison of Responses Under Abstraction Top ? ? ?=?= Abstract Domain Separate abstractions will not do Concrete Domain Concurrent Stack Sequential Stack Concurrent Stack Sequential Stack Top Top
Main Idea Top t 7 x Concurrent Stack Sequential Stack track precisely abstract away Isomorphic Sub-graphs Maintain a mapping between memory layouts of concurrent and sequential data structures
Recording Isomorphism Using Correlation Relation Top All nodes are correlated Correlated nodes are similar (successors also correlated or both null) Nodes pointed-to by Top are correlated
Isomorphism Under Delta Abstraction Top similar duo-object
Isomorphism Under Delta Abstraction 7 7 Top similar duo-object similar summary duo-object Top similar Isomorphism Under Bounded Delta Abstraction
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
Conjoined Execution Under Abstraction (1) Top x x t t x B: push(7) A: push(4) Concurrent Stack Sequential Stack Linearization Point similar T1T1 T2T2
Conjoined Execution Under Abstraction (2) x t Top failed CAS t x Top x Concurrent Stack Sequential Stack Linearization Point similar B: push(7) A: push(4) T1T1 T2T2
Conjoined Execution Under Abstraction (3) Top matching return values Concurrent Stack Sequential Stack similar Partial isomorphism can be maintained under abstraction since the difference between the memory layouts is bounded A: pop() B: push(7) A: push(4) Bounded difference may be at an unbounded distance from the root T1T1 T2T2
Experimental Results [1] Treiber, '86 [2] Michael and Scott, PODC’96 [3] Doherty et al., FORTE'04 [4] Vafeiadis et al., PPoPP' , , ,000
Related Methods Manual –Rely-guarantee reasoning [Vafeiadis et al., PPoPP'06] Semi-automatic –Proving simulation relation between I/O Automata using PVS [Doherty et al., FORTE'04] Automatic –Proving atomicity of procedures [Wang and Stoller, PPoPP'05] More general
Limitations User-specified guess of fixed linearization points User-specified fixed correlation rule Fixed number of threads –Arbitrary in theory –Small in practice (scalability) Assuming memory is garbage collected Future Work
Summary A conservative automatic algorithm for verifying linearizability of unbounded linked concurrent data structures –Sequential specification –Conjoined executions Delta abstraction: A novel heap abstraction –Maintains an isomorphism between mutable linked data structures under abstraction Implementation and experimental results –Non blocking stack [Treiber, '86] –Non blocking queue [Michael and Scott, PODC’96] [Doherty et al., FORTE'04] –2 lock queue [Michael and Scott, PODC’96 ] –Set with fine grained locking [Vafeiadis et al., PPoPP'06 ]
Main Observation Comparison under abstraction of unbounded state systems may be possible when the difference between the systems is bounded
The End MSc Thesis:
Stack's Most-General Client void client (Stack S) { do { if (?) push(S, rand()); else pop(S); } while ( 1 ); }