Qed a simplifier for concurrent programs
Download
1 / 42

QED: A Simplifier for Concurrent Programs - PowerPoint PPT Presentation


  • 130 Views
  • Uploaded on

QED: A Simplifier for Concurrent Programs. Shaz Qadeer Microsoft Research. Joint work with Tayfun Elmas Ali Sezgin Serdar Tasiran. Reliable concurrent software?. Concurrency results in Heisenbugs non-deterministic, timing dependent data corruption, crashes

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'QED: A Simplifier for Concurrent Programs' - aric


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
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


Reliable concurrent software
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 allinputs and allinterleavings?


Qed a simplifier for concurrent programs

Undecidable problem!

P satisfies S


Qed a simplifier for concurrent programs

  • 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

P satisfies S


Invariant problem
Invariant problem

  • pre x=c;

A

B

int t;

L0: acquire(l);

L1: t := x;

L2: t := t + 1;

L3: x := t;

L4: release(l);

L5:

int t;

M0: acquire(l);

M1: t := x;

M2: t := t + 1;

M3: x := t;

M4: release(l);

M5:

B@M0x=c,B@M5x=c+1

A@L0x=c, A@L5x=c+1

B@M0x=c,B@M5x=c+1,

held(l, A)

A@L0x=c, A@L5x=c+1,

held(l, B)

B@M0x=c,B@M5x=c+1,

held(l, A), t=x

A@L0x=c, A@L5x=c+1,

held(l, B), t=x

B@M0x=c,B@M5x=c+1,

held(l, A), t=x+1

A@L0x=c, A@L5x=c+1,

held(l, B), t=x+1

B@M0x=c+1,B@M5x=c+2,

held(l, A)

A@L0x=c+1, A@L5x=c+2,

held(l, B)

B@M0x=c+1,B@M5x=c+2

A@L0x=c+1, A@L5x=c+2

  • post x=c+2;


Abstraction problem
Abstraction problem

int t;

t := x;

t := t + 1;

x := t;

x := x+1

int t;

acquire(l);

t := x;

t := t + 1;

x := t;

release(l);

??


Intuitive reasoning with atomic actions
Intuitive reasoning with atomic actions

  • pre x=c;

int t;

L0: acquire(l);

L1: t := x;

L2: t := t + 1;

L3: x := t;

L4: release(l);

L5:

int t;

M0: acquire(l);

M1: t := x;

M2: t := t + 1;

M3: x := t;

M4: release(l);

M5:

  • post x=c+2;


Intuitive reasoning with atomic actions1
Intuitive reasoning with atomic actions

  • pre x=c;

int t;

atomic {

L0: acquire(l);

L1: t := x;

L2: t := t + 1;

L3: x := t;

L4: release(l);

}

L5:

int t;

atomic {

M0: acquire(l);

M1: t := x;

M2: t := t + 1;

M3: x := t;

M4: release(l);

}

M5:

B@M0x=c,B@M5x=c+1

A@L0x=c, A@L5x=c+1

B@M0x=c+1,B@M5x=c+2

A@L0x=c+1, A@L5x=c+2

  • post x=c+2;


Intuitive reasoning with atomic actions2
Intuitive reasoning with atomic actions

  • pre x=c;

atomic { x := x + 1; }

atomic { x := x + 1; }

  • post x=c+2;


Intuitive reasoning with atomic actions3
Intuitive reasoning with atomic actions

  • pre x=c;

atomic { x := x + 1; }

atomic { x := x + 1; }

  • post x=c+2;

Verify using sequential methods!


Qed a simplifier for concurrent programs
QED

  • Do not verify the original program

  • Instead, simplify the program

  • Verify the program once it is simple enough

I,P

Invariant

Program text

I0,P0

I1,P1

I2,P2

I3,P3

  • Simplified program has simpler invariants

  • Abstraction of a program is another program


Atomic snapshot
Atomic snapshot

int[] m;

procedure Write(int a, int d) {

atomic { m[a] := d; }

}

procedure Snapshot(int a, int b, out int da, out intdb) {

atomic { da := m[a]; db := m[b]; }

}


Atomic snapshot1
Atomic snapshot

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 intdb) {

intva, 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; } }

}


Qed simplified atomic snapshot
QED-simplified atomic snapshot

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, int b, out bool s, out int da, out intdb) {

atomic {

havoc s, da, db;

if (s) { da := m[a].d; db := m[b].d; }

}

}


Qed transformations
QED transformations

I,P

I’,P’

Strengthen invariant

Reduce program

Abstract program


Rule 1 strengthen invariant
Rule 1: Strengthen invariant

I,P

I’,P

I’  I


Rule 2 reduce program
Rule 2: Reduce program

I,P

I,P’

atomic { A} ; atomic { B }

atomic { A ; B }


Right and left movers lipton 1975

x

release

S1

S2

S3

release

x

S1

T2

S3

acquire

y

S1

S2

S3

y

acquire

S1

T2

S3

Right and left movers (Lipton 1975)

Lock

int owner;

procedure acquire() {

atomic {

assume owner == 0;

owner := tid;

}

}

procedure release() {

atomic {

assert owner == tid;

owner := 0;

}

}


Reduction theorem

R*

.

x

.

N

.

Y

.

L*

S0

S5

R*

.

.

.

Y

x

.

N

L*

S0

S5

Reduction theorem

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


Rule 3 abstract program
Rule 3: Abstract program

I,P

I,P’

atomic { A }

atomic { B }

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


Qed tool
QED tool

[http://qed.codeplex.com]

P1

P2

Pn

P1

...

QED

Correct

Pn

reduce

abstract

.....

reduce

check


Qed verified examples
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 [Treiber86]

    • 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]


Qed transformations1
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!


Two examples
Two examples

  • Atomic snapshot

    • Abstraction enables reduction

  • Spin lock

    • Program simplification yields simpler invariants



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 intdb) {

intva, 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; } }

}


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 intdb) {

intva, 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; } }

}

Right Mover

Right Mover

Left Mover

Left Mover


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 intdb) {

intva, 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; }

}

}


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 intdb) {

intva, 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;

}

}

}


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 intdb) {

atomic {

havoc da, db, s;

if (s) {

da := m[a].d;

db := m[b].d;

}

}

}

Hide va, vb



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;

}

}


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;

}

}


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;

}

}


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;

}

}


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;

}

}


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


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;

}

}


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


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;

}

}


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


Conclusions
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