Automatically proving linearizability Viktor Vafeiadis University - - PowerPoint PPT Presentation

automatically proving linearizability
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 1

Automatically proving linearizability

Viktor Vafeiadis

University of Cambridge

CAV 2010

slide-2
SLIDE 2

M&S non-blocking queue

X 1 3 4

null

2 head tail

typedef struct Node_s *Node; struct Node_s { int val; Node next; } struct Queue_s { Node head; Node tail; } struct Queue_s *Q; init() { n = new Node(); n→next = null; Q = new Queue(); Q→head = node; Q→tail = node; }

slide-3
SLIDE 3

Linearizability

Every method executes ‘atomically’ & obeys a functional correctness specification Shared variable: AQ

AQ := append(singleton(v), AQ); return 0; if (AQ == empty) { return EMPTY; } else { r := hd(AQ); AQ := tl(AQ); return r; } dequeue() spec enqueue(v) spec

slide-4
SLIDE 4

Linearizability & forward simulation

Linearizability: The implementation (of every method) is a refinement

  • f an atomic specification.

Standard proof technique: forward simulation Abstract (spec) Concrete (impl)

Sconc S’conc Sabs S’abs

slide-5
SLIDE 5

Linearization points

The implementation is a refinement of an atomic specification.

abstract execution concrete execution

linearization point (LP)

slide-6
SLIDE 6

Linearization point of enqueue

  • Lin. Point

(provided CAS succeeds)

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) { if (CAS(&t→next,n,m)) break; } else { CAS(&Q→tail,t,n); } } CAS(&Q→tail,t,n); }

slide-7
SLIDE 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 ?

slide-8
SLIDE 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
slide-9
SLIDE 9

LP of dequeue, when it returns EMPTY

LP provided

this test fails, and the h==t test succeeds the n==null test succeeds

Condition:

¬prophecy(Q→tail ≠ t)

∧ h == t ∧ n == null dequeue () { while (true) { h := Q→head; t := Q→tail; n := h→next; if (Q→tail ≠ t) continue; if (h == t) { if (n == null) return EMPTY; CAS(&Q→tail,t,n); } else { if (CAS(&Q→head,h,n)) return n→val; } } }

slide-10
SLIDE 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.

slide-11
SLIDE 11

Basic LP validation

Auxiliary variable: lres

  • 1. At the entry to the function:

lres := UNDEF;

  • 2. At the candidate efgectful LPs:

assert(lres==UNDEF); lres := method_spec();

  • 3. At the return points, check

res == lres concrete result abstract result

slide-12
SLIDE 12

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-efgects) can_return[abs_method()] := true;

  • 3. At the return points, check

can_return[res] == true

Validating pure executions

concrete result

slide-13
SLIDE 13

For example...

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

slide-14
SLIDE 14

Auxiliary variables: lres, can_return

  • 1. At the entry to the function:

lres := UNDEF; ∀i. can_return[i] := false;

  • 2. At the candidate efgectful 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-efgects.

  • 4. At the return points, check

(res==lres) ∨ (lres==UNDEF ∧ can_return[res])

Enhanced LP validation

slide-15
SLIDE 15

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 +INF

null

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-16
SLIDE 16

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-17
SLIDE 17

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-18
SLIDE 18

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-19
SLIDE 19

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 5 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-20
SLIDE 20

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 5 3 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-21
SLIDE 21

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 5 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-22
SLIDE 22

LPs in other threads

add (e) { ... } remove (e) { ... } contains (e) { c := H; while (c→val < e) c := c→next; return (c→val == e); }

1 7 3 5 +INF

null

c

  • INF

contains(5) || add(5); remove(3); remove(5)

slide-23
SLIDE 23

Auxiliary variables: lres, can_return

  • 1. At the entry to the function:

lres := UNDEF; ∀i. can_return[i] := false;

  • 2. At the candidate efgectful 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])

Enhanced LP validation

slide-24
SLIDE 24

Experiments (linearizability)

Algorithm Lines Ops Efg Pure LpO Time (s) DCAS stack 100 8 4 5 0.3 Treiber stack 100 8 4 5 0.3 M&S two-lock queue 85 4 3 2 16.5 M&S non-blocking queue 127 4 3 2 4.9 DGLM non-blocking queue 126 4 3 2 7.6 Pessimistic set 100 3 2 3 247.8 V&Y DCAS-based set 101 3 2 3 51.0 ORVYY lazy set 94 3 2 3 1 521.5

Lines: lines of code: excluding comments & specs Ops: # methods Efg: # efgectful methods Pure: # methods with a pure execution path LpO: # linearization points in other threads

slide-25
SLIDE 25

Summary & future work

  • Observation:

Efgectful LPs are usually simple

  • Technique:

Search for efgectful LPs Try all possible pure LPs at once

  • Challenges ahead:

Memory management More complicated data structures (e.g. skip lists)