360 likes | 511 Views
Verifying Safety Properties of Concurrent Java Programs Using 3-Valued Logic. Eran Yahav and Mooly Sagiv School of Computer Science Tel-Aviv University yahave@post.tau.ac.il http://www.cs.tau.ac.il/~yahave. Introduction. Goal: Verification of concurrent Java programs Support the following
E N D
Verifying Safety Properties of Concurrent Java Programs Using 3-Valued Logic Eran Yahav and Mooly Sagiv School of Computer Science Tel-Aviv University yahave@post.tau.ac.il http://www.cs.tau.ac.il/~yahave
Introduction • Goal: Verification of concurrent Java programs • Support the following • Java concurrency-model • Dynamic allocation/deallocation of objects • Dynamic allocation/deallocation of threads
Why Verify Java Programs? • Concurrency is hard to debug • deadlocks • interference • dependence on thread scheduling • failures hard to reproduce • Concurrent Programming in Java • low-level constructs • no compile-time or run-time checks
Java Concurrency • Threads and locks are just dynamically allocated objects • synchronized implements mutual exclusion • wait, notify and notifyAll coordinate activities across threads
Java Concurrency Challenges • Dynamic allocation • Data and control are strongly related • Thread-scheduling info may require understanding of heap structure (e.g., scheduling queue) • Heap analysis requires information on thread scheduling Thread t1 = new Thread(); Thread t2 = new Thread(); … if (…) t = t1 else t = t2; t.start();
Model Checking Approach • Explore the space of possible program configurations • Find configurations that violate the desired safety property How do you guarantee finiteness ?
Example - Mutual Exclusion l_0: while (true) { l_1: synchronized(sharedLock) { l_C: // critical actions l_2: } l_3: } • Allocate new lock ? • Allocate new thread ? Two threads: (pc1,pc2,lockAcquired1,lockAcquired2)
Existing Approaches for Dynamic Allocation • dSPIN, Java pathfinder, Bandera, • All put an a priori bound on number of allocated objects • Abstraction applied when model is extracted
Existing Approaches for Dynamic Allocation • Will fail on many interesting programs • Example: http server • Creates a thread for each http request • Threads using exclusive shared resource • Show mutual exclusion T R T R T R
T T R R T T R R T T R R T R Existing Approaches for Dynamic Allocation • Challenges • Guaranteed correctness vs. assumed correctness • Correctly track thread states
Our Approach • Abstract configurations (conservatively) represent multiple program configurations • Compute a finite set of abstract configurations modeling program behavior • Every potential concrete configuration is represented • Superfluous configurations might be represented too • Check property for every computed abstract configuration
Plan • Concrete Program Model • Safety Properties • Abstract Program Model • Prototype implementation (3VMC) • Summary
Program Model • Interleaving model of concurrency • Program is a collection of thread-type transition systems
Configurations • A program configuration encodes: • global store • program-location of every thread • status of locks and threads • First-order logical structures used to represent program configurations
Configurations blocked is_thread at[l_1] held_by is_thread at[l_C] rval[this] blocked rval[this] is_thread at[l_1] is_thread at[l_0] is_thread at[l_0] rval[this]
Configurations • Predicates model properties of interest • is_thread • { at[lab](t) : lab Labels } • { rval[fld](o1,o2) : fld Fields } • held_by(l,t) • blocked(t,l) • waiting(t,l) • Can use the framework with different predicates
Configurations • Program control-flow is not separately represented • Program location for each thread is encoded inside the configuration • { at[lab](t) : lab Labels }
Structural Operational Semantics - actions • An action consists of: • precondition formula • update formulae • Precondition formula may use a free variable ts for “currently scheduled” thread • Semantics is non-deterministic
lock(v) precondition tts: rval[v](ts,l) held_by(l,t) predicate update held_by’(l1,t1) = held_by(l1,t1) (l1 = l t1 = ts) blocked’ (t1,l1) = blocked(t1,l1) ((l1 l) (t1 ts)) Structural Operational Semantics - actions
State Space Exploration Initialize(C0) { for each C C0 push(stack,C) } explore() { while stack is not empty { C = pop(stack) if not member(C,stateSpace) { verify(C) stateSpace = stateSpace {C} for each action ac for each C’ such that C ac C’ push(stack,C’) } } }
Example: mutual exclusion t1,t2: (t1 t2) (at[lcrit](t1) at[lcrit](t2)) • Example: no total deadlock t,lb : is_thread(t) blocked(t, lb) Safety Properties • Configuration-local property as logical formula
Abstract Program Model • Conservative representation of the concrete model • Use 3-valued logical structures to conservatively represent multiple 2-valued structures • Conservatively apply actions on abstract configurations
Abstract Configurations • First-order 3-valued logical structures are used to represent abstract program configurations • 3-valued logic • 1 = true • 0 = false • 1/2 = unknown • A join semi-lattice, 0 1 = 1/2
Concrete Configuration blocked is_thread at[l_1] held_by is_thread at[l_C] rval[this] blocked rval[this] is_thread at[l_1] is_thread at[l_0] is_thread at[l_0] rval[this]
Abstract Configuration held_by blocked is_thread at[l_C] is_thread at[l_1] rval[this] rval[this] is_thread at[l_0]
Canonic Abstraction • Merge all nodes with the same unary predicate values into a single summary node • Join predicate values • Converts a configuration of arbitrary size into a 3-valued abstract configuration of bounded size
Abstract Semantics • Conservatively model the effect of an action • use same formulae as in concrete semantics • soundness is guaranteed by [SRW99] • Use same state-space exploration algorithm to explore the abstract state space
Unbounded Number of Threads • Exploit state-space symmetry • Previous work defined symmetry between process names (indices) • Thread location = thread property • Canonic names = symmetry between properties
Example - Mutual Exclusion is_thread at[l_0] rval[this] Initial configuration
Example - Mutual Exclusion is_thread at[l_C] rval[this] held_by rval[this] is_thread at[l_0] A thread enters the critical section
Example - Mutual Exclusion is_thread at[l_C] rval[this] held_by is_thread at[l_0] rval[this] rval[this] is_thread at[l_1] blocked Other threads may be blocked or just beginning execution
Safety Properties Revisited • RW interference • WW interference • Total deadlock • Nested monitors • Illegal thread interactions
Prototype Implementation • 3VMC • Used to verify several small example programs • concurrent stack • queue • two-lock queue [PODC96] • dining philosophers • only intraprocedural • no optimizations used
Further Work • Optimizations • Partial-order reduction • Symbolic representations (BDDs) • Liveness properties • Providing counter examples
The End http://www.cs.tau.ac.il/~yahave