bounded model checking of concurrent programs
Post on 14-Jan-2016
60 Views
Preview:
DESCRIPTION
TRANSCRIPT
Bounded Model Checking of Concurrent Programs
Bounded Model Checking of Concurrent Programs
Ishai Rabinovitz and Orna Grumberg
CAV ‘05
Presented by Changki Hong
2 / 26
Software Model Checking
Main trends in formal verification SAT-based Bounded Model Checking (BMC)
leading technique for model checking of hardware Software verification using formal method
Traditional testing method often fails to find bugs in concurrent programs
How about adopting BMC technique for software? Error traces are typically long large bound is needed
This results in a too large propositional formula handled by SAT solver C-Bounded Model Checking (CBMC)
Handled problems stated above. However, CBMC is only for verifying sequential programs
TCBMC
Changki Hong @ pswlab TCBMC
3 / 26
CBMC in multi-threaded program
Can not extend CBMC’s approach to concurrent C programs When there are assignments in two different threads to the same
global variable, we can’t determine the order in which they will be executed.
Changki Hong @ pswlab TCBMC
int x;
int i;
thread1() {
x=0;
for (i=0; i<3; i++)
x++;
}
thread2() {
x=0;
for (i=0; i<3; i++)
x--;
}
thrd1_x1 = 0;
thrd1_i1 = 0;
if (thrd1_i1 < 3) {
thrd1_x2 = thrd1_x1 + 1;
thrd1_i2 = thrd1_i1 + 1;
}
if (thrd1_i2 < 3) {
thrd1_x3 = thrd1_x2 + 1;
thrd1_i3 = thrd1_i2 + 1;
}
if (thrd1_i3 < 3) {
thrd1_x4 = thrd1_x3 + 1;
thrd1_i4 = thrd1_i3 + 1;
}
thrd2_x1 = 0;
thrd2_i1 = 0;
if (thrd2_i1 < 3) {
thrd2_x2 = thrd2_x1 + 1;
thrd2_i2 = thrd2_i1 + 1;
}
if (thrd2_i2 < 3) {
thrd2_x3 = thrd2_x2 + 1;
thrd2_i3 = thrd2_i2 + 1;
}
if (thrd2_i3 < 3) {
thrd2_x4 = thrd2_x3 + 1;
thrd2_i4 = thrd2_i3 + 1;
}
thread 1 thread 2
4 / 26
Contents
TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions
5 / 26
TCBMC
TCBMC (Threaded-C Bounded Model Checking) TCBMC bounds the number of context switches
Claim : most bug patterns have only a few context switches. TCBMC allows context switches to be anywhere in the code. Different models are needed
We need to apply TCBMC for three times for detecting regular bugs (assert) data races deadlocks
Changki Hong @ pswlab TCBMC
6 / 26
TCBMC
Context switch block A set of consecutive lines of code executed with no interleaving
context switch
Changki Hong @ pswlab TCBMC
Context switch block 0
Context switch block 2
Context switch block 4
Context switch block 1
Context switch block 3
Context switch block 5
Thread 0 Thread 1
thrd1_x1 = 0;
thrd1_i1 = 0;
if (thrd1_i1 < 3) {
thrd1_x2 = thrd1_x1 + 1;
thrd1_i2 = thrd1_i1 + 1;
}
if (thrd1_i2 < 3) {
thrd1_x3 = thrd1_x2 + 1;
thrd1_i3 = thrd1_i2 + 1;
}
if (thrd1_i3 < 3) {
thrd1_x4 = thrd1_x3 + 1;
thrd1_i4 = thrd1_i3 + 1;
}
thrd2_x1 = 0;
thrd2_i1 = 0;
if (thrd2_i1 < 3) {
thrd2_x2 = thrd2_x1 + 1;
thrd2_i2 = thrd2_i1 + 1;
}
if (thrd2_i2 < 3) {
thrd2_x3 = thrd2_x2 + 1;
thrd2_i3 = thrd2_i2 + 1;
}
if (thrd2_i3 < 3) {
thrd2_x4 = thrd2_x3 + 1;
thrd2_i4 = thrd2_i3 + 1;
}
thread 1 thread 2
CSB 0
CSB 2
CSB 4
CSB 1
CSB 3
CSB 5
7 / 26
Template variable threadt_cs
threadt_cs(l) associate with each line l in the template a variable threadt_cs(l).
The value of threadt_cs(l) indicates the number of context switches that occurred before this line was executed.
threadt_cs(l) variables determine where the context switches occur.
The value of threadt_cs(l) will be decided by SAT solver using following constraints :
Monotonicity : 8l. threadt_cs(l) · threadt_cs(l+1) Interleaving bound : There is a bound on the number of context switches n.
8l. threadt_cs(l) · n
Parity : For two threads, the value of threadt_cs(l) can be restricted to be even for t = 0 and odd for t = 1.
8l. (threadt_cs(l) mod 2) = t
Extend the definition of threadt_cs(l)
threadt_cs(vj) = threadt_cs(lvj), where lvj
is the line in which vj is assigned.
Changki Hong @ pswlab TCBMC
8 / 26
Context switch block
Changki Hong @ pswlab TCBMC
Context switch block 0
Context switch block 2
Context switch block 4
Context switch block 1
Context switch block 3
Context switch block 5
Thread 0 Thread 1thread0_cs 0
00
2222222222
44444
1111111
3333
5555555
thread1_cs
9 / 26
The translation stages
Translation process of TCBMC Stage 1 - Preprocessing
A C statement which accesses more than one global variables is not always executed as an atomic statement.
Ex) Suppose each xi are global variables and ri are registers.
context switch may occur between these instructions
To allow such context switches in TCBMC, we need to break statements just as a complier does by introducing new temporary local variable.
Changki Hong @ pswlab TCBMC
x1 = x2 + x3; ra x2; rb x3; rc ra + rb; x1 rc;
x1 = x2 + x3; y1 = x2; y2 = x3; x1 = y1 + y2;
10 / 26
The translation stages
Stage 2 - Applying CBMC seperately on each thread. generates a list of constraints for each thread applying CBMC template : a list of constraints generated for each thread template has four types of statements:
1. local variable local variable(s) ex) y1 = (guardr? z0: y0);
2. global variable local variable(s) ex) x1 = (guardr? z0: x0);
3. local variable global variable(s) ex) y1 = (guardr? x2 : y0)
4. guard variable guard variable and global variable(s) ex) guard1 = guard0 && (x1 > y0)
Changki Hong @ pswlab TCBMC
global variables : each xi
local variables : each yi, zi
11 / 26
Global variables
Stage 3 - Generating constraints for concurrency Handling global variables using concept of context switch block The bound n is the number of context switches define n new variables x_vali for each global variable x (0 · i < n)
x_vali is the value of variable x at the end of the i-th context switch block.
The value of x in context switch block i+1 is initialized to x_vali.
Changki Hong @ pswlab TCBMC
12 / 26
The translation stages
Stage 3 - Generating constraints for concurrency (cond.) Translate each statement in the template (stage 2) into a constraints.
1. local variable local variable(s)- Simply add the thread prefix threadt. (to avoid name collision)
- y1 = (guardr? z0: y0);
threadt_y1 = (threadt_guardr? threadt_z0: threadt_y0);
Changki Hong @ pswlab TCBMC
global variables : each xi
local variables : each yi, zi
thread1() {
if(y%2 == 0)
y = z;
else ;
} thread1_guard0 = (thread1_y0%2 == 0);
thread1_y1 = (thread1_guard0? thread1_z0 : thread1_y0);
guard0 = (y0%2 == 0);
y1 = (guard0? z0 : y0);
13 / 26
The translation stages
2. global variable local variable(s)
- If the assignment to x0 is in the same context switch block as the
assignment x1, the thread prefix can simply be added.
- Otherwise, the x_val of the previous context switch block should be used
for the value of x0
- x1 = (guardr? z0: x0);
Changki Hong @ pswlab TCBMC
threadt_x1 = if (threadt_guardr) threadt_z0 ;
else if (threadt_cs(x1) == threadt_cs(x0))
threadt_x0 ; else
x_val ;
(threadt_cs(x1)-1)
int x;
thread1() {
if(y%2 == 0)
x = z;
else ;
}
thread1_guard0 = (thread1_y0%2 == 0);
thread1_x1 = if (thread1_guard0)
thread1_z0 ;
else
if (thread1_cs(x1) == thread1_cs(x0))
thread1_x0 ;
else
x_val ;
guard0 = (y0%2 == 0);
x1 = (guard0? z0 : x0);
(thread1_cs(x1)-1)
14 / 26
The translation stages
3. local variable global variable(s)
- If the assignment to y1 is in the same context switch block as the
assignment x2, the thread prefix can simply be added.
- Otherwise, the x_val of the previous context switch block should be used
for the value of x2
- y1 = (guardr? x2 : y0)
4. guard variable guard variable and global variable(s)
- ex) guard1 = guard0 && (x1 > y0)
- treat as third item.
Changki Hong @ pswlab TCBMC
threadt_y1 = if (threadt_guardr) if (threadt_cs(y1) == threadt_cs(x2))
threadt_x2 ; else
x_val ; else
threadt_y0 ;
(threadt_cs(y1)-1)
15 / 26
Example
Changki Hong @ pswlab TCBMC
int x;
int i;
thread1() {
x=0;
for (i=0; i<3; i++)
x++;
}
thread2() {
x=0;
for (i=0; i<3; i++)
x--;
}
thread1_x1 = 0;
thread1_i1 = 0;
thread1_guard1 =
if (thread1_cs(thread1_guard1)
== thread1_cs(thread1_i1))
(thread1_i1 < 3);
else
(i_val(thread1_cs(thread1_guard1)-1) < 3);
thread1_x2 =
if (thread1_guard1)
if (thread1_cs(x2) == thread1_cs(x1))
thread1_x1 + 1;
else
x_val + 1;
else
if (thread1_cs(x2) == thread1_cs(x1))
thread1_x1;
else
x_val ;
...
thread2_x1 = 0;
thread2_i1 = 0;
thread2_guard1 =
if (thread2_cs(thread2_guard1)
== thread2_cs(thread2_i1))
(thread2_i1 < 3);
else
(i_val(thread2_cs(thread2_guard1)-1) < 3);
thread2_x2 =
if (thread2_guard1)
if (thread2_cs(x2) == thread2_cs(x1))
thread2_x1 - 1;
else
x_val - 1 ;
else
if (thread2_cs(x2) == thread2_cs(x1))
thread2_x1;
else
x_val ;
...
Monotonicity : threadt_cs(l) · threadt_cs(l+1)Interleaving bound : threadt_cs(l) · nParity : (threadt_cs(l) mod 2) = t
+(thread1_cs(x2)-1)
(thread1_cs(x2)-1) (thread2_cs(x2)-1)
(thread2_cs(x2)-1)
16 / 26
Contents
TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions
17 / 26
Modeling synchronization primitives
Modeling atomic section Do not allow context switch in the section marked with atomic.
just add constraints that force the threadt_cs values of the lines in an atomic section to be identical.
Changki Hong @ pswlab TCBMC
1 atomic {
2 x1 = y1;
3 x2 = y2;
4 }
add additional constraints:
thread1_cs(1) = thread1_cs(2);
thread1_cs(2) = thread1_cs(3);
thread1_cs(3) = thread1_cs(4);
thread 1
18 / 26
Modeling synchronization primitives
Modeling mutex A mutex has two states, L(locked) and U(unlocked) Lock operation : Lock waits until the mutex is in state U and changes its
state to L. Unlock operation : Unlock is applied to a mutex in state L and changes its
state to U.
Changki Hong @ pswlab TCBMC
atomic {
assume(mutex==U);
mutex = L;
}
atomic {
assert(mutex==L);
mutex = U;
}
lock (mutex) unlock (mutex)
19 / 26
Contents
TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions
20 / 26
Verifying race conditions
Race condition A race condition is a state in which the next instruction of different threads
access the same memory location and at least one of them is a write. Detecting races
add to each global variable x a new global bit variable x_write_flag. x_write_flag is raised whenever x is assigned to some value and lowered
in the next instruction. on every access to x we assert that its x_write_flag is low.
Changki Hong @ pswlab TCBMC
atomic {
assert(x_write_flag==0);
x_write_flag=1;
x=3;
}
x_write_flag=0;
assert(x_write_flag==0);
y = x;
Translation of x = 3
Translation of y = x
21 / 26
Verifying Deadlocks
Deadlock Global deadlocks
All the threads are waiting for a mutex Local deadlocks
Some of threads form a waiting cycle ex) thread 1 is waiting for mutex ma which is held by thread 2 which is
waiting for mutex mb which is held by thread 1
Finding deadlocks Model should be changed
Model of lock() function we learnt was implemented by assume() function Global deadlock occurs when all threads are in a waiting state. We must change the modeling of lock() function. trds_in_wait : global counter for the number of threads in wait state. When modeling lock(m), if mutex m is already in state L
increase trds_in_wait assert that trds_in_wait < Total number of threads If the assertion fails, a global deadlock was detected.
Changki Hong @ pswlab TCBMC
22 / 26
Modeling of lock for deadlock detection
lock(mutex)
Changki Hong @ pswlab TCBMC
if(!dd) {//dd = deadlock_detected
atomic {
unlocked = (mutex == U);
if(unlocked) mutex = L
else trds_in_wait++;
}
atomic {
if(!unlocked) {
dd = (trds_in_wait == T);
assert(!dd);
}
}
}
23 / 26
Contents
TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions
24 / 26
Experimental results
TCBMC v.s. Zing
Concurrent implementation of bubble sort Bugs are dependent on both data and the interleaving. Two threads. TCBMC scales better with respect to integer widths TCBMC performs better for detecting bugs dependent on both data and
interleavings
Changki Hong @ pswlab TCBMC
*Windows operating system, Pentium4 1.8Ghz with 1GB memory**Linux operating system, Pentium4 2Ghz with 250MB memory
* **
25 / 26
Contents
TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions
26 / 26
Conclusions
TCBMC extended CBMC to verify concurrent C programs.
TCBMC bounds the number of context switches among threads.
Using TCBMC, we can detect safety properties, races and deadlocks which is crucial for concurrent programs.
Changki Hong @ pswlab TCBMC
top related