42
QED: A Simplifier for Concurrent Programs Shaz Qadeer Microsoft Research Joint work with ayfun Elmas Ali Sezgin Serdar Tasira

QED: A Simplifier for Concurrent Programs

  • Upload
    aric

  • View
    46

  • Download
    0

Embed Size (px)

DESCRIPTION

QED: A Simplifier for Concurrent Programs. Shaz Qadeer Microsoft Research. Joint work with Tayfun ElmasAli SezginSerdar Tasiran. Reliable concurrent software?. Concurrency results in Heisenbugs non-deterministic, timing dependent data corruption, crashes - PowerPoint PPT Presentation

Citation preview

Page 1: QED: A Simplifier for Concurrent Programs

QED: A Simplifier for Concurrent Programs

Shaz Qadeer Microsoft Research

Joint work with Tayfun Elmas Ali Sezgin Serdar Tasiran

Page 2: QED: A Simplifier for Concurrent Programs

Reliable concurrent software?• Concurrency results in Heisenbugs– non-deterministic, timing dependent– data corruption, crashes– difficult to detect, reproduce, eliminate

• Correctness problem– does program behave correctly for all inputs and all interleavings?

Page 3: QED: A Simplifier for Concurrent Programs

P satisfies S

Undecidable problem!

Page 4: QED: A Simplifier for Concurrent Programs

P satisfies S

Assertions: Provide contracts to decompose problem into a collection of decidable problems• pre-condition and post-condition for each procedure• loop invariant for each loop

Page 5: QED: A Simplifier for Concurrent Programs

int t;

L0: acquire(l);

L1: t := x;

L2: t := t + 1;

L3: x := t;

L4: release(l);

L5:

pre x=c;

post x=c+2;

int t;

M0: acquire(l);

M1: t := x;

M2: t := t + 1;

M3: x := t;

M4: release(l);

M5:

A B

B@M0x=c, B@M5x=c+1

B@M0x=c, B@M5x=c+1, held(l, A)

B@M0x=c, B@M5x=c+1, held(l, A), t=x

B@M0x=c, B@M5x=c+1, held(l, A), t=x+1

B@M0x=c+1, B@M5x=c+2, held(l, A)

B@M0x=c+1, B@M5x=c+2

A@L0x=c, A@L5x=c+1

A@L0x=c, A@L5x=c+1, held(l, B)

A@L0x=c, A@L5x=c+1, held(l, B), t=x

A@L0x=c, A@L5x=c+1, held(l, B), t=x+1

A@L0x=c+1, A@L5x=c+2, held(l, B)

A@L0x=c+1, A@L5x=c+2

Invariant problem

Page 6: QED: A Simplifier for Concurrent Programs

int t;acquire(l);t := x;t := t + 1;x := t;release(l);

Abstraction problem

int t;t := x;t := t + 1;x := t;

x := x+1

??

Page 7: QED: A Simplifier for Concurrent Programs

int t;

L0: acquire(l);L1: t := x;L2: t := t + 1;L3: x := t;L4: release(l);L5:

pre x=c;

post x=c+2;

int t;

M0: acquire(l);M1: t := x;M2: t := t + 1;M3: x := t;M4: release(l);M5:

Intuitive reasoning with atomic actions

Page 8: QED: A Simplifier for Concurrent Programs

int t;

atomic { L0: acquire(l); L1: t := x; L2: t := t + 1; L3: x := t; L4: release(l);}L5:

pre x=c;

post x=c+2;

int t;

atomic { M0: acquire(l); M1: t := x; M2: t := t + 1; M3: x := t; M4: release(l);}M5:

Intuitive reasoning with atomic actions

B@M0x=c, B@M5x=c+1

B@M0x=c+1, B@M5x=c+2

A@L0x=c, A@L5x=c+1

A@L0x=c+1, A@L5x=c+2

Page 9: QED: A Simplifier for Concurrent Programs

pre x=c;

post x=c+2;

atomic { x := x + 1; }

Intuitive reasoning with atomic actions

atomic { x := x + 1; }

Page 10: QED: A Simplifier for Concurrent Programs

pre x=c;

post x=c+2;

atomic { x := x + 1; }atomic { x := x + 1; }

Intuitive reasoning with atomic actions

Verify using sequential methods!

Page 11: QED: A Simplifier for Concurrent Programs

• Do not verify the original program• Instead, simplify the program• Verify the program once it is simple enough

QED

I0,P0 I1,P1 I2,P2 I3,P3

I,PInvariant Program text

• Simplified program has simpler invariants• Abstraction of a program is another program

Page 12: QED: A Simplifier for Concurrent Programs

procedure Write(int a, int d) { atomic { m[a] := d; }}

procedure Snapshot(int a, int b, out int da, out int db) { atomic { da := m[a]; db := m[b]; }}

Atomic snapshotint[] m;

Page 13: QED: A Simplifier for Concurrent Programs

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb;

atomic { va := m[a].v; da := m[a].d; } atomic { vb := m[b].v; db := m[b].d; } s := true; atomic { if (va < m[a].v) { s := false; } } atomic { if (vb < m[b].v) { s := false; } }}

Atomic snapshotclass VersionedInteger { int v; int d; } VersionedInteger[] m;

Page 14: QED: A Simplifier for Concurrent Programs

QED-simplified atomic snapshot

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a: int, int b, out bool s, out int da, out int db) { atomic { havoc s, da, db; if (s) { da := m[a].d; db := m[b].d; } }}

class VersionedInteger { int v; int d; } VersionedInteger[] m;

Page 15: QED: A Simplifier for Concurrent Programs

QED transformations

I,P I’,P’

1. Strengthen invariant2. Reduce program3. Abstract program

Page 16: QED: A Simplifier for Concurrent Programs

Rule 1: Strengthen invariant

I,P I’,P

I’ I

Page 17: QED: A Simplifier for Concurrent Programs

Rule 2: Reduce program

atomic { A ; B }atomic { A } ; atomic { B }

I,P I,P’

Page 18: QED: A Simplifier for Concurrent Programs

S1 S2 S3acquire y

S1 T2 S3acquirey

S1 T2 S3release x

S1 S2 S3releasex

Right and left movers (Lipton 1975)

int owner;

procedure acquire() { atomic { assume owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; }}

Lock

Page 19: QED: A Simplifier for Concurrent Programs

S0 . S5R* N L*x Y. . .

S0 . S5R* N L*x Y. . .

Reduction theorem

Sequence R*;(N+); L* is atomic

Page 20: QED: A Simplifier for Concurrent Programs

Rule 3: Abstract program

atomic { A } atomic { B }

I,P I,P’

From each state x in I, if A can go to y then B can also go to y

Page 21: QED: A Simplifier for Concurrent Programs

21

QED tool

reduceabstract

.....reducecheck

[http://qed.codeplex.com]

QED

Correct

...P1 PnP2

P1

Pn

Page 22: QED: A Simplifier for Concurrent Programs

QED-verified examples• Fine-grained locking

– Linked-list with hand-over-hand locking [Herlihy-Shavit 08] – Two-lock queue [Michael-Scott 96]

• Non-blocking algorithms– Bakery [Lamport 74] – Non-blocking stack [Treiber 86]– Obstruction-free deque [Herlihy et al. 03]– Non-blocking stack [Michael 04]– Writer mode of non-blocking readers/writer lock [Krieger et al. 93] – Non-blocking queue [Michael-Scott 96] – Synchronous queue [Scherer-Lea-Scott 06]

Page 23: QED: A Simplifier for Concurrent Programs

QED transformations

I,P I’,P’

• Strengthen invariant• Abstract program• Reduce program

The rules are symbiotic:• Abstraction enables reduction• Reduction enables abstraction• Program simplification enables simpler invariants

Together these rules are surprisingly powerful!

Page 24: QED: A Simplifier for Concurrent Programs

Two examples

• Atomic snapshot– Abstraction enables reduction

• Spin lock– Program simplification yields simpler invariants

Page 25: QED: A Simplifier for Concurrent Programs

Atomic Snapshot

Page 26: QED: A Simplifier for Concurrent Programs

class VersionedInteger { int v; int d; } VersionedInteger[] m;

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb;

atomic { va := m[a].v; da := m[a].d; } atomic { vb := m[b].v; db := m[b].d; } s := true; atomic { if (va < m[a].v) { s := false; } } atomic { if (vb < m[b].v) { s := false; } }}

Page 27: QED: A Simplifier for Concurrent Programs

class VersionedInteger { int v; int d; } VersionedInteger[] m;

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb;

atomic { havoc va, da; assume va <= m[a].v; if (va == m[a].v) { da := m[a].d; } } atomic { havoc vb, db; assume vb <= m[b].v; if (vb == m[b].v) { db := m[b].d; } } s := true; atomic { if (va < m[a].v) { s := false; } if (s) { havoc s; } } atomic { if (vb < m[b].v) { s := false; } if (s) { havoc s; } }}

Left Mover

Right MoverRight Mover

Left Mover

Page 28: QED: A Simplifier for Concurrent Programs

class VersionedInteger { int v; int d; } VersionedInteger[] m;

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb;

atomic { havoc va, da; assume va <= m[a].v; if (va == m[a].v) { da := m[a].d; } havoc vb, db; assume vb <= m[b].v; if (vb == m[b].v) { db := m[b].d; } s := true; if (va < m[a].v) { s := false; } if (s) { havoc s; } if (vb < m[b].v) { s := false; } if (s) { havoc s; } }}

Page 29: QED: A Simplifier for Concurrent Programs

class VersionedInteger { int v; int d; } VersionedInteger[] m;

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a, int b, out bool s, out int da, out int db) { int va, vb;

atomic { havoc va, da, vb, db, s; if (s) { va := m[a].v; da := m[a].d; vb := m[b].v; db := m[b].d; s := true; } }}

Page 30: QED: A Simplifier for Concurrent Programs

class VersionedInteger { int v; int d; } VersionedInteger[] m;

procedure Write(int a, int d) { atomic { m[a].d := d; m[a].v := m[a].v+1; }}

procedure Snapshot(int a, int b, out bool s, out int da, out int db) { atomic { havoc da, db, s; if (s) { da := m[a].d; db := m[b].d; } }}

Hide va, vb

Page 31: QED: A Simplifier for Concurrent Programs

Spin Lock

Page 32: QED: A Simplifier for Concurrent Programs

bool held;

procedure acquire() { while (true) { if (CAS(held, false, true)) { break; } }}

procedure release() { held := false;}

int owner;

procedure acquire() { atomic { assume owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; }}

Page 33: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { while (true) { if (CAS(held, false, true)) { owner := tid; break; } }}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Page 34: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { while (*) { assume held != false; } atomic { assume held == false; held := true; } owner := tid;}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Page 35: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { while (*) { assume true; } atomic { assume held == false; held := true; } owner := tid;}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Page 36: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { atomic { assume held == false; held := true; } owner := tid;}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Page 37: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { atomic { assume held == false; held := true; } atomic { assert owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Left Mover

(Not Quite) Invariant: owner == 0 held == false

Page 38: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { atomic { assume held == false; held := true; assert owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Page 39: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { atomic { assume held == false; held := true; assert owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Invariant: owner == 0 held == false

Page 40: QED: A Simplifier for Concurrent Programs

bool held;int owner;

procedure acquire() { atomic { assume held == false; held := true; assume owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; held := false; }}

Page 41: QED: A Simplifier for Concurrent Programs

int owner;

procedure acquire() { atomic { assume owner == 0; owner := tid; }}

procedure release() { atomic { assert owner == tid; owner := 0; }}

Hide held

Page 42: QED: A Simplifier for Concurrent Programs

Conclusions

• QED: A simplifier for concurrent programs– Do not verify the original program– Instead, simplify the program– Verify the program once it is simple enough

• Other applications– Concurrency testing – Programmer-assisted parallelization