410 likes | 586 Views
Verifying Safety Properties of Concurrent Java Programs Using 3-Valued Logic. Paper by: Eran Yahav Presented by: Avi Yadgar. Overview. Checking safety properties Checked programs: Multiple threads (unbounded) Dynamic heap (unbounded number of objects) Use 3 valued logic for abstraction.
E N D
Verifying Safety Properties of Concurrent Java Programs Using 3-Valued Logic Paper by: Eran Yahav Presented by: Avi Yadgar
Overview • Checking safety properties • Checked programs: • Multiple threads (unbounded) • Dynamic heap (unbounded number of objects) • Use 3 valued logic for abstraction
Outline • Concurrent programs (Crash Course) • Important Properties • Concurrent Java • Challenges • Verifying Safety Properties • Verification Algorithm • Representation of States • Representation of Properties • Representation of Functionality • Verification Algorithm (again) • 3-Value Abstraction • Abstract state representation • Abstract Functionality
Concurrent Programs • Multiple threads • Some shared resources (memory, code) • Some separate resources (PC, locks) • Locks • Can be held by a single thread • Blocks other threads
Checking Concurrent Programs • Inconsistent updates • Deadlocks • Violation of data types invariants • Illegal thread manipulation
Concurrent Java • Threads • Threads as objects • Created, started, blocked, waiting, dead • Objects as locks • Synchronized code • Wait • Notify, notifyall • join
Example class Queue { protected Object head, tail; public void put(Object o) { synchronized(this) { // lp1 put o into the queue // lp2 } // lp3 } public void approveHead() { synchronized(this) { // la1 if (head != null) // la2 head.approve(); } } } // end of class Queue public Object take() { synchronized (this) { // lt1 o = cut the head of the queue // lt2 } return o; }
class Producer implements Runnable { protected Queue q; public void run() { Object o = produce object; q.put(o); } } class Consumer implements Runnable { protected Queue q; public void run() { Object o = q.get(); consume o } } class Approver { protected Queue q; public void run() { p.approveHead(); } }
class Main { public static void main () { Queue q = new Queue(); Thread prd = new Thread(new Producer (q)); Thread csm = new Thread(new Consumer (q)); for (int i=3; i<3; i++) new Tread(new Approver(q).start()); prd.start(); csm.start(); } } // lm1 // lm2 // lm3 // lm4 // lm5 // lm6 // lm 7
Challenges • Number of threads • Possibly unbounded • Number of objects in heap • Possibly unbounded An abstraction is required
Outline • Concurrent programs (Crash Course) • Important Properties • Concurrent Java • Challenges • Verifying Safety Properties • Verification Algorithm • Representation of States • Representation of Properties • Representation of Functionality • Verification Algorithm (again) • 3-Value Abstraction • Abstract state representation • Abstract Functionality
States of a Concurrent System • Memory map • Program locations • Status of locks and threads • Represent the states using logical structures • As first order formulae
<u0> <q> <u1> <u2> <m1> <u3> <u4> Representing States - Configurations rvalue[next] rvalue[next] rvalue[next] rvalue[next] r_by[next] r_by[tail] r_by[head] r_by[next] r_by[next] r_by[next] rvalue[head] rvalue[tail] rvalue[this] <a3> rvalue[this] <a2> Is_thread <a1> Is_thread at[la_1] rvalue[this] Is_thread at[la_1] rvalue[this] at[la_1] rvalue[o] <prd> Is_thread held_by r_by[o] at[lp_2] blocked rvalue[this] <cns> <UC,ic> UC Configuration: Is_thread at[lt_1]
Representing states • States are represented by configurations <U,i> • U – Set of current objects • i – Set of interpretations to predicates • Each element is a mapping U{0,1} • Predicates – represent properties of objects
Predicates • is_thread(t) • at[lab](t) • rvalue[fld](t) • held_by(l,t) • blocked(t,l) • waiting(t,l) • Idlt(l1,l2)
Representing Safety Properties • As first order formulae
Actions • Pre-conditions for the execution • Action is ‘taken’ if there is an assignment that satisfies the preconditions • Update the values of the predicates • Notation: • C rewrites into C’
<q> <u0> <u1> <m1> <u2> <u3> <u4> Actions synchronized(this) { // lp1 put o into the queue // lp2 } // lp3 r_by[head] r_by[next] r_by[next] r_by[next] r_by[next] r_by[tail] <a3> <a2> Is_thread <a1> Is_thread at[la_1] Is_thread at[la_1] at[la_1] <prd> Is_thread held_by held_by r_by[o] at[lp_2] at[lp_3] at[lp_2] blocked <cns> Is_thread at[lt_1]
Safety Properties • RW interference lr : Obj1 = xr lw : xw = Obj2
Safety Properties • WW interference lw1: xw1 = Obj1 lw2 : xw2 = Obj2
Safety Properties • Missing ownership (when invoking wait/notify) ls : wait(v)
Checking Algorithm C = <U,i> Check if property holds under i check() { initialize_stack(C0) while stack is not empty { C=stack.pop if C S { verify(C) for each action ac for each C’ s.t. stack.push(C’) } } }
Outline • Concurrent programs (Crash Course) • Important Properties • Concurrent Java • Challenges • Verifying Safety Properties • Verification Algorithm • Representation of States • Representation of Properties • Representation of Functionality • Verification Algorithm (again) • 3-Value Abstraction • Abstract state representation • Abstract Functionality
Abstract States • New logic value • Definite values: 0,1 • Indefinite value : ½ - “might be true” • Abstract Configurations <U,i> • U: Each element might represent multiple objects (summary nodes) • i: Each element is a mapping : U {0, ½,1}
Embedding • Given C=<U,i>, C’=<U’,i’> • An embedding f:UU’: • C’represents C • Use Canonical Abstraction
<q> <m1> <u4> <u3> <u2> <u1> <u0> <u> Abstract Configurations r_by[head] r_by[next] r_by[next] r_by[next] r_by[next] r_by[tail] <a3> <a2> Is_thread <a1> Is_thread at[la_1] Is_thread at[la_1] at[la_1] <prd> Is_thread held_by r_by[o] at[lp_2] blocked <cns> Is_thread at[lt_1]
<q> <u4> <u> <m1> <u0> Abstract Configurations Rvalue[next](u,u4)=? Rvalue[next](u0,u)=? Rvalue[next] Rvalue[next] r_by[head] r_by[next] r_by[tail] <a3> <a2> Is_thread <a> <a1> Is_thread Is_thread at[la_1] Is_thread at[la_1] at[la_1] at[la_1] <prd> Is_thread held_by r_by[o] at[lp_2] blocked <cns> Is_thread at[lt_1]
Abstract Rewrites Cc=<Uc,ic> C’c=<U’c,I’c> Cc rewrites into C’c C=<U,i> C’=<U’,i’> C rewrites into C
Abstract Rewrites <s_t> At[la_1] Is_thread rvalue[this] <u> public void approveHead() { synchronized(this) { // la1 if (head != null) // la2 head.approve(); } } } // end of class Queue rvalue[this] <s_t_0> At[la_2] Is_thread <u> held_by <s_t_1> At[la_1] Is_thread rvalue[this]
Instrumentation Predicates is_blocked? public void approveHead() { synchronized(this) { // la1 if (head != null) // la2 head.approve(); } } } // end of class Queue <s_t_0> is_blocked Is_thread At[la_1] <s_t_a> At[la_1] Is_thread <s_t_1> At[la_1] Is_thread rvalue[this] rvalue[this] rvalue[this] blocked blocked <u> Is_acquired rvalue[this] held_by <s_t_b> At[la_2] Is_thread
Instrumentation Predicates l is referenced by the field “fld” of some object
Instrumentation Predicates The lock l is acquired by some thread
Instrumentation Predicates The thread t is blocked by some lock
Outline • Concurrent programs (Crash Course) • Important Properties • Concurrent Java • Challenges • Verifying Safety Properties • Verification algorithm • Representation of States • Representation of Properties • Representation of Functionality • Verification Algorithm (again) • 3-Value Abstraction • Abstract state representation • Abstract Functionality
Further Reading • http://www.cs.tau.ac.il/~tvla/ • http://www.cs.tau.ac.il/~msagiv/sas00t.ps • http://www.cs.tau.ac.il/~msagiv/toplas02.pdf • http://www.math.tau.ac.il/~yahave/3vmc