Logic Model Checking

Logic Model Checking
Lecture Notes 2:18
Caltech 101b.2
January-March 2005
Course Text:
The Spin Model Checker: Primer and Reference Manual
Addison-Wesley 2003, ISBN 0-321-22862-6, 608 pgs.
course web page
•
http://spinroot.com/spin/Doc/course/
– pdf’s for lectures and background material (Standish survey, NIST
report) – will have assignments and any additional materials
•
to do:
– install a copy of Spin and start experimenting with it
• http://spinroot.com/spin/
– on Windows PCs with cygwin installed (www.cygwin.com):
• download the executable spin422.exe and copy it to /bin/spin.exe
• download the tcl/tk gui xspin422.tcl and copy it to /bin/xspin
– on Linux or Unix systems: compile from the sources and install spin
and xspin in your /home/user/bin
•
questions:
[email protected]
Logic Model Checking [2 of 18]
2
Course Outline
• introduction
– what makes designing reliable distributed systems so hard?
– the concept of a verification model
• modeling concurrency, expressing correctness claims
• using abstraction effectively
• theoretical foundation
– automata and logic
– verification algorithms
– search optimization
• model checking in practice
– tools and tool design
– model building and model extraction
– challenges
Logic Model Checking [2 of 18]
3
a very small example
of a multi-threaded system
int
x, y, r;
int *p, *q, *z;
int **a;
thread_1(void)
{
p = &x;
q = &y;
z = &r;
}
thread_2(void)
{
r = *p;
*p = *q;
*q = r;
}
thread_3(void)
{
a = &p;
*a = z;
**a = 12;
}
Logic Model Checking [2 of 18]
/* initialize p, q, and r */
/* swap contents of x and y */
/* access z via a and p */
reads
h
t
s
u
o
n
ro
3 asynch shared data
g
h
accessin
ents eac ded to
m
e
t
a
t
s
3
are nee
s
n
u
r
t
ccur?
s
o
te
n
y
a
n
c
a
n
m
how
corruptio
a
t
a
d
o
n
at
check th
4
thread interleaving
•
3
the number of possible thread
interleavings is...
9!
6!
3!
----- · ----- · ---- =
6!.3!
3!.3!
3!
1,680
1,680 possible executions
2
1
placing 3 sets of 3 tokens in 9 slots
•
•
•
start
are all these executions okay?
can we check them all? should we
check them all?
in classic system testing, how many
would normally be checked?
Logic Model Checking [2 of 18]
5
simpler still
•
consider two 2-state automata
– representing two asynchronous processes
•
•
one can print an arbitrary number of ‘0’ digits, or stop
the other can print an arbitrary number of ‘1’ digits, or stop
print ‘0’
stop
print ‘1’
stop
odel
m
a
d
coul
w
o
ssibly
h
o
:
p
Q
h
t
i
eal w
d
r
e
ns ?
k
o
i
t
u
c
chec
e
ex
infinite
how many different combined executions are there?
i.e., how many different binary numbers can be printed?
how would one test that this system does what we think it does?
Logic Model Checking [2 of 18]
6
one cannot, not even in principle, exhaustively
test process behavior in a distributed system
• problems:
– lack of observability in distributed systems
• of data access patterns, process scheduling decisions,
precise interleaving in time of events that occur in
physically distinct systems
– lack of controllability
• e.g., of process scheduling actions in distinct systems,
order of arrival of events, etc.
– lack of time
• consider 20 possible sources of error, they can occur in
220 possible combinations (220 = 1 million; can you test
them all? hint: 1 million seconds is a little over 12 days)
• in practice exhaustive testing exhausts the testers
long before it exhausts the system…
Logic Model Checking [2 of 18]
7
concurrent systems are not just hard to test
they are also hard to design (so we need
more thorough not less thorough checking)
an example:
designing foolproof traffic rules
(road traffic is one big
asynchronous process system
with many shared resources)
simple rule for traffic circles:
“traffic approaching from
the right always has priority”
Logic Model Checking [2 of 18]
8
an undesirable side-effect of this rule: potential
deadlock (also called gridlock or circular waiting)
so, okay, that didn’t work
Q: would the reverse rule be better?
Logic Model Checking [2 of 18]
9
the opposite rule introduces
a different set of problems
“traffic within the circle
always has priority”
a different problem:
potentially unbounded
delay or starvation
two questions should come up:
how can one predict the consequences of
perfectly innocent looking rules like these?
how does this get resolved in real-life?
Logic Model Checking [2 of 18]
10
distributed algorithms
in real-life conflicts ultimately get resolved by human judgment.
computers, though, must be able to resolve it with fixed algorithms
after-you, no
after-you blocking
Logic Model Checking [2 of 18]
me-first, no
me-first blocking
two asynchronous processes
competing for a shared resource
using a fixed algorithm/rule
11
a challenge problem
the problem of the Leidsestraat
(a busy street in the center of Amsterdam)
canal
tram
tram
bridge1
bridge2
street
Leidseplein
Koningsplein
busy two-way traffic of tram-cars through the street
1 track in the street, 2 tracks on bridges
the trams pass each other on the bridges
priority rule: trams moving to the center (the right) have priority
challenge: design a traffic light control algorithm that maximizes
throughput of trams and prevents deadlock and starvation
hint-1: there are currently no traffic lights in this street
Logic Model Checking [2 of 18]
12
no problem?
Logic Model Checking [2 of 18]
13
when is a system “correct”?
•
a system is correct when it meets its requirements
“a design without requirements cannot be right or
wrong, it can only be surprising”
•
•
therefore, verification must always start with the
identification and formalization of all relevant
correctness requirements
a well-designed system is provably correct
– burden of proof: it is best to assume that the system is
incorrect until the opposite can be shown
– sometimes we have to keep the design simpler than we
would like, just to be able to prove its properties
– reason: common sense can be misleading, especially in
distributed systems design
Logic Model Checking [2 of 18]
14
correctness
• corollaries:
– you cannot prove a system correct in any absolute sense
– you can only prove that a system (or a model of a system)
does or does not have certain specific properties
– it requires human judgment to conclude whether having or
not having those properties constitutes ‘correctness’
– getting the properties (requirements) right is as important as
getting the (model of the) system right
– there is no magic wand, no blind test that could
automagically prove an arbitrary given system ‘correct’
Logic Model Checking [2 of 18]
15
types of correctness requirements
• some requirements are standard:
– a system should not deadlock
– no process should be able to starve another
– no explicitly stated assertion inside a process should ever fail
• others are application specific:
–
–
–
–
system invariants, process assertions
effective progress requirements
proper termination
general causal and temporal relations on states
• e.g., when a request is issued eventually a reply is returned
– fairness assumptions,
• e.g., about process scheduling
– etc. etc.
Logic Model Checking [2 of 18]
16
building verification models and
selecting correctness requirements
tool-based verification often pushes the limits of tractability
a good use of selective abstraction is the key to success
this is true for any type of proof attempt
“it is not reasonable to check the minor details before we
have good reason to believe that the major steps of an
argument are sound [Polya,How to Solve it, 1945, p. 69]
“the point of view is worth 80 IQ points” [Alan Kay]
(in logic model checking picking the right point of view,
the right abstraction, can be more powerful than the
best supercomputer you don’t have)
Logic Model Checking [2 of 18]
17
the choice of the model depends on the
requirements that must be checked
• a good model is always an abstraction of reality
– it should have less detail than the artifact being modeled
– the level of detail is selected based on its relevance to the
correctness requirements
– the objective is to gain analytical power by reducing detail
• the purpose of a model is to explain and predict
– if it can do neither because it is too detailed, it is not a good
model
• a model is a design aid
– it often goes through different versions, describing different
aspects of reality, and can slowly become more accurate,
without becoming more detailed
accuracy != detail
Logic Model Checking [2 of 18]
18
an example of a powerful abstraction
or not
n
o
i
t
c
a
r
t
s
ab
model
s
d
i
o
h
t
o
f
g
o
a
e
this is
purpos
e
h
t
n
o
whether
y
tel
/verify)
le
e
t
p
a
r
m
t
o
s
c
n
o
s
depend
t to dem
n
a
e
m
it
t is
(i.e., wha
Logic Model Checking [2 of 18]
19
which is the better abstraction?
bad
good
good!
good!
bad!
bad!
status?
status?
status?
hide what is irrelevant or what should be invisible
Logic Model Checking [2 of 18]
20
a telephone subscriber
how many states can the process be in?
• in some cases, a 1-state automaton is the best
conservative abstraction to describe all possible (and
some impossible) behaviors of a complex system (e.g. a
telephone subscriber)
on-hook
off-hook
digit 0
…
Logic Model Checking [2 of 18]
digit 9
21
two things we always abstract from in
logic model checking
•
•
•
a correctness proof that makes no assumptions about the
passage of time or about the probability (rather than the
possibility) of events is stronger than one that does
in distributed systems, logical correctness and real-time
performance should be treated as orthogonal concerns
Dijkstra’s golden rule: in distributed systems design, one can
never make assumptions about the relative speed of execution
of asynchronously executing processes (and the same holds for
proofs of correctness)
real-time
Logic Model Checking [2 of 18]
probability
22
building verification models
• we want to be able to make separate statements
about system design and about system requirements
• therefore we will need two notations/formalisms
– one for specifying behavior (system design)
– one for specifying requirements (correctness properties)
• the two types of statements combined define a
verification model
• a model checker can now:
– check that the behavior specification (the design) is logically
consistent with the requirements specification (the desired
properties of the design)
– the formalism must be defined in such a way that we can
guarantee the decidability of any property we can state for
any system we can specify
Logic Model Checking [2 of 18]
23
Spin verification models are used to define
abstractions of distributed system designs
•
•
the specification language must support all essential aspects of
distributed systems software, and discourage the specification
of any redundant detail (not bearing on things that are provable)
there are 3 basic types of objects in a Spin verification model:
– asynchronous processes
– global and local data objects
– message channels
global
data
process0
process1
message
channels
local
data
Logic Model Checking [2 of 18]
local
data
24
hello world as a “Spin model”
these are keywords
start
s0
‘main’ is not a keyword
print
automaton
s1
active proctype main()
no semi-colon here…
stop
{
a simulation run:
printf(“hello world\n”)
$$ spin
spin hello.pml
hello.pml
}
hello
world
hello world
this is a bit like C
11 process
process created
created
$$
a verification run:
$$ spin
spin –a
–a hello.pml
hello.pml
$$ gcc
gcc –o
–o pan
pan pan.c
pan.c
$$ ./pan
./pan
...
... depth
depth reached
reached 2,
2, errors:
errors: 00
$$
Logic Model Checking [2 of 18]
25
a more interesting example: two processes
a card reader and a line printer
process 1
process 2
?A
?B
?B
?A
!A
!B
?A reserve printer device
?B reserve card reader
!B
!A
!A release printer device
!B release card reader
Logic Model Checking [2 of 18]
26
the corresponding Spin model
(don’t worry about the details just yet)
$$ cat
cat generic.pml
generic.pml
bool
bool printer
printer == true;
true;
bool
bool reader
reader == true;
true;
/*
/* initially
initially both
both devices
devices */
*/
/*
/* are
are available
available */
*/
active
active [2]
[2] proctype
proctype user()
user()
{{
do
do
::
:: (printer)
(printer) ->
-> printer
printer == false;
false;
(reader)
(reader) ->
-> reader
reader == false;
false;
/*
/* print
print cards
cards */
*/
printer
=
true;
printer = true; /*
/* available
available */
*/
reader
reader == true
true
::
:: (reader)
(reader) ->
-> reader
reader == false;
false;
(printer)
(printer) ->
-> printer
printer == false;
false;
/*
print
cards
*/
/* print cards */
reader
reader == true;
true;
printer
printer == true
true
od
od
}}
$$
Logic Model Checking [2 of 18]
27
a simulation of 20 steps
$$ spin
spin -v
-v -u20
-u20 generic.pml
generic.pml
0:
proc
0:
proc -- (:root:)
(:root:) creates
creates proc
proc 11 (user)
(user)
1:
proc
0
(user)
line
6
"generic.pml"
1:
proc 0 (user) line
6 "generic.pml" (state
(state
2:
proc
77 "generic.pml"
2:
proc 00 (user)
(user) line
line
"generic.pml" (state
(state
3:
proc
88 "generic.pml"
3:
proc 00 (user)
(user) line
line
"generic.pml" (state
(state
4:
proc
1
(user)
line
6
"generic.pml"
(state
4:
proc 1 (user) line
6 "generic.pml" (state
5:
proc
88 "generic.pml"
5:
proc 00 (user)
(user) line
line
"generic.pml" (state
(state
6:
proc
1
(user)
line
13
"generic.pml"
(state
6:
proc 1 (user) line 13 "generic.pml" (state
7:
proc
7:
proc 00 (user)
(user) line
line 10
10 "generic.pml"
"generic.pml" (state
(state
8:
proc
1
(user)
line
14
"generic.pml"
(state
8:
proc 1 (user) line 14 "generic.pml" (state
9:
proc
9:
proc 11 (user)
(user) line
line 14
14 "generic.pml"
"generic.pml" (state
(state
10:
proc
10:
proc 00 (user)
(user) line
line 11
11 "generic.pml"
"generic.pml" (state
(state
11:
proc
0
(user)
line
19
"generic.pml"
(state
11:
proc 0 (user) line 19 "generic.pml" (state
12:
proc
66 "generic.pml"
12:
proc 00 (user)
(user) line
line
"generic.pml" (state
(state
13:
proc
1
(user)
line
16
"generic.pml"
(state
13:
proc 1 (user) line 16 "generic.pml" (state
14:
proc
14:
proc 11 (user)
(user) line
line 17
17 "generic.pml"
"generic.pml" (state
(state
15:
proc
15:
proc 11 (user)
(user) line
line 19
19 "generic.pml"
"generic.pml" (state
(state
16:
proc
1
(user)
line
6
"generic.pml"
(state
16:
proc 1 (user) line
6 "generic.pml" (state
17:
proc
17:
proc 00 (user)
(user) line
line 13
13 "generic.pml"
"generic.pml" (state
(state
18:
proc
1
(user)
line
13
"generic.pml"
(state
18:
proc 1 (user) line 13 "generic.pml" (state
19:
proc
19:
proc 00 (user)
(user) line
line 14
14 "generic.pml"
"generic.pml" (state
(state
20:
proc
20:
proc 11 (user)
(user) line
line 14
14 "generic.pml"
"generic.pml" (state
(state
13)[(printer)]
13)[(printer)]
2)
2) [printer
[printer == 0]
0]
3)
[(reader)]
3) [(reader)]
13)[(reader)]
13)[(reader)]
4)
4) [reader
[reader == 0]
0]
8)
[reader
=
0]
8) [reader = 0]
5)
5) [printer
[printer == 1]
1]
9)
[(printer)]
9) [(printer)]
10)[printer
10)[printer == 0]
0]
6)
6) [reader
[reader == 1]
1]
14)[.(goto)]
14)[.(goto)]
13)[(reader)]
13)[(reader)]
11)[reader
11)[reader == 1]
1]
12)[printer
12)[printer == 1]
1]
14)[.(goto)]
14)[.(goto)]
13)[(reader)]
13)[(reader)]
8)
8) [reader
[reader == 0]
0]
8)
[reader
=
0]
8) [reader = 0]
9)
9) [(printer)]
[(printer)]
9)
9) [(printer)]
[(printer)]
------------------------depth-limit
depth-limit (-u20
(-u20 steps)
steps) reached
reached
#processes:
#processes: 22
printer
printer == 11
reader
reader == 00
20:
proc
20:
proc 11 (user)
(user) line
line 14
14 "generic.pml"
"generic.pml" (state
(state 10)
10)
20:
proc
20:
proc 00 (user)
(user) line
line 14
14 "generic.pml"
"generic.pml" (state
(state 10)
10)
22 processes
processes created
created
$$
Logic Model Checking [2 of 18]
28
a verification
(checking a default property: absence of deadlock)
$$ spin
spin -a
-a generic.pml
generic.pml
$$ gcc
–DBFS
gcc –DBFS –o
–o pan
pan pan.c
pan.c
$$ ./pan
./pan
pan:
pan: invalid
invalid end
end state
state (at
(at depth
depth 4)
4)
pan:
pan: wrote
wrote generic.pml.trail
generic.pml.trail
(Spin
(Spin Version
Version 4.1.0
4.1.0 --- 19
19 November
November 2003)
2003)
Warning:
Search
not
completed
Warning: Search not completed
++ Using
Using Breadth-First
Breadth-First Search
Search
++ Partial
Order
Reduction
Partial Order Reduction
Full
Full statespace
statespace search
search for:
for:
never
claim
never claim
assertion
assertion violations
violations
cycle
checks
cycle checks
DSAFETY)
DSAFETY)
invalid
invalid end
end states
states
-++
--
(none
(none specified)
specified)
(disabled
(disabled by
by --
++
State-vector
State-vector 20
20 byte,
byte, depth
depth reached
reached 4,
4, errors:
errors: 11
44
44 states,
states, stored
stored
44
nominal
44 nominal states
states (stored-atomic)
(stored-atomic)
16
16 states,
states, matched
matched
60
60 transitions
transitions (=
(= stored+matched)
stored+matched)
00 atomic
atomic steps
steps
hash
hash conflicts:
conflicts: 00 (resolved)
(resolved)
(max
size
2^18
states)
(max size 2^18 states)
1.253
1.253
$$
spin’s euphemism
for deadlock
stopped at first
error found
memory
memory usage
usage (Mbyte)
(Mbyte)
Logic Model Checking [2 of 18]
29
inspection of the error trail
$$ spin
spin -t
-t -v
-v generic.pml
generic.pml
1:
proc
77
1:
proc 11 (user)
(user) line
line
2:
proc
77
2:
proc 11 (user)
(user) line
line
3:
proc
3:
proc 00 (user)
(user) line
line 13
13
4:
proc
4:
proc 00 (user)
(user) line
line 13
13
spin:
spin: trail
trail ends
ends after
after 44 steps
steps
#processes:
2
#processes: 2
printer
printer == 00
reader
reader == 00
4:
proc
88
4:
proc 11 (user)
(user) line
line
4:
proc
4:
proc 00 (user)
(user) line
line 14
14
22 processes
processes created
created
$$
"generic.pml"
"generic.pml"
"generic.pml"
"generic.pml"
"generic.pml"
"generic.pml"
"generic.pml"
"generic.pml"
(state
(state
(state
(state
(state
(state
(state
(state
[(printer)]
[(printer)]
[printer
[printer == 0]
0]
[(reader)]
[(reader)]
[reader
[reader == 0]
0]
"generic.pml"
"generic.pml" (state
(state 3)
3)
"generic.pml"
"generic.pml" (state
(state 9)
9)
process 1
process 2
?A
?B
?B
1)
1)
2)
2)
7)
7)
8)
8)
printer == 0
&&
reader == 0
?A
deadlock
Logic Model Checking [2 of 18]
30
the Spin gui – getting fancy
Logic Model Checking [2 of 18]
31