1 Model Checking Multithreaded C Code with SPIN Anna Zaks & Rajeev Joshi SPIN 2008 10 August, Los Angeles, USA
Dec 21, 2015
1
Model Checking Multithreaded C Code with SPIN
Anna Zaks & Rajeev Joshi
SPIN 2008
10 August, Los Angeles, USA
Checking Multithreaded C Code
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; for (;;) { *(d.f0)=1; sh_last=d.last ; while (*(d.f1)==1 && (last==d.last)) { ; /* busy wait */ } /* critical section */ d.f0=0; }}…
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
express design as
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; }...
2
Checking Multithreaded C Code
Model-Driven Verification
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;
for (;;) { *(d.f0)=1; sh_last=d.last ; while (*(d.f1)==1 && (last==d.last)) { ; /* busy wait */ } /* critical section */ d.f0=0; }}…
Ref: Model-Driven Software Verification, G.J.Holzmann & R.Joshi, SPIN 2004
c_decl { extern void * run_thread0 (void *); extern void * run_thread1 (void *); } ;
...active proctype main() { init() ; do :: choose(thread0) -> c_code {run_thread0 (); } :: choose(thread1) -> c_code {run_thread1 (); } ... od}
3
Embed C code within PROMELA - C code is executed by SPIN during search
Main drawback:• Not useful for verification of multithreaded C programs• Need to explore the interleavings within the function
Checking Multithreaded C Code
Our Solution – Introducing pancamBuild 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
4
Checking Multithreaded C Code
The LLVM Compiler Infrastructure pancam interprets optimized LLVM bytecode (a typed bytecode language)
catches errors that manifest themselves only after the optimization phase
5
Ref: LLVM compiler (originated from University of Illinois Urbana-Champaign), http://llvm.org
/* 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;}}
6
The pancam Checker
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
Spin(pan.c)
Spin(pan.c)
take_step (thread_id, granularity, &state)
&statepancampancam
Checking Multithreaded C Code
Checking Multithreaded C Code
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}
7
Checking Multithreaded C Code
Program State cs[N]
8
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}
global state
systemheap
program stack
FREE
Checking Multithreaded C Code
Addressing State Space Explosion
Three Strategies support user-defined abstraction functions
use context-bounded checking
do on-the-fly partial-order reduction
9
Checking Multithreaded C Code
User Defined Abstractions
c_track “cs” “N” “UnMatched”;c_track “as” “K” “Matched”;
as is populated through the user defined function
compute_abst(void *as)
Abstract Stateas[K]
10
Concrete State cs[N]
systemheap
program stack
FREEuser
defined
cs is stored on Spin’s stack, which is used for DFS backtracking as is used for state hashing
global state
Checking Multithreaded C Code
Context-Bounded Checking
Enforce upper bound on number of allowed preemptivecontext-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
11
Ref: Iterative context bounding for systematic testing of multithreaded programs,
M. Musuvathi, S. Qadeer, POPL 2007
Checking Multithreaded C Code
pancam Implementation of Context Bounding
Implemented as an optional extension
• requires no modification to Spin
12
Checking Multithreaded C Code
Experimental Results: Context Bounding
peterson.c without abstraction
13
Checking Multithreaded C Code
On-the-fly Partial-order Reduction
pancam “transitions” have no structure :
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
SpinSpintake_step (th_id, s)
s’ pancampancam
Checking Multithreaded C Code
On-the-fly Partial-order Reduction
pancam “transitions” have no structure :
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?
SpinSpintake_step (th_id, s)
s’ pancampancam
Checking Multithreaded C Code
Superstep Reduction: Key Ideas
Unlike classical POR, which considers subsets of enabled transitions from state s, we consider subsets of enabled finite paths from s
16
S
1
2
Checking Multithreaded C Code
Superstep Reduction: Key Ideas
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
17
S
1
2
Checking Multithreaded C Code
Superstep Reduction: Key Ideas
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
18
S
1
2
Checking Multithreaded C Code
Superstep Requirments
Compute superstep i for each enabled thread i
a superstep is finite and nonempty
only the last transition in a superstepmay conflict with transitions in other supersteps
only the last transition of a superstepcan be visible
From these, we can show thatsuperstep reduction is sound and complete for checking any LTL property without the next-time operator
19
Can be seen as an extension of the Cartesian partial-order reduction to LTLRef: Cartesian partial-order reduction, G. Gueta, C. Flanagan, E. Yahav, M. Sagiv, SPIN
2007
Checking Multithreaded C Code
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
20
Checking Multithreaded C Code
Experimental Results: Superstep Reduction
21
robots.c benchmark
Checking Multithreaded C Code
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
22
Checking Multithreaded C Code
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
23
Checking Multithreaded C Code
Questions?
24
25
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
Given a state s, choose Cap(s) - a subset of finite prefixes of paths from s:
: paths from s : ( , : Cap(s) ext(): )
S
1
2
26
Reduced System
Given a transition state graph M = S, T, S0, L
The reduced graph M‘ = S, T’, S0, L , such that
T’ = { s : sS, 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'
27
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
28
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’)
s
r’
r
L(r)
L(s) L(s)
L(r)
29
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’)
No need to show the intermediate states
Path is substituted by one superstep transition
s
s
r’
r
L(r)
L(s)
L(r)