670 likes | 800 Views
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.
E N D
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
Contents • Memory Model • The Java Memory Model • Algorithm • Implementation • Experience • Conclusion
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 • 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. JPF assumes SC memory model
Example Intially, x = 0, done = false SCMM r == 1
Example Intially, x = 0, done = false SCMM r == 1 JMM r == 0 ˅ r == 1
Java’s String class • Data race is benign in both SC MM and JMM public final class String{ private final char value[]; private final int offset; private final int count; private inthash; //default 0 … public inthashCode(){ inth = 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; } }
Another Version • Benign in SC MM but not benign in JMM public final class String{ private final char value[]; private final int offset; private final int count; private inthash; //default 0 … public inthashCode(){ inth = 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; } }
Another Version • Benign in SC MM but not benign in JMM public final class String{ private final char value[]; private final int offset; private final int count; private inthash; //default 0 … public inthashCode(){ inth = 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; } } • Return hash code or0
Extending JPF • JPF: generates executions under SC memory model. • JPR: generates executions under an overapproximation of JMM.
Contents • Memory Model • The Java Memory Model • Algorithm • Implementation • Experience • Conclusion
Overview of JMM • 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
JMM Action • 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 Execution • Execution E <A, P, ≤po, ≤so, W, V>
Synchronizes-with Order ≤sw • A partial order over actions with regard to ≤so
Happens-before Order ≤hb • A partial order over actions by taking transitive closure of ≤po and ≤sw Initially, x == 0 ⋀ done == false, done is volatile ≤sw ≤sw ≤po ≤sw ≤po
Happens-before Order ≤hb • A partial order over actions by taking transitive closure of ≤po and ≤sw Initially, x == 0 ⋀ done == false, done is volatile ≤sw ≤sw ≤po ≤hb ≤sw ≤po
Data Race • In an execution Thread-1: … Write … Thread-2: … Read … ≤hb ≤hb x
Data Race Free • 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.
Well-formed Execution • For all reads r of variable v, it cannot be • r ≤hbW(r) • W(r) ≤hbw ≤hbr (w writes to v)
Example • r can only be 1, not 0 Initially, x == 0⋀ done == false, done is volatile ≤sw ≤sw ≤po If read x = 0, then there is an interleaving write x = 1. ≤sw ≤po
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) 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: E Justify ∅ C1 C2 Ci-1 → E1 → E2 → … → Ei
Out-of-thin-air Value • 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
Contents • Memory Model • The Java Memory Model • Algorithm • Implementation • Experience • Conclusion
JPR Overview • Fixed-point semantics • Overapproximation of JMM • WriteSet JPF WriteSet Write: addvalues to Read: Pick value from
Structure of JPR JPR Driver WriteSetold Iterative calls WriteSetnew Events JPF JMMListener Bytecode of the target program
Metadata • JPF’s state representation is extended with the following metadata:
Example Initially, x == y == 0, x and y are non-volatile. Under JMM, r1 == 1 ⋀ r2 == 1 is possible.
1st iteration init: x = 0, y = 0 WS(x) = {<init, 0>}, WS(y) = {<init, 0>} IS = ∅ init GWS = ∅
1st iteration init: x = 0, y = 0 A1; r1 = x; WS(x) = {<init, 0>}, WS(y) = {<init, 0>} IS = ∅ R(A1) = <init, 0>, legal past read init A1
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0> init A1 A2
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; B1: r2 = y; WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0> A1 A2 init B1
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; A1 A2 init B1: r2 = y; B1 0 WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <init, 0>legal past read
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; A1 A2 init B1: r2 = y; B1 B2 0 WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <init, 0> B2: x = 1; r1 = 0, r2 = 0
1st iteration init: x = 0, y = 0 A1; r1 = x; A1 A2 A2: y = 1; init B1 B1: r2 = y; WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <A2, 1>legal past read 0 1 B2: x = 1;
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; A1 A2 init B1: r2 = y; B1 B2 0 1 WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <A2, 1> B2: x = 1; r1 = 0, r2 = 1
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; B1: r2 = y; B1: r2 = y; WS(x) = {<init, 0>}, WS(y) = {<init, 0>} IS = ∅, R(A1) = <init, 0>, R(B1) = 0legal past read 0 1 A1 init B2: x = 1; B1
1st iteration init: x = 0, y = 0 A1; r1 = x; A1 A2 A2: y = 1; B1: r2 = y; init A2: y = 1; B1: r2 = y; B1 WS(x) = {<init, 0>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <init, 0> 0 1 B2: x = 1;
1st iteration init: x = 0, y = 0 A1; r1 = x; A1 A2 A2: y = 1; B1: r2 = y; init A2: y = 1; B1 B2 B1: r2 = y; WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <init, 0> B2: x = 1; 0 1 B2: x = 1; r1 = 0, r2 = 0
1st iteration init: x = 0, y = 0 A1; r1 = x; A2: y = 1; A1 A2 B1: r2 = y; A2: y = 1; init B1: r2 = y; B2: x = 1; B1 B2 B2: x = 1; 0 1 A2: y = 1; r1 = 0, r2 = 0 WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅, R(A1) = <init, 0>, R(B1) = <init, 0> B2: x = 1;
1st iteration init: x = 0, y = 0 A1; r1 = x; B1: r2 = y; A2: y = 1; WS(x) = {<init, 0>}, WS(y) = {<init, 0>} IS = ∅ R(B1) = <init, 0>legal past read B1: r2 = y; A2: y = 1; B1: r2 = y; B2: x = 1; B2: x = 1; 0 1 A2: y = 1; init B1 B2: x = 1;
1st iteration init: x = 0, y = 0 A1; r1 = x; B1: r2 = y; A2: y = 1; A1; r1 = x; B1: r2 = y; A2: y = 1; B1: r2 = y; WS(x) = {<init, 0>}, WS(y) = {<init, 0>} IS = ∅ R(B1) = <init, 0>, R(A1) = <init, 0> legal past read B2: x = 1; B2: x = 1; 0 1 A2: y = 1; A1 init B2: x = 1; B1
1st iteration init: x = 0, y = 0 A1; r1 = x; B1: r2 = y; A2: y = 1; A1; r1 = x; B1: r2 = y; A2: y = 1; A2: y = 1; B1: r2 = y; B2: x = 1; B2: x = 1; B2: x = 1; 0 1 A2: y = 1; B2: x = 1; A2: y = 1; B2: x = 1; r1 = 0, r2 = 0
1st iteration init: x = 0, y = 0 A1; r1 = x; B1: r2 = y; A2: y = 1; A1; r1 = x; B2: x = 1; B1: r2 = y; A2: y = 1; A2: y = 1; A1; r1 = x; B1: r2 = y; B2: x = 1; B2: x = 1; B2: x = 1; 0 1 0 1 A2: y = 1; B2: x = 1; A2: y = 1; B2: x = 1; A2: y = 1; 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 r1 = 0, r2 = 1
2nd iteration init: x = 0, y = 0 WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅ GWS(x) = {<T, 0>, <B2, 1>} GWS(y) = {<T, 0>, <A2, 1>} init
2nd iteration init: x = 0, y = 0 A1: r1 = x; WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = ∅ init A1
2nd iteration init: x = 0, y = 0 A1: r1 = x; 0 1 init A1 WS(x) = {<init, 0>, <B2, 1>}, WS(y) = {<init, 0>, <A2, 1>} IS = {<B2, 1>}, R(A1) = <B2, 1>potential future read …