Slide - NYU Computer Science

Model Checking Multithreaded C Code with SPIN
Anna Zaks & Rajeev Joshi
SPIN 2008
10 August, Los Angeles, USA
1
The Goal: Check Multithreaded C Code
/* Peterson's algorithm (adapted from Wikipedia) */
static int sh_f0, sh_f1, sh_last;
void * run_thread0 () {
struct pa_desc d;
d.f0 = &sh_f0;
d.f1 = &sh_f1;
d.last = 1;
}
…
express design as
for (;;) {
*(d.f0)=1;
sh_last=d.last ;
while (*(d.f1)==1 && (last==d.last)) {
; /* busy wait */
}
/* critical section */
d.f0=0;
}
a PROMELA
model
bool turn, flag[2];
active proctype run_thread0 () {
again:
flag[0] = 1;
turn = 1;
(flag[1] == 0 || turn == 0) ->
/* busy wait */
/* critical section */
flag[0] = 0;
goto again;
}
...
Limitations
– need to redo manual translation whenever implementation changes
– the absence of errors in the design does not guarantee that the
implementation (the executable) is error free
Checking Multithreaded C Code
2
Model-Driven Verification
Embed C code within PROMELA - C code is executed by SPIN during search
static int sh_f0, sh_f1, sh_last;
c_decl {
extern void * run_thread0 (void *);
extern void * run_thread1 (void *);
} ;
void * run_thread0 () {
struct pa_desc d;
d.f0 = &sh_f0;
d.f1 = &sh_f1;
d.last = 1;
}
…
for (;;) {
*(d.f0)=1;
sh_last=d.last ;
while (*(d.f1)==1 && (last==d.last)) {
; /* busy wait */
}
/* critical section */
d.f0=0;
}
...
active proctype main() {
init() ;
do
:: choose(thread0) -> c_code {run_thread0 (); }
:: choose(thread1) -> c_code {run_thread1 (); }
...
od
}
Main drawback:
• Not useful for verification of multithreaded C programs
• Need to explore the interleavings within the function
Ref: Model-Driven Software Verification, G.J.Holzmann & R.Joshi, SPIN 2004
Checking Multithreaded C Code
3
Our Solution – Introducing pancam
Build pancam interpreter that can be embedded within an existing model checker
pancam inherits all SPIN optimizations and future enhancements:



bit-state verification
hash compression
multi-core checking
pancam does not rely on any customization of SPIN
Checking Multithreaded C Code
4
The LLVM Compiler Infrastructure
pancam interprets optimized LLVM bytecode (a typed bytecode language)
catches errors that manifest themselves only after the optimization phase
/* Peterson's algorithm (adapted from Wikipedia) */
static
volatile
int sh_f0, sh_f1, sh_last;
void * run_thread0 () {
struct pa_desc d;
d.f0 = &sh_f0;
d.f1 = &sh_f1;
d.last = 1;
}}
for (;;) {
*(d.f0)=1;
sh_last=d.last ;
while (*(d.f1)==1 && (sh_last==d.last)) {
; /* busy wait */
}
/* critical section */
d.f0=0;
Ref: LLVM compiler (originated from University of Illinois Urbana-Champaign), http://llvm.org
Checking Multithreaded C Code
5
The pancam Checker
take_step (thread_id, granularity, &state)
Spin
(pan.c)
&state
pancam
SPIN orchestrates the state space search
- decides which thread to execute next
- stores visited states in the hash
- restores to the previous step during DFS backtracking
pancam computes the transition by code interpretation
- can execute any number of instructions of a specific thread
- can check predicates at any point
Checking Multithreaded C Code
6
Spin Model for pancam
active proctype main() {
c_code {
pancam_init(“petersons.bc”);
init_thread(0, “run_thread0”);
init_thread(1, “run_thread1”);
};
do
:: c_expr { is_enabled(0) } -> c_code { take_step(0); }
:: c_expr { is_enabled(1) } -> c_code { take_step(1); }
od
}
Checking Multithreaded C Code
7
enabled
Program State cs[N]
global
state
system
heap
FREE
program
stack
c_track “cs” “N” “Matched”;
active proctype main() {
c_code {
pancam_init(“petersons.bc”);
init_thread(0, “run_thread0”);
init_thread(1, “run_thread1”);
};
do
:: c_expr { is_enabled(0) } -> c_code { take_step(0); }
:: c_expr { is_enabled(1) } -> c_code { take_step(1); }
od
}
Checking Multithreaded C Code
8
Addressing State Space Explosion
Three Strategies
 support user-defined abstraction functions
 use context-bounded checking
 do on-the-fly partial-order reduction
Checking Multithreaded C Code
9
enabled
User Defined Abstractions
global
state
system
heap
FREE
Concrete State cs[N]
program
stack
user
defined
Abstract State
as[K]
as is populated through the user defined function
compute_abst(void *as)


cs is stored on Spin’s stack, which is used for DFS backtracking
as is used for state hashing
c_track “cs” “N” “UnMatched”;
c_track “as” “K” “Matched”;
Checking Multithreaded C Code
10
Context-Bounded Checking
Enforce upper bound on number of allowed preemptive
context-switches

a switch from p to q is preemptive provided p is enabled

explore state space exhaustively with increasingly larger bounds

works well in practice - most concurrency bugs can be triggered with a
small number of switches
Ref: Iterative context bounding for systematic testing of multithreaded programs,
M. Musuvathi, S. Qadeer, POPL 2007
Checking Multithreaded C Code
11
pancam Implementation of Context Bounding
Implemented as an optional extension
•
requires no modification to Spin
Checking Multithreaded C Code
12
Experimental Results: Context Bounding
peterson.c without abstraction
Checking Multithreaded C Code
13
On-the-fly Partial-order Reduction
pancam “transitions” have no structure :
take_step (th_id, s)
Spin
s’
pancam
c_code { take_step (th_id, s); }
Spin’s traditional partial-order reduction doesn’t apply
-
even if we modified Spin, computing independence relation is too hard
Shift the burden to pancam by

increasing the granularity of a “pancam step”

hiding unnecessary states from Spin
Checking Multithreaded C Code
On-the-fly Partial-order Reduction
pancam “transitions” have no structure :
take_step (th_id, s)
Spin
s’
pancam
c_code { take_step (th_id, s); }
Spin’s traditional partial-order reduction doesn’t apply
-
even if we modified Spin, computing independence relation is too hard
Shift the burden to pancam by

increasing the granularity of a “pancam step”

hiding unnecessary states from Spin
Example

execute a thread until it accesses a global variable or the shared heap

Can we do better?
Checking Multithreaded C Code
Superstep Reduction: Key Ideas
S
1

2
Unlike classical POR, which considers subsets of enabled transitions from
state s, we consider subsets of enabled finite paths from s
Checking Multithreaded C Code
16
Superstep Reduction: Key Ideas
S
1
2

Unlike classical POR, which considers subsets of enabled transitions from
state s, we consider subsets of enabled finite paths from s

Each selected path is replaced with a single superstep transition
Checking Multithreaded C Code
17
Superstep Reduction: Key Ideas
S
1
2

Unlike classical POR, which considers subsets of enabled transitions from
state s, we consider subsets of enabled finite paths from s

Each selected path is replaced with a single superstep transition

The conflicts (dependencies) are computed dynamically
Checking Multithreaded C Code
18
Superstep Requirments
Compute superstep i for each enabled thread i

a superstep is finite and nonempty

only the last transition in a superstep
may conflict with transitions in other supersteps

only the last transition of a superstep
can be visible
From these, we can show that
superstep reduction is sound
and complete for checking any
LTL property without the nexttime operator
Can be seen as an extension of the Cartesian partial-order reduction to LTL
Ref: Cartesian partial-order reduction, G. Gueta, C. Flanagan, E. Yahav, M. Sagiv, SPIN 2007
Checking Multithreaded C Code
19
Efficient DFS Implementation

DFS is essential for liveness support

Precomputing the supersteps leads to run time overhead


Supersteps are computed on-the-fly using a scheme that
maintains bookkeeping information across Spin backtracking
steps
no modification to SPIN is required
Checking Multithreaded C Code
20
Experimental Results: Superstep Reduction
robots.c benchmark
Checking Multithreaded C Code
21
Other Related Work

Modex tool extracts PROMELA models from C implementations
A practical method for verifying event-driven software, G. Holzmann, M. Smith, SE1999

Java Pathfinder integrates model checking with the virtual machine
Model checking programs, W. Visser, K. Havelund, G. Brat, S. Park, F. Lerda, ASE 2003

VeriSoft [God97] and Inspect [YCGK07] tools are state-less model checkers for C
Model checking for programming languages using VeriSoft, P. Godefroid, POPL 1997
Dynamic partial-order reduction for model checking software, C. Flanagan, P. Godefroid, POPL 2005

CHESS model checker for concurrent C code checks for livelocks
Fair stateless model checking, M. Musuvathi, S. Qadeer, PLDI 2008

CMC explicit-state model checking requires manual translation from C
A pragmatic approach to model checking real code, M. Musuvathi, et al., OSDI 2002

In CodeSurfer tool, program analysis is applied to a model constructed from an executable
Wysinwyx : What you see is not what you execute, G. Balakrishnan, et al., VSTTE 2005
Checking Multithreaded C Code
22
Summary


First version of pancam completed

implements abstraction support, context-bounding, superstep reduction

applied to several small programs (~200 lines of C)

applied to an inter-process communication module (~2800 lines of C)

fixed bug in Wikipedia implementation of Peterson’s protocol

extended the tool to support liveness properties
Ongoing work

reduce the size of a concrete state

combine superstep reduction with static POR

make some conservative approximations to reduce overhead of POR

reduce run time overhead
Checking Multithreaded C Code
23
Questions?
Checking Multithreaded C Code
24
Cap Sets

Unlike classical POR, which looks at subsets of enabled
transitions from state s, we look at subsets of enabled finite paths
from s
S

1
2


Given a state s, choose Cap(s) - a subset of finite prefixes of
paths from s:
:   paths from s : ( ,  :   Cap(s)    ext():    )
25
Reduced System

Given a transition state graph M =  S, T, S0, L 

The reduced graph M‘ =  S, T’, S0, L , such that
T’ = { s   : sS, Cap(s) } , where s   is a superstep
transition summarizing execution of path 

If M and M' are stuttering equivalent, for any LTL formula Af
without the next time operator, and every initial state s:
s╞ Af in M if and only if s╞ Af in M'
26
Independence Requirement
[:   paths from s : ( ,  :   Cap(s)    ext():   ); let  =  ]
Independence Requirement:
transitions of    are independent from 

     is enabled at s, and results in the same state as 

then choose  =     
s


r’

r

27
Visibility Requirement
[ have to show that (    )  (     ) ]
Visibility Requirement:
both  and  have the same visible transition and at most one is allowed

All states on the paths  and   can be partitioned into two sets Seq
and Req:

 s’  Seq: L(s) = L(s’)

 r’  Req: L(r) = L(r’)
L(s)

L(r)


r
L(s)
s

r’
L(r)
28
Visibility Requirement
[ have to show that (    )  ( s    ) ]
Visibility Requirement:
both  and  have the same visible transition and at most one is allowed

All states on the paths  and   can be partitioned into two sets
Seq and Req:

 s’  Seq: L(s) = L(s’)

 r’  Req: L(r) = L(r’)
L(s)

No need to show the intermediate states

Path  is substituted by one superstep transition

s

L(r)
s
r’

r
L(r)
29