Infinite State Model Checking with Presburger Arithmetic Constraints Tevfik Bultan

advertisement
Infinite State Model Checking with
Presburger Arithmetic Constraints
Tevfik Bultan
Department of Computer Science
University of California, Santa Barbara
Joint Work with My Students
• Action Language Verifier
– Tuba Yavuz-Kahveci (PhD 2004)
– Constantinos Bartzis (PhD 2004)
• Design for verification
– Aysu Betin-Can (PhD 2005)
Infinite State Model Checking?
• Model checking started as a finite state verification
technique
• Advantages of finite state systems:
– Exhaustive state enumeration is possible for finite state
systems
• Disadvantages of infinite state systems:
– Verification problems that are computable for finite state
systems are uncomputable for infinite state systems
Why Care About Infinity?
• Computer systems do not have infinite memory or infinite
time
– So why care about infinity?
• Infinity is an abstraction
– Abstraction is at the core of computer science
• Computers are built with layers of abstractions
– Abstraction is necessary for design
– Abstraction is necessary for analysis
Why Care About Infinity?
• Reason 1:
– Enables us to check a specification with respect to an
arbitrarily large number of components or memory
• For example, arbitrary number of threads
• Reason 2:
– Rather than developing verification techniques that rely
on the bound of the state space to terminate
• Enables us to develop infinite state verification
techniques that terminate independent of the bound
• A technique which is guaranteed to terminate is not
helpful if it runs out of memory
An Example
• A simple example that demonstrates
limitations of (finite state) model
checkers
x’=x+1
State0
State1
x’=x+1
Initial: x=0  State0
P: AG(State1  x is odd)
P: AG(State1  ( . x =2+1))
• Property P can be verified with an
infinite state model checker that uses
standard backward fixpoint
computations
• Fixpoint computation for some
properties
– for example, AG(State1  x 6)
may not converge but we can use
conservative approximations
Outline
•
•
•
•
•
•
Model checking with arithmetic constraints
Conservative approximations
Automata representation for arithmetic constraints
Composite representation
Action Language Verifier (ALV)
Checking synchronization in concurrent programs with ALV
Symbolic Model Checking
[McMillan et al. LICS 1990]
• Represent sets of states and the transition relation as
Boolean logic formulas
• Forward and backward fixpoints can be computed by
iteratively manipulating these formulas
– Forward, backward image: Existential variable
elimination
– Conjunction (intersection), disjunction (union) and
negation (set difference), and equivalence check
• Use an efficient data structure for manipulation of Boolean
logic formulas
– BDDs
Symbolic Model Checking
• What do you need to compute fixpoints?
Symbolic
Symbolic
Symbolic
Boolean
Symbolic
Conjunction(Symbolic,Symbolic)
Disjunction(Symbolic,Symbolic)
Negation(Symbolic)
EquivalenceCheck(Symbolic,Symbolic)
Precondition(Symbolic)
• Precondition (i.e., EX) computation is handled by:
– variable renaming, followed by conjunction, followed by
existential variable elimination
• Infinite state model checking: Use a symbolic
representation that is capable of representing infinite sets
and supports the above functionality
Linear Arithmetic Constraints
• Linear arithmetic formulas can represent (infinite) sets of
valuations of unbounded integers
• Linear integer arithmetic formulas on can be stored as a set
of polyhedra
F f kl
k l
f kl is a linear equality or inequality constraint
where each

v

a  x  c
i
i1
and each
 f kl
l
i
v
a  x  c
i
i
i1
is a polyhedron

xi integer variable, ai coefficient, c constant


A Linear Arithmetic Constraint Manipulator
• Omega Library [Pugh et al.]
– A tool for manipulating Presburger arithmetic formulas:
First order theory of integers without multiplication
– Equality and inequality constraints are not enough
– Divisibility constraints are also needed
v
y( a  x  yc)
i
i
i1
v
• which means:

a  x
i 1
i
i
is divisible by
c
Integers are Complicated
x – 5  2y
y
2y  x – 1
x  3y
3y  x + 7
3
29
dark shadow
real shadow
x
Presburger Arithmetic Model Checking
[Bultan et al. CAV’97, TOPLAS’99]
• Use linear arithmetic constraints as a symbolic
representation
• Use a Presburger arithmetic manipulator as the symbolic
engine (Omega library)
• Compute fixpoints to verify or falsify CTL properties
• Use conservative approximations to achieve convergence
What About Using BDDs for Encoding Arithmetic
Constraints?
• Arithmetic constraints on bounded integer variables can be
represented using BDDs
• Use a binary encoding
– represent integer x as x0x1x2... xk
– where x0, x1, x2, ... , xk are binary variables
– You have to be careful about the variable ordering!
• BDDs and constraint representations are both applicable
– Which one is better?
Arithmetic Constraints vs. BDDs
[Bultan TACAS’00]
Arithmetic Constraints vs. BDDs
Arithmetic Constraints vs. BDDs
• Constraint based verification can be more efficient than
BDDs for integers with large domains
• Constraint based verification can be used to automatically
verify infinite state systems
– cannot be done using BDDs
• However, BDD-based verification is more robust and the
arithmetic constraint representation has two problems:
• Problem 1: Constraint based verification does not scale
well when there are boolean or enumerated variables in
the specification
• Problem 2: Price of infinity
– CTL model checking becomes undecidable for infinite
domains
Outline
•
•
•
•
•
•
Model checking with arithmetic constraints
Conservative approximations
Automata representation for arithmetic constraints
Composite representation
Action Language Verifier (ALV)
Checking synchronization in concurrent programs with ALV
Conservative Approximations
• Compute a lower ( p ) or an upper ( p+ ) approximation to
the truth set of the property ( p )
Conservative Approximations
• Compute a lower ( p ) or an upper ( p+ ) approximation to
the truth set of the property ( p )
• There are three possible outcomes:
I
p
p
1) “The property is satisfied”
Conservative Approximations
• Compute a lower ( p ) or an upper ( p+ ) approximation to
the truth set of the property ( p )
• There are three possible outcomes:
I
p
I
p
1) “The property is satisfied”
sates which
violate the
property
I
p
3) “I don’t know”
p
p+
 p
2) “The property is false and here is a counter-example”
p
Conservative Approximations
• Compute a lower ( p ) or an upper ( p+ ) approximation to
the truth set of the property ( p )
• There are three possible outcomes:
I
p
I
p
1) “The property is satisfied”
sates which
violate the
property
I
p
3) “I don’t know”
p
p+
 p
2) “The property is false and here is a counter-example”
p
Conservative Approximations
• Truncated fixpoint computations
– To compute a lower bound for a least-fixpoint
computation
– Stop after a fixed number of iterations
• Widening
– To compute an upper bound for the least-fixpoint
computation
– We use a generalization of the polyhedra widening
operator by [Cousot and Halbwachs POPL’78]
Polyhedra Widening
y
xy
y5
1y
x4
Ai: x  y  x  4  y  5  1  y
x
Polyhedra Widening
y
xy
xy
y5
1y
x4
x5
Ai: x  y  x  4  y  5  1  y
Ai+1: x  y  x  5  y  5  1  y
y5
1y
x
Polyhedra Widening
y
xy
y5
1y
x4
x5
Ai: x  y  x  4  y  5  1  y
Ai+1: x  y  x  5  y  5  1  y
AiAi+1: x  y  y  5  1  y
x
Polyhedra Widening
y
xy
xy
y5
1y
x4
x5
Ai: x  y  x  4  y  5  1  y
Ai+1: x  y  x  5  y  5  1  y
AiAi+1: x  y  y  5  1  y
y5
1y
x
Ai  Ai+1 is defined as:
all the constraints in Ai
that are also satisfied by Ai+1
Outline
•
•
•
•
•
•
Model checking with arithmetic constraints
Conservative approximations
Automata representation for arithmetic constraints
Composite representation
Action Language Verifier (ALV)
Checking synchronization in concurrent programs with ALV
Automata Representation for Arithmetic
Constraints [Bartzis, Bultan CIAA’02, IJFCS ’02]
• Given an atomic linear arithmetic constraint in one of the
following two forms
a  x  c
v
i 1
i
i
v
a  x  c
i 1
i
i
we can construct an FA which accepts all the solutions to
the given constraint
• By combining such automata one can handle full
Presburger arithmetic
Basic Construction
• We first construct a basic state machine which
– Reads one bit of each variable at each step, starting
from the least significant bits
– and executes bitwise binary addition and stores the
carry in each step in its state
In my figures alphabet symbols are written vertically!
0
0
/
0
Example
x + 2y
010
+ 2  001
10 0
1
0
/
1
0
v
Number of states: O( | ai |)
i 1
0
1
/
0
0
0
/
1
1
1
/
1
0
1
/
1
1
0
/
0
1
0
1
/
0
1
1
/
0
0
0
/
0
1
0
/
1
2
1
1
/
1
Automaton Construction
• Equality With 0
– All transitions writing 1 go to a sink state
– State labeled 0 is the only accepting state
– For disequations (), state labeled 0 is the only rejecting
state
• Inequality (<0)
– States with negative carries are accepting
– No sink state
• Non-zero Constant Term c
– Same as before, but now -c is the initial state
– If there is no such state, create one (and possibly some
intermediate states which can increase the size by |c|)
Conjunction and Disjunction
• Conjunction and disjunction is handled by generating the
product automaton
001
0,1,1
Automaton for x-y<1
01
0,1
1
0
-1
00
0,1
0
11
0,1
01
0,1
0
0
1
-1
01
0,1
0
1
01
1,1
001
0,1,1
0
1
1
0
-1,-1
-2,-1
Automaton for
x-y<1  2x-y>0
01
0,1
-1,0
1
0
0
0
-2
1
0,-1
1
1
1
0
011
1,0,1
1
0
0
1
00
0,1
Automaton
for 2x-y>0
1
0
1
0
0
1
0
0
0
0
1
0
01
1,1
-2,0
1
1
1
0
-2,1
1
0
Other Extensions
• Existential quantification (necessary for pre and post)
– Project the quantified variables away
– The resulting FA is non-deterministic
• Determinization may result in exponential blowup of
the FA size but we do not observe this in practice
– For universal quantification use negation
• Constraints on all integers
– Use 2’s complement arithmetic
– The basic construction is the same
– In the worst case the size doubles
Experiments
• We implemented these algorithms using MONA [Klarlund et al]
• We integrated them to our infinite state model checker
• We compared our automata representation against
– the polyhedral representation used in the Omega library
– the automata representation used in LASH [Boigelot and
Wolper]
• we also integrated LASH to our model checker by
writing a wrapper around it
problem instance
li g
ht
co
nt
in
ro
se
l
rti
on
so
rt
si
s1
si
s3
pc
pc 5
10
rw
3
rw 2
64
ba
r
ba ber
r m
ba ber prb mp 1
er -2
m
p3
ba
ke
ba ry
k 2
ba ery -1
k e 3ry 1
41
ti c
k
ti c et2
k -1
ti c et3
k e -1
co
t
he 4-1
c o re
he nc
re enc 3
e4
time (seconds)
Experimental results
Construction time
1000
100
10
Omega
1
Our construction
based on MONA
LASH
0.1
0.01
problem instance
li g
ht
co
nt
in
ro
se
l
rti
on
so
rt
si
s1
si
s3
pc
pc 5
10
rw
3
rw 2
64
ba
r
ba ber
r m
ba ber prb mp 1
er -2
m
p3
ba
ke
ba ry
k 2
ba ery -1
k e 3ry 1
41
ti c
k
ti c et2
k -1
ti c et3
k e -1
co
t
he 4-1
c o re
he nc
re enc 3
e4
time (seconds)
Experimental results
Verification time
1000
100
10
Omega
1
Our construction
based on MONA
LASH
0.1
0.01
problem instance
li g
ht
co
nt
in
ro
se
l
rti
on
so
rt
si
s1
si
s3
rw
3
rw 2
64
pc
pc 5
10
ba
r
ba ber
r m
ba ber p-1
rb mp
er -2
m
p3
ba
ke
ba ry
k 2
ba ery -1
k e 3ry 1
41
ti c
k
ti c et2
k -1
ti c et3
k e -1
t4
co
-1
he
c o re
he nc
re enc 3
e4
memory (Mbytes)
Experimental results
Memory comsumption
100
10
Omega
1
0.1
Our construction
based on MONA
LASH
0.01
Efficient Pre- and Post-condition Computations
[Bartzis, Bultan CAV’03]
• Pre and post condition computations can cause an
exponential blow-up in the size of the automaton in the
worst case
• We do not observe this blow-up in the experiments
• We proved that for a common class of systems this blow
up does not occur
Assumptions About the Transition Relation
•
We assume that the transition relation of the input system
is a disjunction of formulas in the following form
guard(R)  update(R)
where
– guard(R) is a Presburger formula on current state
variables and
– update(R) is of the form
xi’=f(x1, …, xv) 
•

ji
xj’= xj
In asynchronous concurrent systems the transition relation
is usually in the above form
Three Classes of Updates
1. xi’ = c
2. xi’ = xi + c
3. xi’ =

v
j=1aj·
xj + c
We proved that
• Computation of pre is polynomial for all 3 cases
• Computation of post is polynomial for 2 and for 3,
whenever ai is odd.
Other Results Related to Automata Encoding
[Bartzis, Bultan TACAS’03, STTT]
• We developed efficient BDD construction algorithms and
proved bounds for the sizes of the BDDs for bounded
linear arithmetic constraints
– Given a linear arithmetic formula that contains n atomic
constraints on v bounded integer variables represented
with b-bits, the size of the BDD is:
n
v
O(vb |a |)
i, j
j 1 i 1
• These results explain why all three versions of SMV
(NuSMV, CMU SMV and Cadence SMV) are inefficient in

handling linear arithmetic constraints
– In SMV the BDD size could be exponential in b
Other Results Related to Automata Encoding
[CAV’04]
• We defined a widening operator for the automata
representation of arithmetic constraints
• The widening operator looks for similar states in two
consecutive iterations (Ai and Ai+1) and creates an
equivalence relation
– then it merges the states in the same equivalence class
• We can prove that for some cases this widening operator
computes the exact fixpoint
– for example for updates of the form x’=x+c
Example
module incr_1
integer y;
parameterized integer x;
initial: y=x;
incr_1: y'=y+1;
spec: AG(y>=x)
endmodule
• The sequence y=x, y=x  y=x+1, y=x  y=x+1  y=x+2,
… does not converge
• However we know that a fixpoint exists (yx) and is
representable as an arithmetic constraint
Widening
• Instead of computing a sequence A1, A2, … where
Ai+1=Aipost(Ai)
compute A’1, A’2, … where
A’i+1=A’i(A’ipost(A’i))
• By definition AB  AB
• The goal is to find a widening operator  such that:
– The sequence A’1, A’2, … converges
– It converges fast
– The computed fixpoint is as close as possible to the
exact set of reachable states
Widening Arithmetic Automata
• Given automata A and A’ we want to compute AA’
• We say that states k and k’ are equivalent (kk’) if either
– k and k’ can be reached from either initial state with the
same string (unless k or k’ is a sink state)
– or, the languages accepted from k and k’ are equal
– or, for some state k’’, kk’’ and k’k’’
• The states of AA’ are the equivalence classes of 
Example
01
0,1
y=x
0
0
1
3
0
1
2
3
1
0
X
X
10
0,1
1
01
0,1
y=x  y=x+1
0X
0,1
10
0,1
1
0
3
0
1
1
0
2
1
0
01
0,1
X
X
Example
01
0,1
01
0,1
0
X
X
10
0,1
0X
0,1
1
1
0
2
1
0
=
0,1
1
0
1
0
0
1
2
X
X
01
0,1
3
0
1
1
0
0X
0,1
10
0,1
3
01
0,1
X
X
Example
0X
0,1
0
0 2
1
1 3
2
4
0
1
2
3
4
1
0
1
0
0
X
X
01
0,1
1
2
0
1
0X
0,1
X
1
0
0
0
1
0
2
3
0
1
0
1
1
0
1
0
1
0
1
X
0
X
X
01
0,1
4
Example
0X
0,1
0 X
0, 1
0
1
0
1
0
1
X
X
01
0,1
X
1
0
0
2
0
1
0
0X
0,1
=
0,2
X1
0,0
1
0
0
1
1,3
2
3
0
1
0
1
0
1
1
0
1
0
1
0
1
X
0
Represents:
yx
X
X
01
0,1
4
Outline
•
•
•
•
•
•
Model checking with arithmetic constraints
Conservative approximations
Automata representation for arithmetic constraints
Composite representation
Action Language Verifier (ALV)
Checking synchronization in concurrent programs with ALV
Composite Model Checking
[Bultan, Gerber, League ISSTA 98, TOSEM 00]
• Map each variable type to a symbolic representation
– Map boolean and enumerated types to BDD
representation
– Map integer type to a linear arithmetic constraint
representation
• Use a disjunctive representation to combine different
symbolic representations: composite representation
• Each disjunct is a conjunction of formulas represented by
different symbolic representations
– we call each disjunct a composite atom
Composite Representation
composite atom
F
f
n
i 1
i1
 f i 2  ...  f i t
symbolic symbolic
rep. 1
rep. 2
symbolic
rep. t
Example:
x: integer, y: boolean
x>0 and x´x-1 and y´ or x<=0 and x´x and y´y
arithmetic constraint
representation
BDD
arithmetic constraint
representation
BDD
Composite Symbolic Library
[Yavuz-Kahveci, Tuncer, Bultan TACAS01], [Yavuz-Kahveci, Bultan FroCos 02, STTT 03]
• Uses a common interface for each symbolic representation
• Easy to extend with new symbolic representations
• Enables polymorphic verification
• Multiple symbolic representations:
– As a BDD library we use Colorado University Decision
Diagram Package (CUDD) [Somenzi et al]
– As an integer constraint manipulator we use Omega
Library [Pugh et al]
Composite Symbolic Library Class Diagram
Symbolic
+intersect()
+union()
+complement()
+isSatisfiable()
+isSubset()
+pre()
+post()
BoolSym
–representation: BDD
+intersect()
+union()
•
•
•
CUDD Library
CompSym
IntSym
–representation: list
of comAtom
–representation: Polyhedra
+intersect()
+ union()
•
•
•
compAtom
–atom: *Symbolic
+intersect()
+union()
•
•
•
OMEGA Library
Pre and Post-condition Computation
Variables:
x: integer, y: boolean
Transition relation:
R: x>0 and x´x-1 and y´ or x<=0 and x´x and y´y
Set of states:
s: x=2 and !y or x=0 and !y
Compute post(s,R)
Pre and Post-condition Distribute
R: x>0 and x´x-1 and y´ or x<=0 and x´x and y´y
s: x=2 and !y or x=0 and y
post(s,R) = post(x=2 , x>0 and x´x-1)  post(!y , y´)
x=1
y

post(x=2 , x<=0 and x´x)  post (!y , y´y)
false
!y

post(x=0 , x>0 and x´x-1)  post(y , y´)
false
y

post (x=0 , x<=0 and x´x)  post (y, y´y )
x=0
y
= x=1 and y or x=0 and y
Polymorphic Verifier
Symbolic TranSys::check(Node *f) {
•
•
•
Symbolic s = check(f.left)
case EX:
s.pre(transRelation)
case EF:
do
sold = s
s.pre(transRelation)
s.union(sold)
while not sold.isEqual(s)
•
•
•
}
 Action
Language Verifier
is polymorphic
 It becomes a BDD based model
checker when there or no integer
variables
Composite Representation + Shape Graphs
[Yavuz-Kahveci, Bultan SAS 02]
• Shape graphs represent the states of the heap
add
heap variables add and top
point to node n1
top
n1
next
n2
next
add.next is node n2
top.next is also node n2
add.next.next is null
• Each node in the shape graph represents a dynamically
allocated memory location
• Heap variables point to nodes of the shape graph
• The edges between the nodes show the locations pointed
by the fields of the nodes
Composite Symbolic Library: Further Extended
Symbolic
+union()
+isSatisfiable()
+isSubset()
+forwardImage()
HeapSym
IntSym
CompSym
–representation:
BDD
–representation:
list of ShapeGraph
–representation:
list of Polyhedra
–representation:
list of comAtom
+union()
+union()
+union()
+ union()
BoolSym
•
•
•
CUDD Library
•
•
•
ShapeGraph
–atom: *Symbolic
•
•
•
OMEGA Library
•
•
•
compAtom
–atom: *Symbolic
Forward Fixpoint
arithmetic constraint
representation
BDD
pc=l1  mutex

numItems=2
A set of shape graphs
add

top

pc=l2  mutex

numItems=2

add
top

pc=l4  mutex

numItems=2

add
top

pc=l1  mutex

numItems=3

add
top
Post-condition Computation: Example
set of
states

pc=l4  mutex
transition pc=l4 and mutex’
pc’=l1
relation
pc=l1  mutex

numItems=2

add
numItems’=numItems+1

numItems=3


add
top
top’=add
top
Again: Fixpoints Do Not Converge
• We have two reasons for non-termination
– integer variables can increase without a bound
– the number of nodes in the shape graphs can increase
without a bound
• As I mentioned earlier, we use widening on integer
variables to achieve convergence
• For heap variables we use the summarization operation
Summarization Example
pc=l1  mutex

numItems=3

add
top
summarized nodes
After summarization, it becomes:
add
pc=l1  mutex

numItems=3  summarycount=2
a new integer variable
representing the number
of concrete nodes encoded
by the summary node
top

summary node
Simplification
pc=l1  mutex

numItems=3
 summaryCount=2

add
top

pc=l1  mutex

numItems=4

(numItems=4
 summaryCount=3

add
top
=
pc=l1  mutex
 summaryCount=3
 numItems=3
 summarycount=2)

add
top
Simplification On the Integer Part

pc=l1  mutex
(numItems=4
 summaryCount=3

add
top
 numItems=3
 summaryCount=2)
=
pc=l1  mutex

numItems=summaryCount+1
 3  numItems
 numItems  4

add
top
Then We Use Integer Widening
pc=l1  mutex

numItems=summaryCount+1
add

top
 3  numItems
 numItems  4
pc=l1  mutex


numItems=summaryCount+1

add
top
 3  numItems
 numItems  5
=
pc=l1  mutex

numItems=summaryCount+1
 3  numItems
Now, fixpoint converges

add
top
Verified Properties
Specification
Verified Invariants
Stack
top=null  numItems=0
topnull  numItems0
numItems=2  top.nextnull
Single Lock Queue
head=null  numItems=0
headnull  numItems0
(head=tail  head null)  numItems=1
headtail  numItems0
Two Lock Queue
numItems>1  headtail
numItems>2  head.nexttail
Verifying Linked Lists with Multiple Fields
• Pattern-based summarization
– User provides a graph grammar rule to describe the
summarization pattern
L x = next x y, prev y x, L y
• Represent any maximal sub-graph that matches the
pattern with a summary node
– no node in the sub-graph pointed by a heap variable
Summarization Pattern Examples
L x  x.n = y, L y
n
n
...
L x  x.n = y, y.p = x, L y
n
n
...
p
p
n
L x  x.n = y, x.d = z, L y
d
n
d
n
n
p
...
n
d
Outline
•
•
•
•
•
•
Model checking with arithmetic constraints
Conservative approximations
Automata representation for arithmetic constraints
Composite representation
Action Language Verifier (ALV)
Checking synchronization in concurrent programs with ALV
Action Language Tool Set
Action Language
Specification
Action Language
Parser
Composite Symbolic Library
Action Language
Verifier (ALV)
Verified
Counter
example
Omega
Library
Presburger
Arithmetic
Manipulator
CUDD
Package
BDD
Manipulator
MONA
Automata
Manipulator
Action Language
[Bultan, ICSE 00], [Bultan, Yavuz-Kahveci, ASE 01]
• Variables: boolean, enumerated, integer (unbounded)
• Parameterized constants
– specifications are verified for all possible values
• Transition relation is defined using actions and modules
– Atomic actions: Predicates on current and next state
variables
– Action composition:
• asynchronous (|) or synchronous (&)
– A module is defined as asynchronous and/or
synchronous compositions of its actions and
submodules
Readers Writers Example: A Closer Look
module main()
integer nr;
boolean busy;
restrict: nr>=0;
initial: nr=0 and !busy;
S : Cartesian product of
variable domains defines
the set of states
I : Predicates defining
the initial states
module Reader()
boolean reading;
R : Atomic actions of the
initial: !reading;
Reader
rEnter: !reading and !busy and
nr’=nr+1 and reading’;
rExit: reading and !reading’ and nr’=nr-1;
Reader: rEnter | rExit;
endmodule
R : Transition relation of
Reader defined as
module Writer()
asynchronous composition
...
of its atomic actions
endmodule
main: Reader() | Reader() | Writer() | Writer();
spec: invariant(busy => nr=0)
endmodule
R : Transition relation of main defined as asynchronous
composition of two Reader and two Writer processes
Arbitrary Number of Threads
• Counting abstraction
– Create an integer variable for each local state of a
thread
– Each variable will count the number of threads in a
particular state
• Local states of the threads have to be finite
– Specify only the thread behavior that relates to the
correctness of the controller
– Shared variables of the controller can be unbounded
• Counting abstraction can be automated
Readers-Writers After Counting Abstraction
Parameterized constants
module main()
introduced by the counting
integer nr;
abstractions
boolean busy;
parameterized integer numReader, numWriter;
restrict: nr>=0 and numReader>=0 and numWriter>=0;
initial: nr=0 and !busy;
Variables introduced by the
module Reader()
counting abstractions
integer readingF, readingT;
initial: readingF=numReader and readingT=0;
rEnter: readingF>0 and !busy and
nr’=nr+1 and readingF’=readingF-1 and
readingT’=readingT+1;
rExit: readingT>0 and nr’=nr-1 readingT’=readingT-1
and readingF’=readingF+1;
Reader: rEnter | rExit;
endmodule
module Writer()
...
endmodule
main: Reader() | Writer();
spec: invariant(busy => nr=0)
endmodule
Verification of Readers-Writers
Integers
Booleans
Cons. Time
(secs.)
Ver. Time
(secs.)
Memory
(Mbytes)
RW-4
1
5
0.04
0.01
6.6
RW-8
1
9
0.08
0.01
7
RW-16
1
17
0.19
0.02
8
RW-32
1
33
0.53
0.03
10.8
RW-64
1
65
1.71
0.06
20.6
RW-P
7
1
0.05
0.01
9.1
Outline
•
•
•
•
•
•
Model checking with arithmetic constraints
Conservative approximations
Automata representation for arithmetic constraints
Composite representation
Action Language Verifier (ALV)
Checking synchronization in concurrent programs with ALV
Design for Verification
Action
Language
Verifier
enables
uses
Verification of
Synchronization in
Concurrent
Programs
Design for
Verification
A Java Read-Write Lock Implementation
How do we translate this to
Action Language?
class ReadWriteLock {
private Object lockObj;
private int totalReadLocksGiven;
private boolean writeLockIssued;
private int threadsWaitingForWriteLock;
Action
public ReadWriteLock() {
lockObj = new Object();
Language
writeLockIssued = false;
}
Verifier
public void getReadLock() {
synchronized (lockObj) {
while ((writeLockIssued) || (threadsWaitingForWriteLock != 0)) {
try {
lockObj.wait();
} catch (InterruptedException e) {
}
Verification of
}
totalReadLocksGiven++;
Synchronization
}
}
Java
public void getWriteLock() {
synchronized (lockObj) {
Programs
threadsWaitingForWriteLock++;
while ((totalReadLocksGiven != 0) || (writeLockIssued)) {
try {
lockObj.wait();
} catch (InterruptedException e) {
//
}
}
threadsWaitingForWriteLock--;
writeLockIssued = true;
in
Design for Verification
• Abstraction and modularity are key both for successful designs and
scalable verification techniques
• The question is:
– How can modularity and abstraction at the design level be better
integrated with the verification techniques which depend on these
principles?
• Our approach:
– Structure software in ways that facilitate verification
– Document the design decisions that can be useful for verification
– Improve the applicability and scalability of verification using this
information
A Design for Verification Approach
We have been investigating a design for verification approach based on
the following principles:
1. Use of design patterns that facilitate automated verification
2. Use of stateful, behavioral interfaces which isolate the behavior and
enable modular verification
3. An assume-guarantee style modular verification strategy that
separates verification of the behavior from the verification of the
conformance to the interface specifications
4. A general model checking technique for interface verification
5. Domain specific and specialized verification techniques for behavior
verification
• Avoids usage of error-prone Java synchronization primitives:
synchronize, wait, notify
• Separates controller behavior from the threads that use the controller:
Supports a modular verification approach which exploits this modularity
for scalable verification
Reader-Writer Controller
class Action{
This helper class is
provided.
No need to rewrite it!
class RWController implements
protected final Object owner; …
RWInterface{
private boolean GuardedExecute(){
int nR; boolean busy;
boolean result=false;
final Action act_r_enter, act_r_exit;
for(int i=0; i<gcV.size(); i++) try{
final Action act_w_enter, act_w_exit;
if(((GuardedCommand)gcV.get(i)).guard()){
((GuardedCommand)gcV.get(i)).update();
RWController() {
result=true; break; }
...
}catch(Exception e){}
gcs = new Vector();
return result;
gcs.add(new GuardedCommand() {
}
public boolean guard(){
public void blocking(){
return (nR == 0 && !busy);}
synchronized(owner) {
while(!GuardedExecute()) {
public void update(){busy = true;}}
try{owner.wait();}
);
catch (Exception e){} }
act_w_enter = new Action(this,gcs);
owner.notifyAll(); }
}
}
public void w_enter(){
public boolean nonblocking(){
act_w_enter.blocking();}
synchronized(owner) {
boolean result=GuardedExecute();
public boolean w_exit(){
if (result) owner.notifyAll();
return act_w_exit.nonblocking();}
return result; }
public void r_enter(){
}
act_r_enter.blocking();}
}
public boolean r_exit(){
return act_r_exit.nonblocking();}
}
Controller Interfaces
• A controller interface defines the acceptable call sequences
for the threads that use the controller
• Interfaces are specified using finite state machines
public class RWStateMachine implements
RWInterface{
r_enter
reading StateTable stateTable;
final static int idle=0,reading=1,
writing=2;
r_exit
public RWStateMachine(){ ...
idle
stateTable.insert("w_enter",idle,writing);
}
w_exit
public void w_enter(){
stateTable.transition("w_enter");
writing
w_enter
}
...
}
Verification Framework
Controller
Behavior
Machine
Controller
Classes
Behavior
Verification
Action
Language
Verifier
Counting
Abstraction
Concurrent
Program
Controller
Interface
Machine
Thread
Thread
Thread
Classes
Interface
Verification
Java
Path Finder
Thread
Isolation
Thread
Class
Modular Design / Modular Verification
Thread Modular Interface Verification
Thread 1
Thread 2
Thread n
Thread n
Thread 2
Thread 1
Concurrent Program
Interface
Machine
Interface
Machine
Interface
Machine
Interface
Controller
Shared
Data
Controller Behavior
Modular
Behavior
Verification
Behavior Verification
• Analyzing properties (specified in CTL) of the
synchronization policy encapsulated with a concurrency
controller and its interface
– Verify the controller properties assuming that the user
threads adhere to the controller interface
• Behavior verification with Action Language Verifier
– We wrote a translator which translates controller classes
to Action Language
– Using counting abstraction we can check concurrency
controller classes for arbitrary number of threads
Interface Verification
• A thread is correct with respect to an interface if all the call sequences
generated by the thread can also be generated by the interface
machine
– Checks if all the threads invoke controller methods in the order
specified in the interfaces
– Checks if the threads access shared data only at the correct
interface states
• Interface verification with Java PathFinder
– Verify Java implementations of threads
– Correctness criteria are specified as assertions
• Look for assertion violations
• Assertions are in the StateMachine and SharedStub
– Performance improvement with thread Isolation
Thread Isolation: Part 1
• Interaction among threads
• Threads can interact with each other in only two ways:
– invoking controller actions
– invoking shared data methods
• To isolate the threads
– Replace concurrency controllers with controller interface
state machines
– Replace shared data with shared stubs
Thread Isolation: Part 2
• Interaction among a thread and its environment
• Modeling thread’s call to its environment with stubs
– File I/O, updating GUI components, socket operations,
RMI call to another program
• Replace with pre-written or generated stubs
• Modeling the environment’s influence on threads with
drivers
– Thread initialization, RMI events, GUI events
• Enclose with drivers that generate all possible events
that influence controller access
Automated Airspace Concept
• Automated Airspace Concept by NASA researchers
automates the decision making in air traffic control
• The most important challenge is achieving high
dependability
• Automated Airspace Concept includes a failsafe short term
conflict detection component called Tactical Separation
Assisted Flight Environment (TSAFE)
– It is responsible for detecting conflicts in flight plans of
the aircraft within 1 minute from the current time
– Dependability of this component is even more important
than the dependability of the rest of the system
– It should be a smaller, isolated component compared to
the rest of the system so that it can be verified
TSAFE
TSAFE functionality:
1. Display aircraft position
2. Display aircraft planned route
3. Display aircraft future projected route trajectory
4. Show conformance problems
TSAFE Architecture
User
Radar feed
<<TCP/IP>>
Feed Parser
Server
Client
Flight
Database
EventThread
<<RMI>>
Graphical
Client
Computation
21,057 lines of code with 87 classes
Timer
Behavior Verification Performance
Controller
Time(sec)
Memory (MB) P-Time (sec)
P-Memory (MB)
RW
0.17
1.03
8.10
12.05
Mutex
0.01
0.23
0.98
0.03
Barrier
0.01
0.64
0.01
0.50
BB-RW
0.13
6.76
0.63
10.80
BB-Mutex
0.63
1.99
2.05
6.47
P denotes parameterized verification for arbitrary number of threads
Interface Verification Performance
Thread
Time (sec)
Memory (MB)
TServer-Main
67.72
17.08
TServer-RMI
91.79
20.31
TServer-Event
6.57
10.95
TServer-Feed
123.12
83.49
TClient-Main
2.00
2.32
TClient-RMI
17.06
40.96
TClient-Event
663.21
33.09
Fault Categories
• Concurrency controller faults
– initialization faults (2)
– guard faults (2)
– update faults (6)
– blocking/nonblocking faults (4)
• Interface faults
– modified-call faults (8)
– conditional-call faults
• conditions based on existing program variables (13)
• conditions on new variables declared during fault
seeding (5)
Effectiveness in Finding Faults
• Created 40 faulty versions of TSAFE
• Each version had at most one interface fault and at most
one behavior fault
– 14 behavior and 26 interface faults
• Among 14 behavior faults ALV identified 12 of them
– 2 uncaught faults were spurious
• Among 26 interface faults JPF identified 21 of them
– 2 of the uncaught faults were spurious
– 3 of the uncaught faults were real faults that were not
caught by JPF
Falsification Performance
Thread
Time (sec)
Memory (MB)
TServer-RMI
29.43
24.74
TServer-Event
6.88
9.56
TServer-Feed
18.51
94.72
TClient-RMI
10.12
42.64
TClient-Event
15.63
12.20
Concurrency Controller
RW-8
Time (sec)
0.34
Memory (MB)
3.26
RW-16
1.61
10.04
RW-P
1.51
5.03
Mutex-8
0.02
0.19
Mutex-16
0.04
0.54
Mutex-p
0.12
0.70
Conclusions
• Infinite state model checking is feasible
– Enables verification of specifications with unbounded
variables
– Enables verification of parameterized systems
• Infinite state verification techniques can help us in
identifying more efficient finite state model checking
techniques
• Building extensible tools is important!
Conclusions
• Application of automated verification techniques to realworld systems leads to re-thinking the design
– Design for verification can lead to more effective
verification
• Integrating verification tools lead to more effective
verification
– In our case ALV and JPF
Conclusions
• We were able to use our design for verification approach
based on design patterns and behavioral interfaces in
different domains
• Use of domain specific behavior verification techniques has
been very effective
– Interface verification was the bottleneck
• Model checking research resulted in various verification
techniques and tools which can be customized for specific
classes of software systems
• Automated verification techniques can scale to realistic
software systems using design for verification approach
THE END
Download