Title: Bounded Model Checking of Concurrent Programs
1Bounded Model Checking of Concurrent Programs
- Ishaj Rabinovitz, Orna Grumberg
- Technion Israel Institute of Technology
- Stefan Nägeli
- Software Engineering Seminar 13.06.05
2Schedule
- Model Checking
- CBMC (context bounded model checking)
- TCBMC (threaded context bounded model checking)
- Modeling Synchronization Primitives
- Verifying Concurrent Specifications
- Experimental Results
3Model Checking
4Model Checking
- Has become a leading technique for checking
specifications of hardware. - Model checking is used to see if the model
(formula describing all possible executions of
the system) satisfies the specification. - Especially checking threaded application will
become very important due to better hardware
support for concurrent processes/threads
5Procedure
- Construct model
- Conjunct with negation of specification
- Try to satisfy formula using a SAT-Solver to
check any violations of the specification
6Problems Model Checking
- Since all model checking tools have to cope with
the State Explosion Problem we bound all traces
up to a length k. - Software has typically very long error traces
and therefore a large bound k is needed. - With a large bound the SAT solver will not find
a solution in appropriate time.
7CBMC
- Context Bounded Model Checking
8C-Bounded Model Checking
- Different approach using SAT-Solver
- Program is translated into Single Assignment Form
(SSA) - Unroll loop to its bound
- Inline function call
- Unroll recursion to its bound
- Index all assignments to a variable
- Introduce guard variables for conditional
statements - Generate a set of constraints
- No notion of state and therefore less sensitive
to the length of the trace.
9Loop Unrolling
x 3 while (xgt1) if(x2 0) x
x/2 else x 3x1
x 3 if (xgt1) if(xgt1) assert(xlt1)
body
body
10Single Assignment Form Guard Variables
x0 3 guard1 x0 gt 1 guard2 guard1 x02
0 x1 if(guard2) x0/2 else x0 guard3 guard1
!(x02 0) x2 if(guard3) 3x11 else
x1 guard4 guard1 x2 gt 1 guard5 guard4
x22 0 x3 if(guard5) x2/2 else x2 guard6
guard4 !(x22 0) x4 if(guard6) 3x31 else
x3 specification !(x4 lt 1)
x 3 if (xgt1) if(x2 0) x x/2
else x 3x1 if(xgt1) if(x2
0) x x/2 else x3x1
assert(xlt1)
11Pointers Arrays
Every assignment to a dereference of a pointer is
instantiated to multiple assignments, one for
each possible value of the pointer p.
x12 if (px) 3 else x11 y7 if (py) 3
else y6 z4 if (pz) 3 else z3
p1 3
Arrays treated similarly by instantiating for
each possible value of the array index.
12CBMC in Multi-Threaded Apps
Problem Indexing of shared variables!
13Threaded Programs
Shared variables
g
Thread 1
Context Switch
Context Switch Block
Thread 2
Write(g)
Write(g)
14TCBMC
- Threaded Context Bounded Model Checking
15Goals of TCBMC
The Authors suggest to run TCMBC 3 times to
- Check for regular bugs Situations where the
specifications are not met. - Check for races
- Check for deadlocks
16Threaded-C BMC
- Extended Model of C-BMC to cope with concurrency
specific problems by - Bounding the number of allowed context switches.
- Introducing a new variable val_gi for each shared
variable g and each context switch block i.
17Procedure
- Next we will see how we can translate a program
efficiently to a set of constraints in 3 steps - Preprocessing
- Applying CBMC separately on each thread
- Generating constraints for concurrency
- Main idea
- Bound the number of context switches in the run
while allowing them to be anywhere.
181. Preprocessing
A context switch can occur during the execution
of a C-statement. x1 x2 x3
ra ? x2 rb ? x3 rc ? ra rb x1 ? rc
Break statements involving more than 1 shared
variables into multiple statements
191. Preprocessing (2)
Break statements into several
g global / shared variables x local variables
x1 g2 x2 g3 g1 x1 x2
g1 g2 g3
202. Apply CBMC on each thread
Generate constraints for each thread
seperately. Template Set of constraints for a
thread
- Generates 4 types of possible constraints
- local ? local(s) x1 y1
- global ? local(s) g1 x6
- local ? global x1 if guard4 g3
else x0 - guardlocal ? local(s) / global guard3 (g2 gt x3)
213. Add Concurrency Constraints
- Define l referring to the line number
- Define threadt referring to the t-th thread in an
application - Define threadt_cs(l) number of context switches
until the line l in thread t was reached.
22Monotonic
The value of threadt_cs must increase
monotonically.
23Interleaving bound
Since we introduced a bound n of context
switches, there is a bound for the variable
threadt_cs n
24Parity
Since we deal here only with 2 threads, the
values for threadt_cs(l) can be restricted to
even for t0 and odd for t1.
25Extending the definition
We extend the definition for threadt_cs(l) to
threadt_cs(vj) threadt_cs(lvj) meaning the
value of threadt_cs(vj) is the number of context
switches until the variable vj is assigned.
26Modeling shared variables
In order to model shared variables in concurrent
programs correctly we define n new variables for
each shared (global) variable.
where g_vali refers to the value of the variable
g at the end of the i-th context switch block.
27Modeling shared variables
g_vali gp-1 has either the value of the last
assignment in the ended context switch block
(with 0..p-1 assignments to the variable g) or
the same value as in the context switch block
before g_vali g_val i-1
28Reminder 4 types of constr.
- Generates 4 types of possible constraints
- local ? local(s) x1 y1
- global ? local(s) g1 x6
- local ? global x1 if guard4 g3
else x0 - guardlocal ? local(s) / global guard3 (g2 gt x3)
We need to define translation-rules for each
possible constraint to cope with concurrency
29Type 1 local ? local(s)
For regular statements that do not access global
variables we dont have to do anything except add
the thread prefix.
threadt_
Example x1 y1 ? thread1_x1 thread1_y1
30Type 2 global ? local(s)
Template for expressions of type gj if
(guardr) xk else g j-1
threadt_gj if(threadt_guardr) threadt_xk
else if (threadt_cs(gj)
threadt_cs(gj-1)) threadt_gj-1 else g_val(thr
eadt_cs(gj) 1)
31Type 3 local ? global
Expresssion of type xj if guardr gk else x
j-1 if gk was assigned in same context switch
block ? add prefix as in previous
rule. else use g_val of previous context switch
block
32Type 3 local ? global (2)
template for xj if guardr gk else x
j-1 threadt_xj if(threadt_guardr)
if(threadt_cs(xj) threadt_cs(gk))
threadt_gk else g_val(threadt_cs(xj)-1)
else threadt_x j-1
33Type 4 guardlocal ?locals/global
guardlocal ? local treated as items of type 1
simply add prefixes guardlocal ?
global treated as items of type 3 use last
assignment to that global variable in this
context switch block or use g_val of previous
context switch block
34Modeling Synchronization Primitives
- Atomic Sections
- Mutexes
- Conditions
35Modeling Atomic Sections
Very simple Just add constraints that force
threadt_cs values of the lines in an atomic
section to be identical.
thread 1
add additional constraints thread1_cs(1)
thread1_cs(2) thread1_cs(2) thread1_cs(3) thre
ad1_cs(3) thread1_cs(4)
36Modeling Mutexes
We define a redundant-attempt as an attempt to
lock a mutex that is already in the locked
state. A wait-free execution is an execution that
has no redundant-attempts.
In our model all executions are wait-free since
all errors other than dead-locks that appear in a
non-wait-free execution also appear in a
wait-free execution.
37Modeling Mutexes
We model a mutex by implementing special C
functions for lock and unlock primitives and
translate it using CBMC
lock mutex
unlock mutex
atomic assume(mutexU) mutex L
atomic assert(mutexL) mutex U
38Modeling Conditions
- A condition has 3 primitives
- wait
- signal
- broadcast
We model waiting for conditions with a condition
vector of type boolean and length
threads. cond0..threads-1 if the flag is set,
that thread is waiting for that condition to
happen
39Modeling Conditions
wait(cond, mutex)
signal(cond)
atomic condcurr_thread1
unlock(mutex) assume( condcurr_thread0)
lock(mutex)
atomic i rand(threads) assume(
condi 1 cond 0) condi 0
40Verifying Concurrent Specs
- Detecting Races
- Finding Deadlocks
41Detecting Races
Race Condition State in which the next
instruction of different threads access the same
memory location and at least one of them is a
write operation.
Detection Add to each global variable a bit
variable g_write_flag and raise it whenever g is
defined (assigned to) and lowered in the next
instruction. Assert that on every access to g we
assert that g_write_flag is low.
42Detecting Races Examples
g 3
x g
atomic assert(g_write_flag0) g3
g_write_flag1 g_write_flag0
assert(g_write_flag0) x g
43Pointers Arrays
When there is an assignment to a dereference of a
pointer we should change the write_flag for the
variable that is being changed. We should
consider all possible variables which pointer p
might point to. For each one we change the
corresponding flag while changing the variable
itself. Arrays are handled similarly.
44Finding Deadlocks
- We have to divide deadlocks into 2 kinds
- global deadlocks
- local deadlocks
In the following discussion we will focus on
global deadlocks.
When modeling the code to detect deadlocks, we
ignore the existence of other errors.
45Finding Deadlocks
We must change the previously defined model to
include a global counter called threads_in_wait co
unting the number of threads that are currently
waiting for a condition.
On a lock attempt we check if the mutex is
already in lock state. If so we increase the
variable threads_in_wait, allow context switch
and then assert that threads_in_wait lt
threads If the assertion fails we encountered a
global deadlock
46New Model lock(mutex)
if(!dd) //dd deadlock_detected atomic
unlocked (mutex U) if(unlocked) mutex
L else threads_in_wait atomic
if(!unlocked) dd (threads_in_wait
T) assert(!dd) assume(dd)
47New Model wait(cond,mutex)
if (!dd) //dd deadlock_detected atomic
condcurrent_thread 1 unlock(mutex)
threads_in_wait atomic dd
(threads_in_wait T) assert(!dd)
assume(dd V condcurrrent_thread0)
threads_in_wait-- lock(mutex)
48Experimental Results
49Experimental Results
Windows operating system, Pentium4 1.8Ghz with
1GB memory
Linux operating system, Pentium4 2Ghz with
250MB memory
50Questions?