1 / 39

Runtime Refinement Checking of Concurrent Data Structures (the VYRD project)

Runtime Refinement Checking of Concurrent Data Structures (the VYRD project). Serdar Tasiran Ko ç University, Istanbul, Turkey Shaz Qadeer Microsoft Research, Redmond, USA. The Problem. Given a specification for a data structure high-level, executable sequential, with atomic operations

Download Presentation

Runtime Refinement Checking of Concurrent Data Structures (the VYRD project)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Runtime Refinement Checking of Concurrent Data Structures(the VYRD project) Serdar Tasiran Koç University, Istanbul, TurkeyShaz Qadeer Microsoft Research, Redmond, USA

  2. The Problem • Given • a specification for a data structure • high-level, executable • sequential, with atomic operations • an implementation • concurrent • not atomic • not necessarily linearizable • may have race conditions • Verify that • (All) executions of the implementation are consistent with the specification

  3. Why runtime verification? • Static techniques • Must reason about entire state space of implementation • Theorem proving techniques: • Need representation invariant for implementation • Difficult for multi-threaded implementations • Compositional methods • Better-suited for correctness proofs • We want to catch concurrency bugs • Proofs difficult in practice • Need abstract model for each component’s environment • Coordination of proof sub-tasks difficult for large programs • Runtime verification • No need for component environment abstractions • Gives up exhaustiveness, but can handle practical programs

  4. Outline • Preliminaries • Atomicity • Refinement • I/O refinement • The multiset example • Checking I/O refinement • Improving I/O refinement • Comparison with other correctness criteria

  5. Semantics: State Transition Systems • A set of program variables • The set of program states • A transition function • Given • current state • action performed specifies next state • Actions • Visible: e.g. method calls, returns • Invisible: e.g. updates to method local variables

  6. More preliminaries • Call action: (thread, “Call”, methodName, args) • Return action: (thread, “Return”, methodName, rets) • A run • Corresponding trace: The sequence of visible actions along the run 2 3 … n-1 1 2 3 n-1 n s0 s1 s2 . . . Sn-1 sn

  7. Well-formed atomic traces • No visible actions by any other thread or by another method between matching “call” and “return” actions Call2 c0 c1 Return2 Call0 a0 a1 Return0 Call1 b0 Return1 Matching call and return Matching call and return Matching call and return

  8. Well-formed atomic traces Call2 c0 c1 Return2 Call0 a0 a1 Return0 Call1 b0 Return1 Atomicfragment Call0 Return0 Fragment signature

  9. Determinism • Recall: Return action contains return value • Atomic state transition system deterministic iff • same initial state and • same fragment signature imply same final state • We require specs to be atomic and deterministic Call0 Return0 Fragment signature

  10. Outline • Preliminaries • Atomicity • Refinement • I/O refinement • The multiset example • Checking I/O refinement • Improving I/O refinement • Comparison with other correctness criteria

  11. Refinement • “Projection of traces (visible actions) to application threads match” • S: State transition system for specification • I: State transition system for implementation • I refines S iff for every trace I of I, there is a trace S of S such that, for every application thread t I|t = S|t

  12. Refinement Specification traceS Call2 c0 c1 Return2 Call0 a0 a1 Return0 Call1 b0 Return1 Implementation traceI Call2 c0 c1 Return2 Call1 Return1 Call0 a1 b0 Return0 a0

  13. I/O Refinement • Refinement: ISI|t = S|t • Notion of refinement: Choice of what actions are visible I/O Refinement: • Define only “call” and “return” actions as visible •  sequence of calls and returns in the implementation  a spec run in with matching calls and return values • Spec atomic and deterministic • Spec run gives a linear order of method executions • Called “witness interleaving” • Practical issue: Too many possible interleavings • Idea: Infer witness interleaving from runtime analysis

  14. Commit actions and witness interleavings Specification traceS Call2 c0 c1 Return2 Call0 a0 a1 Return0 Call1 b0 Return1 Implementation traceI Call2 c0 c1 Return2 a1 b0 Return0 Call0 Call1 a0 Return1 Commitaction Commitaction Commitaction

  15. Commit action • Intuition: • The first line of code that makes visible to other threads the modified view of the data structure state • Ordering of commit actions: Application’s view of ordering of operations • Can be seen as simplified way to construct abstraction map • User specifies line of code that corresponds to the commit action

  16. Outline • Preliminaries • Atomicity • Refinement • I/O refinement • The multiset example • Checking I/O refinement • Improving I/O refinement • Comparison with other correctness criteria

  17. Example: Multiset • Multiset data structure • Two operations • INSERTPAIR(x,y) • If it succeeds, inserts integers x and y into the multiset • If it fails, it leaves multiset unmodified • LOOKUP(x) • Returns true iff x is in the multiset

  18. Multiset Specification INSERTPAIR(x,y) status  success or failure if (status = success) M  M U {x,y} return status LOOKUP(x) return (x  M) • INSERTPAIR allows non-deterministic failure or success • Makes choice visible via return value

  19.    content valid     Multiset Implementation • Implementation uses array to represent multiset • Only elements with valid bit set to “true” in multiset 1 2 3 4 A

  20.    5 5 7 7 content valid A         Multiset Implementation  LOOKUP(x) for i  1 to n ACQUIRE(L[i]) if (A[i].valid and A[i].content = x) RELEASE(L[i]) return true else RELEASE(L[i]) returnfalse  content A valid

  21. Implementation helper method: FindSlot(x) FINDSLOT(x) for i  1 to n ACQUIRE(L[i]) if (A[i].content = null) A[i].content = x RELEASE(L[i]) return i else RELEASE(L[i]) return 0; • Finds free slot in array to insert x • Returns index if slot found • Returns 0 otherwise

  22.         5 5 5 5 7 7 7 content content content content valid valid valid valid A A A A                 Multiset Implementation INSERTPAIR(x,y) i  FINDSLOT(x) if (i=0) returnfailure j  FINDSLOT(y) if (j=0) A[i].content  null returnfailure ACQUIRE(L[i]) ACQUIRE(L[j]) A[i].valid  true A[j].valid  true RELEASE(L[i]) RELEASE(L[j]) returnsuccess;

  23. INSERTPAIR(x,y) i  FINDSLOT(x) if (i=0) returnfailure j  FINDSLOT(y) if (j=0) A[i].content  null returnfailure ACQUIRE(L[i]) ACQUIRE(L[j]) A[i].valid  true A[j].valid  true RELEASE(L[i]) RELEASE(L[j]) returnsuccess; LOOKUP(x)  LOOKUP(y)  Commit LOOKUP(x)  LOOKUP(y) 

  24. Outline • Preliminaries • Atomicity • Refinement • I/O refinement • The multiset example • Checking I/O refinement • Improving I/O refinement • Comparison with other correctness criteria

  25. Runtime Checking of I/O Refinement • Spec atomic and deterministic • Given a sequence of method calls and return values,there is at most one run • Checking procedure: • Execute implementation • Record • order of commit points • method calls and return values • Execute spec methods in the order they committed • Check fails if spec is not able to execute method with given return value

  26. Runtime Checking of I/O Refinement • I/O refinement check may fail because • Implementation is wrong • The selection of commit points is wrong • Can tell which is the case by comparing witness interleaving with implementation trace Improves testing: • In multi-threaded tests, without witness interleaving, difficult to decide expected return value of method or final state at end of test • Must consider all interleavings, or • Forced to be too permissive

  27. Off-line checking using a log • Avoid overhead and concurrency impact • Write actions of implementation into log • Verification: Separate thread • Only reads from the log • Log: Sequence of visible actions and commit actions • Actions appear in log in the order they happen in implementation • Logged actions (not operations) serialized by log • Initial part of log in memory •  Low impact of contention for log • Must perform action atomically with log entry insertion • Optimizations possible

  28. Outline • Preliminaries • Atomicity • Refinement • I/O refinement • The multiset example • Checking I/O refinement • Improving I/O refinement • Comparison with other correctness criteria

  29. Improving I/O refinement • Why: • Test program may not perform “observations” frequently enough • Inserting them may affect concurrency too much • Observations may not get interleaved at the most interesting places • Example: If a multiset test program does no LookUp’s, all I/O refinement tests will pass

  30. Improving I/O refinement: The “view” • Include a state-based condition into the definition of refinement • Define auxiliary, hypothetical variable “view” • Both spec and implementation have their copy of view • User indicates how view gets updated in both • view represents only the “abstract state” of the data structure • Abstract away information not relevant to data structure state • From both spec and implementation • Method return values determined uniquely by view • Initialized to same value in spec and implementation • In spec: Updated once, atomically between call and return • In implementation: Updated once, atomically with commit action • During runtime checking, check that views match for each method

  31. Definition of view for multiset • Spec’s definition of view: • Contents of multiset in spec • Implementation’s definition of view: • Computed atomically with commit action view   for i  1 to n lockOK = (L[i] not held by any thread) or (L[i] held by thread currently committing) or (L[i] held by thread executing LOOKUP) if (A[i].valid or lockOK) view  view U {A[i].content}

  32. Off-line checking for view • Implementation’s version of view constructed from log, off-line • Must log all variable updates that affect view • can look forward in log, past commit action, to compute view for implementation • May have to log certain lock acquisitions and releases in log • Compute, compare view incrementally for efficiency • Overhead, impact on concurrency increases • But programs we are working on keep similar logs for recovery purposes anyway • Performance overhead tolerable for these

  33. What does view buy? • Examining program and spec state provides more observability • Imagine multiset with REMOVE operation • Suppose application executes INSERTPAIR(a,a) • But implementation erroneously inserts a once • To expose this error through I/O refinement or testing, error must show up in return value of LOOKUP(a) • Need execution that • inserts a pair of a’s when there are no a’s in the multiset • removes a • looks “a” up • before more a’s get inserted • Checking view catches bug right after INSERTPAIR(a,a)

  34. Non-trivial spec view • Imagine multiset spec given as a binary search tree • Executable spec contains detail not part of abstract data structure state • Must abstract structure of search tree • view just takes union of tree node contents • Abstracts away parent-child, left-right relationships

  35. Outline • Preliminaries • Atomicity • Refinement • I/O refinement • The multiset example • Checking I/O refinement • Improving I/O refinement • Comparison with other correctness criteria

  36. Multiset is not atomic INSERTPAIR(x,y) i  FINDSLOT(x) if (i=0) returnfailure j  FINDSLOT(y) if (j=0) A[i].content  null returnfailure ACQUIRE(L[i]) ACQUIRE(L[j]) A[i].valid  true A[j].valid  true RELEASE(L[i]) RELEASE(L[j]) returnsuccess; • Not possible to re-order different threads’ executions of FINDSLOT

  37. Multiset has a race condition INSERTPAIR(x,y) i  FINDSLOT(x) if (i=0) returnfailure j  FINDSLOT(y) if (j=0) A[i].content  null returnfailure ACQUIRE(L[i]) ACQUIRE(L[j]) A[i].valid  true A[j].valid  true RELEASE(L[i]) RELEASE(L[j]) returnsuccess; LOOKUP(x) for i  1 to n ACQUIRE(L[i]) if (A[i].valid and A[i].content = x) RELEASE(L[i]) return true else RELEASE(L[i]) returnfalse

  38.  FINDSLOT(1) by t1 succeeds content   valid FINDSLOT(5) by t2 succeeds  content content content 1 1 1 5 5       valid valid valid Multiset is not linearizable • thread t1 executing INSERTPAIR(1,2) concurrently with thread t2 executing INSERTPAIR(5,6) FINDSLOT(2),INSERTPAIR(1,2) by t1 fail FINDSLOT(6),INSERTPAIR(5,6) by t2 fail • No linearized execution of implementation fails first call to INSERTPAIR(5,6) • Multiset implementation not linearizable

  39. Conclusions, future work • Run-time refinement checking a promising approach • Caught artificial bugs in Multiset • Caught real bugs in Scan file system for WindowsNT • In the process of applying it to Boxwood • A concurrent implementation of a B-link tree • When no formal, executable spec exists, we use “atomic version” of implementation as spec • Lowers barrier to application of refinement-based methods • Concentrates on concurrency bugs

More Related