Bounded Model Checking of Concurrent Programs - PowerPoint PPT Presentation

1 / 50
About This Presentation
Title:

Bounded Model Checking of Concurrent Programs

Description:

Check for 'regular' bugs Situations where the specifications are not met. Check for races ... divide deadlocks into 2 kinds. global deadlocks. local deadlocks ... – PowerPoint PPT presentation

Number of Views:43
Avg rating:3.0/5.0
Slides: 51
Provided by: stef329
Category:

less

Transcript and Presenter's Notes

Title: Bounded Model Checking of Concurrent Programs


1
Bounded Model Checking of Concurrent Programs
  • Ishaj Rabinovitz, Orna Grumberg
  • Technion Israel Institute of Technology
  • Stefan Nägeli
  • Software Engineering Seminar 13.06.05

2
Schedule
  • Model Checking
  • CBMC (context bounded model checking)
  • TCBMC (threaded context bounded model checking)
  • Modeling Synchronization Primitives
  • Verifying Concurrent Specifications
  • Experimental Results

3
Model Checking
4
Model 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

5
Procedure
  • Construct model
  • Conjunct with negation of specification
  • Try to satisfy formula using a SAT-Solver to
    check any violations of the specification

6
Problems 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.

7
CBMC
  • Context Bounded Model Checking

8
C-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.

9
Loop Unrolling
x 3 while (xgt1) if(x2 0) x
x/2 else x 3x1
x 3 if (xgt1) if(xgt1) assert(xlt1)

body
body
10
Single 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)
11
Pointers 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.
12
CBMC in Multi-Threaded Apps
Problem Indexing of shared variables!
13
Threaded Programs
Shared variables
g
Thread 1
Context Switch
Context Switch Block
Thread 2
Write(g)
Write(g)
14
TCBMC
  • Threaded Context Bounded Model Checking

15
Goals 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

16
Threaded-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.

17
Procedure
  • 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.

18
1. 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
19
1. Preprocessing (2)
Break statements into several
g global / shared variables x local variables
x1 g2 x2 g3 g1 x1 x2
g1 g2 g3
20
2. 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)

21
3. 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.

22
Monotonic
The value of threadt_cs must increase
monotonically.
23
Interleaving bound
Since we introduced a bound n of context
switches, there is a bound for the variable
threadt_cs n
24
Parity
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.
25
Extending 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.
26
Modeling 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.
27
Modeling 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
28
Reminder 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
29
Type 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
30
Type 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)
31
Type 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
32
Type 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
33
Type 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
34
Modeling Synchronization Primitives
  • Atomic Sections
  • Mutexes
  • Conditions

35
Modeling Atomic Sections
Very simple Just add constraints that force
threadt_cs values of the lines in an atomic
section to be identical.
thread 1
  • atomic
  • x1 y1
  • g3 y2

add additional constraints thread1_cs(1)
thread1_cs(2) thread1_cs(2) thread1_cs(3) thre
ad1_cs(3) thread1_cs(4)
36
Modeling 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.
37
Modeling 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
38
Modeling 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
39
Modeling 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
40
Verifying Concurrent Specs
  • Detecting Races
  • Finding Deadlocks

41
Detecting 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.
42
Detecting Races Examples
g 3
x g
atomic assert(g_write_flag0) g3
g_write_flag1 g_write_flag0
assert(g_write_flag0) x g
43
Pointers 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.
44
Finding 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.
45
Finding 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
46
New 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)

47
New 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)
48
Experimental Results
49
Experimental Results
Windows operating system, Pentium4 1.8Ghz with
1GB memory
Linux operating system, Pentium4 2Ghz with
250MB memory
50
Questions?
Write a Comment
User Comments (0)
About PowerShow.com