java pathrelaxer : extending jpf for jmm-aware model checking

Post on 22-Mar-2016

62 Views

Category:

Documents

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

Java PathRelaxer : Extending JPF for JMM-Aware Model Checking. Huafeng Jin, Tuba Yavuz-Kahveci , and Beverly Sanders Computer and Information Science and Engineering University of Florida. Contents. Memory Model The Java Memory Model Algorithm Implementation Experience Conclusion. - PowerPoint PPT Presentation

TRANSCRIPT

Java PathRelaxer: Extending JPF for JMM-Aware Model Checking

Huafeng Jin, Tuba Yavuz-Kahveci, and Beverly SandersComputer and Information Science and Engineering

University of Florida

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

Specifies “which value each read of a memory location may return”.

Sequentially consistent (SC) memory model Memory actions must execute one at a time in

a single total single order Read always see the value of the most recent

write to that memory location. Relaxed memory models

PSO, TSO, Java Memory Model (JMM), etc.

Memory Model

Specifies “which value each read of a memory location may return”.

Sequentially consistent (SC) memory model Memory actions must execute one at a time in

a single total single order Read always see the value of the most recent

write to that memory location. Relaxed memory models

PSO, TSO, Java Memory Model (JMM), etc.

Memory Model

JPF assumes SC memory model

Example

Intially, x = 0, done = false

SCMM r == 1

Thread-1 Thread-2x = 1;

done = true;

while (!done){/*spin*/}

r = x;

Example

Intially, x = 0, done = false

Thread-1 Thread-2x = 1;

done = true;

while (!done){/*spin*/}

r = x;

SCMM r == 1

JMM r == 0 ˅ r == 1

Java’s String class

public final class String{ private final char value[]; private final int offset; private final int count; private int hash; //default 0 … public int hashCode(){ int h = hash, len = count; //read of hash if (h == 0 && len > 0){

… /*calculate hash code locally and assign to h*/hash = h; //write of hash

} return h; }}

Data race is benign in both SC MM and JMM

Another Version

public final class String{ private final char value[]; private final int offset; private final int count; private int hash; //default 0 … public int hashCode(){ int h = hash, len = count; //read of hash if (h == 0 && len > 0){

… /*calculate hash code locally and assign to h*/hash = h; //write of hash

} h = hash; //read of hash return h; }}

Benign in SC MM but not benign in JMM

Another Version

public final class String{ private final char value[]; private final int offset; private final int count; private int hash; //default 0 … public int hashCode(){ int h = hash, len = count; //read of hash if (h == 0 && len > 0){

… /*calculate hash code locally and assign to h*/hash = h; //write of hash

} h = hash; //read of hash return h; }}

Benign in SC MM but not benign in JMM

Return hash code

or 0

JPF: generates executions under SC memory model.

JPR: generates executions under an overapproximation of JMM.

Extending JPF

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

SC memory model: Read sees most recent write to that location.

Java memory model: Read sees any write (past/future) to that

location provided the execution is Well-formed Meets causality constraints

Overview of JMM

Action (memory related) <t, k, v, u>

Non-synchronization actions: non-volatile write, non-volatile read

Synchronization actions: volatile write, volatile read, lock, unlock, thread start, thread join, …

JMM Action

t Thread ID

k Action kind (volatile read/write, non-volatile read/write, lock/unlock, thread start, thread join …)

v Variable/monitor

u Unique action ID

Execution E <A, P, ≤po, ≤so, W, V>

JMM Execution

A Finite set of actionsP Program

≤po Program order, a partial order over A based on each thread’s sequence.

≤so Synchronization order, a total order over all the synchronization actions in A

W Write-seen function, maps each read action to the write action it sees

V Value-written function, maps each write action to the value it writes

A partial order over actions with regard to ≤so

Synchronizes-with Order ≤sw

unlock(x)

≤sw

subsequent lock(x)volatile write(x) subsequent volatile read(x)start thread t 1st action of thread tWrite of default value 1st action in each thread

A partial order over actions by taking transitive closure of ≤po and ≤sw

Initially, x == 0 done == false, done is volatile⋀

Happens-before Order ≤hb

Thread-1 Thread-2x = 1;

done = true

while (!done){/*spin*/}

r = x;

≤po

≤po

≤sw

≤sw

≤sw

Thread-1 Thread-2x = 1;

done = true

while (!done){/*spin*/}

r = x;

A partial order over actions by taking transitive closure of ≤po and ≤sw

Initially, x == 0 done == false, done is volatile⋀

Happens-before Order ≤hb

≤po

≤po

≤sw

≤sw

≤sw

≤hb

In an execution

Data Race

Thread-1: …

Write

Thread-2: …

Read

x

≤hb

≤hb

A program: If all the SC executions are free of

data races, it is Data-Race-Free program (DRF).

DRF Guarantee: Any legal execution of DRF program is SC.

Data Race Free

For all reads r of variable v, it cannot be

r ≤hb W(r)

W(r) ≤hb w ≤hb r (w writes to v)

Well-formed Execution

r can only be 1, not 0Initially, x == 0 done == false, done is volatile⋀

Example

Thread-1 Thread-2x = 1;

done = true

while(!done) {/*spin*/}

r = x;

≤po

≤po

≤sw

≤sw

≤swIf read x = 0, then there is an interleaving writex = 1.

An execution E <A, P, ≤po, ≤so, W, V> with ≤hb is legal if there is a finite sequence of set of actions Ci and well-formed executions Ei < Ai, Pi, ≤poi, ≤soi, Wi, Vi > with ≤hbi and ≤swi such that C0 = , ∅ Ci ⊆ Ci-1 for all i > 0, ∪ Ci = A, and for each i > 0 the following rules are satisfied:

Causality Rules (complicated)

An execution E <A, P, ≤po, ≤so, W, V> with ≤hb is legal if there is a finite sequence of set of actions Ci and well-formed executions Ei < Ai, Pi, ≤poi, ≤soi, Wi, Vi > with ≤hbi and ≤swi such that C0 = , ∅ Ci ⊆ Ci-1 for all i > 0, ∪ Ci = A, and for each i > 0 the following rules are satisfied:

Causality Rules (complicated)

E

→ E1 → E2 → … → Ei

∅ C1 C2 Ci-1

Justify

Causality Rules: Rules out out-of-thin-air values

Example: Initially, x == y == 0, x and y are non-volatile

r1 == r2 == 42 is out-of-thin-air value

Out-of-thin-air Value

Thread-1 Thread-2r1 = x; r2 = y;

y = r1; x = r2;

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

Fixed-point semantics

Overapproximation of JMM WriteSet

JPR Overview

WriteSetWrite: add values to Read: Pick value from

JPF

Structure of JPR

JPR Driver

JPF JMMListener

WriteSetold

WriteSetnew

Events

Iterative calls

Bytecode of the target program

JPF’s state representation is extended with the following metadata:

Metadata

WriteSet MemLoc → 2Aid × Val Collect write values

ActionSet 2Action Current set of actions

HBSet 2Aid × Aid Collect ≤hb relations

ImposeSet 2Aid × Val Rule out some out-of-thin-air values

Read Aid → Aid × Val Record W(r) and V(W(r))

Write Aid → Val Record V(w)

Initially, x == y == 0, x and y are non-volatile.

Under JMM, r1 == 1 r2 == 1 is possible. ⋀

Example

Thread-1 Thread-2r1 = x; r2 = y;

y = 1; x = 1;

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>}, WS(y) = {<init, 0>}IS = ∅

1st iteration

GWS = ∅init

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>}, WS(y) = {<init, 0>}IS = ∅R(A1) = <init, 0>, legal past read

A1; r1 = x;

1st iteration

init A1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>

A1; r1 = x;

A2: y = 1;

1st iteration

init A1 A2

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

1st iteration

init

A1 A2

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <init, 0> legal past read

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

1st iteration

init

A1 A2

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <init, 0>

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

r1 = 0, r2 = 0

1st iteration

init

A1 A2

B1 B2

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <A2, 1> legal past read

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

1st iteration

init

A1 A2

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

r1 = 0, r2 = 1

1

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <A2, 1>

1st iteration

init

A1 A2

B1 B2

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

WS(x) = {<init, 0>}, WS(y) = {<init, 0>}IS = , ∅R(A1) = <init, 0>, R(B1) = 0 legal past read

1st iteration

init

A1

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <init, 0>

1st iteration

init

A1 A2

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

B2: x = 1; WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <init, 0>

r1 = 0, r2 = 0

1st iteration

init

A1 A2

B1 B2

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = , ∅R(A1) = <init, 0>, R(B1) = <init, 0>

r1 = 0, r2 = 0

1st iteration

init

A1 A2

B1 B2

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

B1: r2 = y;

WS(x) = {<init, 0>}, WS(y) = {<init, 0>}IS = ∅R(B1) = <init, 0> legal past read

1st iteration

init B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

B1: r2 = y;

A1; r1 = x;

WS(x) = {<init, 0>}, WS(y) = {<init, 0>}IS = ∅R(B1) = <init, 0>, R(A1) = <init, 0> legal past read

1st iteration

init

A1

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

B1: r2 = y;

A1; r1 = x;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

r1 = 0, r2 = 0

1st iteration

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

A1; r1 = x;

A2: y = 1;

B1: r2 = y;

0

B2: x = 1;

1

B1: r2 = y;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

B1: r2 = y;

A1; r1 = x;

A2: y = 1;

B2: x = 1;

B2: x = 1;

A2: y = 1;

B2: x = 1;

A1; r1 = x;

0

A2: y = 1;

1

r1 = 0, r2 = 1

1st iteration

r1 = 0, r2 = 1

The WriteSet collected after 1st iteration is

GWS(x) = {<init, 0>, <B2, 1>}GWS(y) = {<init, 0>, <A2, 1>}

It is passed to the 2nd iteration

init: x = 0, y = 0;

Thread-1 Thread-2A1: r1 = x; B1: r2 = y;

A2: y = 1; B2: x = 1;

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = ∅

2nd iteration

GWS(x) = {<T, 0>, <B2, 1>}GWS(y) = {<T, 0>, <A2, 1>}

init

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = ∅

2nd iteration

A1: r1 = x;

init A1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = {<B2, 1>}, R(A1) = <B2, 1> potential future read

2nd iteration

A1: r1 = x;

0 1

init A1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = {<B2, 1>}, R(A1) = <B2, 1>

2nd iteration

A1: r1 = x;

0 1

A2: y = 1;

init A1 A2

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = {<B2, 1>}, R(A1) = <B2, 1>

2nd iteration

A1: r1 = x;

0 1

A2: y = 1;

B1: r2 = y;…

init

A1 A2

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = {<B2, 1>}, R(A1) = <B2, 1>, R(B1) = <A2, 1>

2nd iteration

A1: r1 = x;

0 1

A2: y = 1;

B1: r2 = y;

0 1

init

A1 A2

B1

init: x = 0, y = 0; Thread-1 Thread-2A1: r1 = x; B1: r2 = y; A2: y = 1; B2: x = 1;

init: x = 0, y = 0

WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>}IS = {<B2, 1>}, justifiedR(A1) = <B2, 1>, R(B1) = <A2, 1>

2nd iteration

A1: r1 = x;

0 1

A2: y = 1;

B1: r2 = y;

0 1

B2: x = 1;

… r1 = 1, r2 = 1

init

A1 A2

B1 B2

3rd iteration generates the same global WriteSet as 2nd iteration, so a fixed-point is reached.

Possible outcomes running JPR: r1 == 0 r2 == 0⋀ r1 == 0 r2 == 1⋀ r1 == 1 r2 == 0⋀ r1 == 1 r2 == 1⋀

Example

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

JRF (Java Racefinder) is a JPF extension used to precisely detect data races.

Kyunghee Kim, Eric Mercer, Neha Rungta, Tuba Yavuz-Kahveci, Beverly Sanders

http://babelfish.arc.nasa.gov/trac/jpf/wiki/projects/jpf-racefinder

Working with JRF

Data Race Free (DRF) Guarantee

For DRF programs, model checking under SC memory model is enough. JPF is sufficient, no need to run JPR.

Working with JRF

Working with JRF

JRF

JPF

JPR

DRF? Y

DRF? N

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

Group 1 tc1 – tc20 from JMM causality test cases

http://www.cs.umd.edu/~pugh/java/memoryModel/unified Proposal/testcases.html

Group 2 Benign data races (hash code, is prime)

Group 3 Harmful data races (dcl, peterson, dekker)

Testing Suites

Experiment ResultsTe

st C

ases

Time (milliseconds)

Experiment ResultsTe

st C

ases

Time (milliseconds)

JPR takes much longer time than JPF: Iterations Data choice generators

Experiment ResultsTe

st C

ases

Number of states

Contents

Memory ModelThe Java Memory ModelAlgorithm ImplementationExperienceConclusion

JPR: Applies a fixed-point based semantic Adds non-SC behaviors into JPF Generates an overapproximiation of JMM

Conclusion

Thank You!

top related