Over-Approximating Boolean Programs with Unbounded Thread Creation Natasha Sharygina Byron Cook, Daniel Kroening
Introduction Counterexample guided abstraction refinement (CECAR) is a successful method to verify programs Initial Abstraction Verification No error or bug found C Program with threads Concurrent Boolean Program Model Checker Property holds Simulation successful Refinement Simulator Bug found
Boolean Programs Expressions Control Flow Assignments assert Usual Boolean operators Non-deterministic choice Control Flow if then else goto Functions Assignments Simultaneous assignments to multiple variables Constrained assignments assert
Boolean Programs with Threads Created by version of SLAM for concurrent programs called SLING (G. Weissenbacher) Threads are marked by special labels Dynamic creation of threads Arbitrary interleavings of the threads
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; Thread Creation
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; STATE g0 F
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; STATE g0 T
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; STATE g0 F
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; STATE g0 F Alternative Schedule
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; STATE g0 T Alternative Schedule
Boolean Programs: Example decl g0; void t1() begin end void t2() begin assert(g0); void main() begin g0:=T; ASYNC_1: t1(); ASYNC_2: t2(); g0:=F; STATE g0 F Alternative Schedule
Available Model Checkers With translator: NuSMV SPIN Zing BOPPO – partial order reduction + QBF [Spin 2005] Fixed number of threads
Unbounded Thread Creation Actual number of threads always finite May be very large Actual number usually lost during predicate abstraction Must check abstract program with unbounded number of threads Checking the abstract model is now undecidable! Must give up Soundness or Completeness
Our Approach Other tools (SPIN, ZING) won’t terminate Not a good fit for the CEGAR loop Our approach: Over-approximating reachability in Boolean programs with unbounded thread creation
Our Approach Guarantees termination Initial Abstraction Verification No error or bug found C Program with threads Concurrent Boolean Program Model Checker Property holds Simulation successful Refinement Simulator Bug found Guarantees termination If no bug is found, the loop terminates Otherwise, provide a “helpful trace”to CEGAR loop to make progress
Thread States Explicit State, : Triple (n, pc, ) with n - number of threads pc : {1,…,n} L – vector of program locations : ({1,…,n} Vl) Vg B – valuation of program variables Thread State, : Tuple (PC, ) with PC L : V B Let S denote the set of explicit states and denote a set of thread states
Execution Semantics A scheduler picks a thread to execute an instruction The transition relation of a thread is defined by a case-split on the instruction (i.e., goto, assume, start_thread, lock, unlock, etc.) Current thread state Next thread state
Execution Semantics The set of all reachable states is The property to check: reachability of states with particular locations
Projection from a state to the value of the pc of thread t Thread Projection Projection from a state to the value of the pc of thread t Thread Projection Function Maps an explicit state of the full state space to the state visible to a thread t {1,…,.n} Projection from a state to the values of the program variables of thread t
Thread-Visible States 1 2 3 4 5 *()
Thread-Visible States The set of thread-visible states reachable in i transitions is We compute an over-approximation of This is sufficient to prove reachability properties that are expressed in terms of thread visible states Example: assertions
Over-Approximating Relation
Over-Approximating Relation 1 2 ‘ ‘
Over-Approximation
Approximation Algorithm
Mapping from a set of variables into a set of formulae Making it Symbolic Mapping from a set of variables into a set of formulae
Represents the guard of the state symbolically Making it Symbolic Represents the guard of the state symbolically
Symbolic States Guard and values of variables are stored as Boolean formulae with sharing No blowup – linear space in number of transitions Assertions are checked symbolically by checking satisfiability of SAT instances
Fixpoint Detection with QBF Did we get a new thread state? Fixpoint Detection easy for explicit state (hash-table) Symbolic case: a set of explicit thread states is represented by a symbolic thread state Give that to QBF solver (e.g., Quantor)
Refinement Imprecision caused by over-approximating relation might lead to traces that are spurious within the abstract model Can be ruled out by adding more predicates (i.e., classical refinement)
Recursion Reachability already undecidable with only two threads Our algorithm can be extended to handle recursion Idea: replace recursive calls by thread creation
Experimental Results Ran on many sequential programs generated by SLAM a few concurrent programs generated by SLING Using MiniSAT for assertions Quantor for fixpoint detection
Experimental Results
Tool for Experimentation BOPPO with support for unbounded thread creation is available for download http://www.verify.ethz.ch/boppo/
Related Work Zing: restricted form of recursion and unbounded thread creation Qadeer and Rehof, TACAS05: unsounded approach for bounding the number of context switches Flanagan and Qadeer, SPIN03: loosely coupled multhreaded programs: thread states in order of programs with little interaction.
Questions?
Modeling Recursion For function f(p1,…,pk) | p1,…pk Vl are the parameters of the function p1,…,pk := e1,…ek A new global variable is introduced for synchronization of the function return Function call is replaced by start_thread , - the first program location of f After the function call, is inserted and set to false When f returns, it sets to true. The return values are passed by means of global variables
Over-approximating recursive calls Over-approximation of a recursive call f(e1,e2) with thread creation
Partial Order Reduction with SAT Implemented in GETSUCCESSORS Computes subset of threads that are considered for symbolic execution in a particular state Commonly used in explicit state model checkers, BOPPO does it symbolically