automatically proving linearizability
play

Automatically proving linearizability Viktor Vafeiadis University - PowerPoint PPT Presentation

Automatically proving linearizability Viktor Vafeiadis University of Cambridge CAV 2010 M&S non-blocking queue head tail null X 1 2 3 4 typedef struct Node_s *Node; struct Queue_s *Q; struct Node_s { init() { int val; n = new


  1. Automatically proving linearizability Viktor Vafeiadis University of Cambridge CAV 2010

  2. M&S non-blocking queue head tail null X 1 2 3 4 typedef struct Node_s *Node; struct Queue_s *Q; struct Node_s { init() { int val; n = new Node(); Node next; n → next = null; } Q = new Queue(); Q → head = node; struct Queue_s { Q → tail = node; Node head; } Node tail; }

  3. Linearizability Every method executes ‘atomically’ & obeys a functional correctness specification Shared variable: AQ enqueue(v) spec AQ := append(singleton(v), AQ); return 0; dequeue() spec if (AQ == empty) { return EMPTY; } else { r := hd(AQ); AQ := tl(AQ); return r; }

  4. Linearizability & forward simulation Linearizability: The implementation (of every method) is a refinement of an atomic specification. Standard proof technique: forward simulation Abstract (spec) S abs S’ abs Concrete (impl) S conc S’ conc

  5. Linearization points The implementation is a refinement of an atomic specification. abstract execution concrete execution linearization point (LP)

  6. Linearization point of enqueue enqueue(v) { m := new Node(); m → val := v; m → next := null; while (true) { t := Q → tail; n := tail → next; if (Q → tail ≠ tail) continue ; if (n == null) { Lin. Point if (CAS(&t → next,n,m)) break; (provided CAS succeeds) } else { CAS(&Q → tail,t,n); } } CAS(&Q → tail,t,n); }

  7. Proof search for the LP ?  For each execution path of each method, choose a candidate LP  Check whether it is a valid LP Does this work ?

  8. Proof search for the LP ?  For each execution path of each method, choose a candidate LP  Check whether it is a valid LP Does this work ? Not quite. 1. LPs can be conditional 2. LPs can be in the code of another thread

  9. LP of dequeue, when it returns EMPTY dequeue () { while (true) { h := Q → head; t := Q → tail; n := h → next; LP provided if (Q → tail ≠ t) this test fails, and continue ; the h==t test succeeds if (h == t) { the n==null test succeeds if (n == null) return EMPTY; CAS(&Q → tail,t,n); } else { if (CAS(&Q → head,h,n)) Condition: return n → val; } ¬prophecy(Q → tail ≠ t) } ∧ h == t } ∧ n == null

  10. Key observation  Method executions that logically modify the state have a simple LP.  Method executions that do not logically modify the state often have a complex LP. So: Treat these two cases differently.  Search for LPs of executions that logically modify the state;  Do a non-constructive proof for executions that do not logically modify the state.

  11. Basic LP validation Auxiliary variable: lres 1. At the entry to the function: lres := UNDEF; 2. At the candidate e fg ectful LPs: assert( lres ==UNDEF); lres := method_spec(); 3. At the return points, check res == lres concrete abstract result result

  12. Validating pure executions Auxiliary variable: can_return 1. At the entry to the function: ∀ i. can_return [i] := false; 2. At every point, add a pure ‘LP checker’: if (abs_method() has no side-e fg ects) can_return [abs_method()] := true; 3. At the return points, check can_return [res] == true concrete result

  13. For example... dequeue spec if (AQ == empty) { return EMPTY; } else { r := hd(AQ); AQ := tl(AQ); return r; } pure lin. checker if (AQ == empty) { can_return [EMPTY] := true; }

  14. Enhanced LP validation Auxiliary variables: lres , can_return 1. At the entry to the function: lres := UNDEF; ∀ i. can_return [i] := false; 2. At the candidate e fg ectful LPs: assert( lres= =UNDEF); lres := abs_method() 3. Add pure checkers at every program point: assign can_return [i] := true if method_spec returns i & has no side-e fg ects. 4. At the return points, check (res== lres ) ∨ ( lres ==UNDEF ∧ can_return [res])

  15. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } null -INF 1 3 7 +INF contains(5) || add(5); remove(3); remove(5)

  16. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } null -INF 1 3 7 +INF c contains(5) || add(5); remove(3); remove(5)

  17. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } null -INF 1 3 7 +INF c contains(5) || add(5); remove(3); remove(5)

  18. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } null -INF 1 3 7 +INF c contains(5) || add(5); remove(3); remove(5)

  19. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } null -INF 1 3 5 7 +INF c contains(5) || add(5); remove(3); remove(5)

  20. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } 3 null -INF 1 5 7 +INF c contains(5) || add(5); remove(3); remove(5)

  21. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } 5 3 null -INF 1 7 +INF c contains(5) || add(5); remove(3); remove(5)

  22. LPs in other threads add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c → val < e) c := c → next; return (c → val == e); } 5 3 null -INF 1 7 +INF c contains(5) || add(5); remove(3); remove(5)

  23. Enhanced LP validation Auxiliary variables: lres , can_return 1. At the entry to the function: lres := UNDEF; ∀ i. can_return [i] := false; 2. At the candidate e fg ectful LPs: assert( lres= =UNDEF); lres := abs_method() 3. Add pure checkers at every program point (incl. program points in other threads) 4. At the return points, check (res== lres ) ∨ ( lres ==UNDEF ∧ can_return [res])

  24. Experiments (linearizability) Algorithm Lines Ops E fg Pure LpO Time (s) DCAS stack 100 8 4 5 0 0.3 Treiber stack 100 8 4 5 0 0.3 M&S two-lock queue 85 4 3 2 0 16.5 M&S non-blocking queue 127 4 3 2 0 4.9 DGLM non-blocking queue 126 4 3 2 0 7.6 Pessimistic set 100 3 2 3 0 247.8 V&Y DCAS-based set 101 3 2 3 0 51.0 ORVYY lazy set 94 3 2 3 1 521.5 Lines: lines of code: excluding comments & specs Ops: # methods E fg : # e fg ectful methods Pure: # methods with a pure execution path LpO: # linearization points in other threads

  25. Summary & future work  Observation: E fg ectful LPs are usually simple  Technique: Search for e fg ectful LPs Try all possible pure LPs at once  Challenges ahead: Memory management More complicated data structures (e.g. skip lists)

Recommend


More recommend