bounded model checking of concurrent programs

26
Bounded Model Checking of Concurrent Programs Ishai Rabinovitz and Orna Grumberg CAV ‘05 Presented by Changki Hong

Upload: walda

Post on 14-Jan-2016

60 views

Category:

Documents


0 download

DESCRIPTION

Bounded Model Checking of Concurrent Programs. Ishai Rabinovitz and Orna Grumberg CAV ‘05 Presented by Changki Hong. Software Model Checking. Main trends in formal verification SAT-based Bounded Model Checking (BMC) leading technique for model checking of hardware - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Bounded Model Checking of Concurrent Programs

Bounded Model Checking of Concurrent Programs

Bounded Model Checking of Concurrent Programs

Ishai Rabinovitz and Orna Grumberg

CAV ‘05

Presented by Changki Hong

Page 2: Bounded Model Checking of Concurrent Programs

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

Page 3: Bounded Model Checking of Concurrent Programs

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

Page 4: Bounded Model Checking of Concurrent Programs

4 / 26

Contents

TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions

Page 5: Bounded Model Checking of Concurrent Programs

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

Page 6: Bounded Model Checking of Concurrent Programs

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

Page 7: Bounded Model Checking of Concurrent Programs

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

Page 8: Bounded Model Checking of Concurrent Programs

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

Page 9: Bounded Model Checking of Concurrent Programs

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;

Page 10: Bounded Model Checking of Concurrent Programs

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

Page 11: Bounded Model Checking of Concurrent Programs

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

Page 12: Bounded Model Checking of Concurrent Programs

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);

Page 13: Bounded Model Checking of Concurrent Programs

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)

Page 14: Bounded Model Checking of Concurrent Programs

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)

Page 15: Bounded Model Checking of Concurrent Programs

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)

Page 16: Bounded Model Checking of Concurrent Programs

16 / 26

Contents

TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions

Page 17: Bounded Model Checking of Concurrent Programs

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

Page 18: Bounded Model Checking of Concurrent Programs

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)

Page 19: Bounded Model Checking of Concurrent Programs

19 / 26

Contents

TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions

Page 20: Bounded Model Checking of Concurrent Programs

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

Page 21: Bounded Model Checking of Concurrent Programs

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

Page 22: Bounded Model Checking of Concurrent Programs

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);

}

}

}

Page 23: Bounded Model Checking of Concurrent Programs

23 / 26

Contents

TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions

Page 24: Bounded Model Checking of Concurrent Programs

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

* **

Page 25: Bounded Model Checking of Concurrent Programs

25 / 26

Contents

TCBMC Modeling Synchronization Primitives Verifying Race Conditions and Deadlocks Experimental Results Conclusions

Page 26: Bounded Model Checking of Concurrent Programs

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