qed a simplifier for concurrent programs
Download
Skip this Video
Download Presentation
QED: A Simplifier for Concurrent Programs

Loading in 2 Seconds...

play fullscreen
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?
slide3

Undecidable problem!

P satisfies S

slide4

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:

[email protected]x=c,[email protected]x=c+1

[email protected]x=c, [email protected]x=c+1

[email protected]x=c,[email protected]x=c+1,

held(l, A)

[email protected]x=c, [email protected]x=c+1,

held(l, B)

[email protected]x=c,[email protected]x=c+1,

held(l, A), t=x

[email protected]x=c, [email protected]x=c+1,

held(l, B), t=x

[email protected]x=c,[email protected]x=c+1,

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

[email protected]x=c, [email protected]x=c+1,

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

[email protected]x=c+1,[email protected]x=c+2,

held(l, A)

[email protected]x=c+1, [email protected]x=c+2,

held(l, B)

[email protected]x=c+1,[email protected]x=c+2

[email protected]x=c+1, [email protected]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:

[email protected]x=c,[email protected]x=c+1

[email protected]x=c, [email protected]x=c+1

[email protected]x=c+1,[email protected]x=c+2

[email protected]x=c+1, [email protected]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!

slide11
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
slide26

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

}

slide27

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

slide28

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

}

}

slide29

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;

}

}

}

slide30

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

slide32

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;

}

}

slide33

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;

}

}

slide34

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;

}

}

slide35

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;

}

}

slide36

bool held;

int owner;

procedure acquire() {

atomic { assume held == false; held := true; }

owner := tid;

}

procedure release() {

atomic {

assert owner == tid; owner := 0;

held := false;

}

}

slide37

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

slide38

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;

}

}

slide39

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

slide40

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;

}

}

slide41

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
ad