]> git.lizzy.rs Git - plan9front.git/blob - sys/doc/spin.ms
ape/cc: stop spamming arguments that are only needed once
[plan9front.git] / sys / doc / spin.ms
1 .HTML "Using SPIN
2 .\" runoff as:
3 .\" eqn file | tbl | troff -ms
4 .\"
5 .ds P \\s-1PROMELA\\s0
6 .ds V \\s-1SPIN\\s0
7 .ds C pcc
8 .\" .tr -\(hy
9 .EQ
10 delim $#
11 .EN
12 .TL
13 Using \*V
14 .AU
15 Gerard J. Holzmann
16 gerard@plan9.bell-labs.com
17 .AB
18 \*V can be used for proving or disproving logical properties
19 of concurrent systems.
20 To render the proofs, a concurrent system is first
21 modeled in a formal specification language called \*P.
22 The language allows one to specify the behaviors
23 of asynchronously executing
24 processes that may interact through synchronous
25 or asynchronous message passing, or through direct
26 access to shared variables.
27 .LP
28 System models specified in this way can be verified
29 for both safety and liveness properties. The specification
30 of general properties in linear time temporal logic is
31 also supported.
32 .LP
33 The first part of this manual
34 discusses the basic features of the specification language \*P.
35 The second part describes the verifier \*V.
36 .AE
37 .NH 1
38 The Language \*P
39 .LP
40 \*P is short for Protocol Meta Language [Ho91].
41 \*P is a \f2modeling\f1 language, not a programming language.
42 A formal model differs in two essential ways from an implementation.
43 First, a model is meant to be an abstraction of a design
44 that contains only those aspects of the design that are
45 directly relevant to the properties one is interested in proving.
46 Second, a formal model must contain things that are typically not part
47 of an implementation, such as worst-case assumptions about
48 the behavior of the environment that may interact with the
49 system being studied, and a formal statement of relevant correctness
50 properties. It is possible to mechanically extract abstract models
51 from implementation level code, as discussed, for instance in [HS99].
52 .LP
53 Verification with \*V is often performed in a series of steps,
54 with the construction of increasingly detailed models.
55 Each model can be verified under different types of
56 assumptions about the environment and for different
57 types of correctness properties.
58 If a property is not valid for the given assumptions about
59 system behavior, the verifier can produce a counter-example
60 that demonstrates how the property may be violated.
61 If a property is valid, it may be possible to simplify the
62 model based on that fact, and prove still other properties.
63 .LP
64 Section 1.1 covers the basic building blocks of the language.
65 Section 1.2 introduces the control flow structures.
66 Section 1.3 explains how correctness properties are specified.
67 Section 1.4 concludes the first part with a discussion of
68 special predefined variables and functions that can be used to
69 express some correctness properties.
70 .LP
71 Up to date manual pages for \*V can always be found online at:
72 .CW
73 http://cm.bell-labs.com/cm/cs/what/spin/Man/
74 .R
75 .NH 2
76 Basics
77 .LP
78 A \*P model can contain three different types of objects:
79 .IP
80 .RS
81 \(bu Processes (section 1.1.1),
82 .br
83 \(bu Variables (section 1.1.2),
84 .br
85 \(bu Message channels (section 1.1.3).
86 .RE
87 .LP
88 All processes are global objects.
89 For obvious reasons, a \*P model must contain at least one
90 process to be meaningful.
91 Since \*V is specifically meant to prove properties of
92 concurrent systems, a model typically contains more than
93 one process.
94 .LP
95 Message channels and variables, the two basic types of data objects,
96 can be declared with either a global scope or a local scope.
97 A data object with global scope can be referred to by all processes.
98 A data object with a local scope can be referred to by just a
99 single process: the process that declares and instantiates the object.
100 As usual, all objects must be declared in the specification
101 before they are referenced.
102 .NH 3
103 Processes
104 .LP
105 Here is a simple process that does nothing except print
106 a line of text:
107 .P1
108 init {
109         printf("it works\en")
110 }
111 .P2
112 There are a few things to note.
113 .CW Init
114 is a predefined keyword from the language.
115 It can be used to declare and instantiate
116 a single initial process in the model.
117 (It is comparable to the
118 .CW main
119 procedure of a C program.)
120 The
121 .CW init
122 process does not take arguments, but it can
123 start up (instantiate) other processes that do.
124 .CW Printf
125 is one of a few built-in procedures in the language.
126 It behaves the same as the C version.
127 Note, finally, that no semicolon follows the single
128 .CW printf
129 statement in the above example.
130 In \*P, semicolons are used as statement separators,
131 not statement terminators.  (The \*V parser, however, is
132 lenient on this issue.)
133 .LP
134 Any process can start new processes by using another
135 built-in procedure called
136 .CW run .
137 For example,
138 .P1
139 proctype you_run(byte x)
140 {
141         printf("my x is: %d\en", x)
142 }
143 .P2
144 .P1
145 init {
146         run you_run(1);
147         run you_run(2)
148 }
149 .P2
150 The word
151 .CW proctype
152 is again a keyword that introduces the declaration
153 of a new type of process.
154 In this case, we have named that type
155 .CW you_run
156 and declared that all instantiations of processes
157 of this type will take one argument:  a data object
158 of type
159 .CW byte ,
160 that can be referred to within this process by the name
161 .CW x .
162 Instances of a
163 .CW proctype
164 can be created with the predefined procedure
165 .CW run ,
166 as shown in the example.
167 When the
168 .CW run
169 statement completes, a copy of the process
170 has been started, and all its arguments have been
171 initialized with the arguments provided.
172 The process may, but need not, have performed
173 any statement executions at this point.
174 It is now part of the concurrent system,
175 and its execution can be interleaved arbitrarily with
176 those of the other, already executing processes.
177 (More about the semantics of execution follows shortly.)
178 .LP
179 In many cases, we are only interested in creating a
180 single instance of each process type that is declared,
181 and the processes require no arguments.
182 We can define this by prefixing the keyword
183 .CW proctype
184 from the process declaration with another keyword:
185 .CW active .
186 Instances of all active proctypes are created when the
187 system itself is initialized.
188 We could, for instance, have avoided the use of
189 .CW init
190 by declaring the corresponding process in the last example
191 as follows:
192 .P1
193 active proctype main() {
194         run you_run(1);
195         run you_run(2)
196 }
197 .P2
198 Note that there are no parameters to instantiate in this
199 case.  Had they been declared, they would default to a
200 zero value, just like all other data objects
201 that are not explicitly instantiated.
202 .LP
203 Multiple copies of a process type can also be created in
204 this way.  For example:
205 .P1
206 active [4] proctype try_me() {
207         printf("hi, i am process %d\en", _pid)
208 }
209 .P2
210 creates four processes.
211 A predefined variable
212 .CW _pid
213 is assigned to each running process, and holds
214 its unique process instantiation number.
215 In some cases, this number is needed when a reference
216 has to be made to a specific process.
217 .LP
218 Summarizing:  process behavior is declared in
219 .CW proctype
220 definitions, and it is instantiated with either
221 .CW run
222 statements or with the prefix
223 .CW active .
224 Within a proctype declaration, statements are separated
225 (not terminated) by semicolons.
226 As we shall see in examples that follow, instead of the
227 semicolon, one can also use the alternative separator
228 .CW "->"
229 (arrow), wherever that may help to clarify the structure
230 of a \*P model.
231 .SH
232 Semantics of Execution
233 .LP
234 In \*P there is no difference between a condition or
235 expression and a statement.
236 Fundamental to the semantics of the language is the
237 notion of the \f2executability\f1 of statements.
238 Statements are either executable or blocked.
239 Executability is the basic means of enforcing
240 synchronization between the processes in a distributed system.
241 A process can wait for an event to happen by waiting
242 for a statement to become executable.
243 For instance, instead of writing a busy wait loop:
244 .P1
245 while (a != b)  /* not valid Promela syntax */
246         skip;   /* wait for a==b */
247 \&...
248 .P2
249 we achieve the same effect in \*P with the statement
250 .P1
251 (a == b);
252 \&...
253 .P2
254 Often we indicate that the continuation of an execution
255 is conditional on the truth of some expression by using
256 the alternate statement separator:
257 .P1
258 (a == b) -> \&...
259 .P2
260 Assignments and
261 .CW printf
262 statements are always executable in \*P.
263 A condition, however, can only be executed (passed) when it holds.
264 If the condition does not hold, execution blocks until it does.
265 There are similar rules for determining the executability
266 of all other primitive and compound statements in the
267 language.
268 The semantics of each statement is defined in terms of
269 rules for executability and effect.
270 The rules for executability set a precondition on the state
271 of the system in which a statement can be executed.
272 The effect defines how a statement will alter a
273 system state when executed.
274 .LP
275 \*P assumes that all individual statements are executed
276 atomically: that is, they model the smallest meaningful entities
277 of execution in the system being studied.
278 This means that \*P defines the standard asynchronous interleaving
279 model of execution, where a supposed scheduler is free at
280 each point in the execution to select any one of the processes
281 to proceed by executing a single primitive statement.
282 Synchronization constraints can be used to influence the
283 interleaving patterns.  It is the purpose of a concurrent system's
284 design to constrain those patterns in such a way that no
285 correctness requirements can be violated, and all service
286 requirements are met.  It is the purpose of the verifier
287 either to find counter-examples to a designer's claim that this
288 goal has been met, or to demonstrate that the claim is indeed valid.
289 .NH 3
290 Variables
291 .LP
292 The table summarizes the five basic data types used in \*P.
293 .CW Bit
294 and
295 .CW bool
296 are synonyms for a single bit of information.
297 The first three types can store only unsigned quantities.
298 The last two can hold either positive or negative values.
299 The precise value ranges of variables of types
300 .CW short
301 and
302 .CW int
303 is implementation dependent, and corresponds
304 to those of the same types in C programs
305 that are compiled for the same hardware.
306 The values given in the table are most common.
307 .KS
308 .TS
309 center;
310 l l
311 lw(10) lw(12).
312 =
313 \f3Type Range\f1
314 _
315 bit     0..1
316 bool    0..1
317 byte    0..255
318 short      $-2 sup 15# .. $2 sup 15 -1#
319 int        $-2 sup 31# .. $2 sup 31 -1#
320 _
321 .TE
322 .KE
323 .LP
324 The following example program declares a array of
325 two elements of type
326 .CW bool
327 and a scalar variable
328 .CW turn
329 of the same type.
330 Note that the example relies on the fact that
331 .CW _pid
332 is either 0 or 1 here.
333 .MT _sec5critical
334 .P1
335 /*
336  * Peterson's algorithm for enforcing
337  * mutual exclusion between two processes
338  * competing for access to a critical section
339  */
340 bool turn, want[2];
341
342 active [2] proctype user()
343 {
344 again:
345         want[_pid] = 1; turn = _pid;
346
347         /* wait until this condition holds: */
348         (want[1 - _pid] == 0 || turn == 1 - _pid);
349
350         /* enter */
351 critical:       skip;
352         /* leave */
353
354         want[_pid] = 0;
355         goto again
356 }
357 .P2
358 In the above case, all variables are initialized to zero.
359 The general syntax for declaring and instantiating a
360 variable, respectively for scalar and array variables, is:
361 .P1
362 type name = expression;
363 type name[constant] = expression
364 .P2
365 In the latter case, all elements of the array are initialized
366 to the value of the expression.
367 A missing initializer fields defaults to the value zero.
368 As usual, multiple variables of the same type can be grouped
369 behind a single type name, as in:
370 .P1
371 byte a, b[3], c = 4
372 .P2
373 In this example, the variable
374 .CW c
375 is initialized to the value 4; variable
376 .CW a
377 and the elements of array
378 .CW b
379 are all initialized to zero.
380 .LP
381 Variables can also be declared as structures.
382 For example:
383 .P1
384 typedef Field {
385         short f = 3;
386         byte  g
387 };
388
389 typedef Msg {
390         byte a[3];
391         int fld1;
392         Field fld2;
393         chan p[3];
394         bit b
395 };
396
397 Msg foo;
398 .P2
399 introduces two user-defined data types, the first named
400 .CW Field
401 and the second named
402 .CW Msg .
403 A single variable named
404 .CW foo
405 of type
406 .CW Msg
407 is declared.
408 All fields of
409 .CW foo
410 that are not explicitly initialized (in the example, all fields except
411 .CW foo.fld2.f )
412 are initialized to zero.
413 References to the elements of a structure are written as:
414 .P1
415 foo.a[2] = foo.fld2.f + 12
416 .P2
417 A variable of a user-defined type can be passed as a single
418 argument to a new process in
419 .CW run
420 statements.
421 For instance,
422 .P1
423 proctype me(Msg z) {
424         z.a[2] = 12
425 }
426 init {
427         Msg foo;
428         run me(foo)
429 }
430 .P2
431 .LP
432 Note that even though \*P supports only one-dimensional arrays,
433 a two-dimensional array can be created indirectly with user-defined
434 structures, for instance as follows:
435 .P1
436 typedef Array {
437         byte el[4]
438 };
439
440 Array a[4];
441 .P2
442 This creates a data structure of 16 elements that can be
443 referenced, for instance, as
444 .CW a[i].el[j] .
445 .LP
446 As in C, the indices of an array of
447 .CW N
448 elements range from 0 to
449 .CW N-1 .
450 .SH
451 Expressions
452 .LP
453 Expressions must be side-effect free in \*P.
454 Specifically, this means that an expression cannot
455 contain assignments, or send and receive operations (see section 1.1.3).
456 .P1
457 c = c + 1; c = c - 1
458 .P2
459 and
460 .P1
461 c++; c--
462 .P2
463 are assignments in \*P, with the same effects.
464 But, unlike in C,
465 .P1
466 b = c++
467 .P2
468 is not a valid assignment, because the right-hand side
469 operand is not a valid expression in \*P (it is not side-effect free).
470 .LP
471 It is also possible to write a side-effect free conditional
472 expression, with the following syntax:
473 .P1
474 (expr1 -> expr2 : expr3)
475 .P2
476 The parentheses around the conditional expression are required to
477 avoid misinterpretation of the arrow.
478 The example expression has the value of \f(CWexpr2\f1 when \f(CWexpr1\f1
479 evaluates to a non-zero value, and the value of \f(CWexpr3\f1 otherwise.
480 .LP
481 In assignments like
482 .P1
483 variable = expression
484 .P2
485 the values of all operands used inside the expression are first cast to
486 signed integers before the operands are applied.
487 After the evaluation of the expression completes, the value produced
488 is cast to the type of the target variable before the assignment takes place.
489 .NH 3
490 Message Channels
491 .LP
492 Message channels are used to model the transfer of data
493 between processes.
494 They are declared either locally or globally,
495 for instance as follows:
496 .P1
497 chan qname = [16] of { short, byte }
498 .P2
499 The keyword
500 .CW chan
501 introduces a channel declaration.
502 In this case, the channel is named
503 .CW qname ,
504 and it is declared to be capable of storing up
505 to 16 messages.
506 Each message stored in the channel is declared here to
507 consist of two fields: one of type
508 .CW short
509 and one of type
510 .CW byte .
511 The fields of a message can be any one of the basic types
512 .CW bit ,
513 .CW bool ,
514 .CW byte ,
515 .CW short ,
516 .CW int ,
517 and
518 .CW chan ,
519 or any user-defined type.
520 Message fields cannot be declared as arrays.
521 .LP
522 A message field of type
523 .CW chan
524 can be used to pass a channel identifier
525 through a channel from one process to another.
526 .LP
527 The statement
528 .P1
529 qname!expr1,expr2
530 .P2
531 sends the values of expressions
532 .CW expr1
533 and
534 .CW expr2
535 to the channel that we just created.  It appends
536 the message field created from the values of the two
537 expressions (and cast to the appropriate types of the
538 message fields declared for
539 .CW qname )
540 to the tail of the message buffer of 16 slots that belongs
541 to channel
542 .CW qname .
543 By default the send statement is only executable if the target
544 channel is non-full.
545 (This default semantics can be changed in the verifier into
546 one where the send statement is always executable, but the
547 message will be lost when an attempt is made to append it to
548 a full channel.)
549 .LP
550 The statement
551 .P1
552 qname?var1,var2
553 .P2
554 retrieves a message from the head of the same buffer,
555 and stores the two expressions in variables
556 .CW var1
557 and
558 .CW var2 .
559 .LP
560 The receive statement is executable only if the source channel
561 is non-empty.
562 .LP
563 If more parameters are sent per message than were declared
564 for the message channel, the redundant parameters are lost.
565 If fewer parameters are sent than declared,
566 the value of the remaining parameters is undefined.
567 Similarly, if the receive operation tries to retrieve more
568 parameters than available, the value of the extra parameters is
569 undefined; if it receives fewer than the number of parameters
570 sent, the extra information is lost.
571 .LP
572 An alternative, and equivalent, notation for the
573 send and receive operations is to structure the
574 message fields with parentheses, as follows:
575 .P1
576 qname!expr1(expr2,expr3)
577 qname?var1(var2,var3)
578 .P2
579 In the above case, we assume that
580 .CW qname
581 was declared to hold messages consisting of three fields.
582 .PP
583 Some or all of the arguments of the receive operation
584 can be given as constants instead of as variables:
585 .P1
586 qname?cons1,var2,cons2
587 .P2
588 In this case, an extra condition on the executability of the
589 receive operation is that the value of all message fields
590 specified as constants match the value of the corresponding
591 fields in the message that is to be received.
592 .LP
593 Here is an example that uses some of the mechanisms introduced
594 so far.
595 .P1
596 proctype A(chan q1)
597 {       chan q2;
598         q1?q2;
599         q2!123
600 }
601 .P2
602 .P1
603 proctype B(chan qforb)
604 {       int x;
605         qforb?x;
606         printf("x = %d\en", x)
607 }
608 .P2
609 .P1
610 init {
611         chan qname = [1] of { chan };
612         chan qforb = [1] of { int };
613         run A(qname);
614         run B(qforb);
615         qname!qforb
616 }
617 .P2
618 The value printed by the process of type
619 .CW B
620 will be
621 .CW 123 .
622 .LP
623 A predefined function
624 .CW len(qname)
625 returns the number of messages currently
626 stored in channel
627 .CW qname .
628 Two shorthands for the most common uses of this
629 function are
630 .CW empty(qname)
631 and
632 .CW full(qname) ,
633 with the obvious connotations.
634 .LP
635 Since all expressions must be side-effect free,
636 it is not valid to say:
637 .P1
638 (qname?var == 0)
639 .P2
640 or
641 .P1
642 (a > b && qname!123)
643 .P2
644 We could rewrite the second example (using an atomic sequence,
645 as explained further in section 1.2.1):
646 .P1
647 atomic { (a > b && !full(qname)) -> qname!123 }
648 .P2
649 The meaning of the first example is ambiguous.  It could mean
650 that we want the condition to be true if the receive operation
651 is unexecutable.  In that case, we can rewrite it without
652 side-effects as:
653 .P1
654 empty(qname)
655 .P2
656 It could also mean that we want the condition
657 to be true when the channel does contain a message with
658 value zero.
659 We can specify that as follows:
660 .P1
661 atomic { qname?[0] -> qname?var }
662 .P2
663 The first statement of this atomic sequence is
664 an expression without side-effects that
665 evaluates to a non-zero value only if the
666 receive operation
667 .P1
668 qname?0
669 .P2
670 would have been executable at that
671 point (i.e., channel
672 .CW qname
673 contains at least one message and the oldest
674 message stored consists of one message field
675 equal to zero).
676 Any receive statement can be turned into
677 a side-effect free expression by placing square
678 brackets around the list of all message parameters.
679 The channel contents remain undisturbed by the
680 evaluation of such expressions.
681 .LP
682 Note carefully, however, that in non-atomic sequences
683 of two statements such as
684 .P1
685 !full(qname) -> qname!msgtype
686 .P2
687 and
688 .P1
689 qname?[msgtype] -> qname?msgtype
690 .P2
691 the second statement is not necessarily executable
692 after the first one has been executed.
693 There may be race conditions when access to the channels
694 is shared between several processes.
695 Another process can send a message to the channel
696 just after this process determined that it was not full,
697 or another process can steal away the
698 message just after our process determined its presence.
699 .LP
700 Two other types of send and receive statements are used
701 less frequently: sorted send and random receive.
702 A sorted send operation is written with two, instead of one,
703 exclamation marks, as follows:
704 .P1
705 qname!!msg
706 .P2
707 A sorted send operation will insert a message into the channel's buffer
708 in numerical order, instead of in FIFO order.
709 The channel contents are scanned from the first message towards the
710 last, and the message is inserted immediately before the first message
711 that follows it in numerical order.
712 To determine the numerical order, all message fields are
713 taken into account.
714 .LP
715 The logical counterpart of the sorted send operation
716 is the random receive.
717 It is written with two, instead of one, question marks:
718 .P1
719 qname??msg
720 .P2
721 A random receive operation is executable if it is executable for \f2any\f1
722 message that is currently buffered in a message channel (instead of
723 only for the first message in the channel).
724 Normal send and receive operations can freely be combined with
725 sorted send and random receive operations.
726 .SH
727 Rendezvous Communication
728 .LP
729 So far we have talked about asynchronous communication between processes
730 via message channels, declared in statements such as
731 .P1
732 chan qname = [N] of { byte }
733 .P2
734 where
735 .CW N
736 is a positive constant that defines the buffer size.
737 A logical extension is to allow for the declaration
738 .P1
739 chan port = [0] of { byte }
740 .P2
741 to define a rendezvous port.
742 The channel size is zero, that is, the channel
743 .CW port
744 can pass, but cannot store, messages.
745 Message interactions via such rendezvous ports are
746 by definition synchronous.
747 Consider the following example:
748 .P1
749 #define msgtype 33
750
751 chan name = [0] of { byte, byte };
752
753 active proctype A()
754 {       name!msgtype(124);
755         name!msgtype(121)
756 }
757 .P2
758 .P1
759 active proctype B()
760 {       byte state;
761         name?msgtype(state)
762 }
763 .P2
764 Channel
765 .CW name
766 is a global rendezvous port.
767 The two processes will synchronously execute their first statement:
768 a handshake on message
769 .CW msgtype
770 and a transfer of the value 124 to local variable
771 .CW state .
772 The second statement in process
773 .CW A
774 will be unexecutable,
775 because there is no matching receive operation in process
776 .CW B .
777 .LP
778 If the channel
779 .CW name
780 is defined  with a non-zero buffer capacity,
781 the behavior is different.
782 If the buffer size is at least 2, the process of type
783 .CW A
784 can complete its execution, before its peer even starts.
785 If the buffer size is 1, the sequence of events is as follows.
786 The process of type
787 .CW A
788 can complete its first send action, but it blocks on the
789 second, because the channel is now filled to capacity.
790 The process of type
791 .CW B 
792 can then retrieve the first message and complete.
793 At this point
794 .CW A
795 becomes executable again and completes,
796 leaving its last message as a residual in the channel.
797 .LP
798 Rendezvous communication is binary: only two processes,
799 a sender and a receiver, can be synchronized in a
800 rendezvous handshake.
801 .LP
802 As the example shows, symbolic constants can be defined
803 with preprocessor macros using
804 .CW #define .
805 The source text of a \*P model is translated by the standard
806 C preprocessor.
807 The disadvantage of defining symbolic names in this way is,
808 however, that the \*P parser will only see the expanded text,
809 and cannot refer to the symbolic names themselves.
810 To prevent that, \*P also supports another way to define
811 symbolic names, which are preserved in error reports.
812 For instance, by including the declaration
813 .P1
814 mtype = { ack, msg, error, data };
815 .P2
816 at the top of a \*P model, the names provided between the
817 curly braces are equivalent to integers of type
818 .CW byte ,
819 but known by their symbolic names to the \*V parser and the
820 verifiers it generates.
821 The constant values assigned start at 1, and count up.
822 There can be only one
823 .CW mtype
824 declaration per model.
825 .NH 2
826 Control Flow
827 .LP
828 So far, we have seen only some of the basic statements
829 of \*P, and the way in which they can be combined to
830 model process behaviors.
831 The five types of statements we have mentioned are:
832 .CW printf ,
833 .CW assignment ,
834 .CW condition ,
835 .CW send ,
836 and
837 .CW receive .
838 .LP
839 The pseudo-statement
840 .CW skip
841 is syntactically and semantically equivalent to the
842 condition
843 .CW (1)
844 (i.e., to true), and is in fact quietly replaced with this
845 expression by the lexical analyzer of \*V.
846 .LP
847 There are also five types of compound statements.
848 .IP
849 .RS
850 \(bu
851 Atomic sequences (section 1.2.1),
852 .br
853 \(bu
854 Deterministic steps (section 1.2.2),
855 .br
856 \(bu
857 Selections (section 1.2.3),
858 .br
859 \(bu
860 Repetitions (section 1.2.4),
861 .br
862 \(bu
863 Escape sequences (section 1.2.5).
864 .RE
865 .LP
866 .NH 3
867 Atomic Sequences
868 .LP
869 The simplest compound statement is the
870 .CW atomic
871 sequence:
872 .P1
873 atomic {        /* swap the values of a and b */
874         tmp = b;
875         b = a;
876         a = tmp
877 }
878 .P2
879 In the example, the values of two variables
880 .CW a
881 and
882 .CW b
883 are swapped in a sequence of statement executions
884 that is defined to be uninterruptable.
885 That is, in the interleaving of process executions, no
886 other process can execute statements from the moment that
887 the first statement of this sequence begins to execute until
888 the last one has completed.
889 .LP
890 It is often useful to use
891 .CW atomic
892 sequences to start a series of processes in such a
893 way that none of them can start executing statements
894 until all of them have been initialized:
895 .P1
896 init {
897         atomic {
898                 run A(1,2);
899                 run B(2,3);
900                 run C(3,1)
901         }
902 }
903 .P2
904 .CW Atomic
905 sequences may be non-deterministic.
906 If any statement inside an
907 .CW atomic
908 sequence is found to be unexecutable, however,
909 the atomic chain is broken, and another process can take over
910 control.
911 When the blocking statement becomes executable later,
912 control can non-deterministically return to the process,
913 and the atomic execution of the sequence resumes as if
914 it had not been interrupted.
915 .NH 3
916 Deterministic Steps
917 .LP
918 Another way to define an indivisible sequence of actions
919 is to use the
920 .CW d_step
921 statement.
922 In the above case, for instance, we could also have written:
923 .P1
924 d_step {        /* swap the values of a and b */
925         tmp = b;
926         b = a;
927         a = tmp
928 }
929 .P2
930 The difference between a
931 .CW d_step
932 sequence
933 and an
934 .CW atomic
935 sequence are:
936 .IP \(bu
937 A
938 .CW d_step
939 sequence must be completely deterministic.
940 (If non-determinism is nonetheless encountered,
941 it is always resolved in a fixed and deterministic
942 way: i.e., the first true guard in selection or
943 repetition structures is always selected.)
944 .IP \(bu
945 No
946 .CW goto
947 jumps into or out of a
948 .CW d_step
949 sequence are permitted.
950 .IP \(bu
951 The execution of a
952 .CW d_step
953 sequence cannot be interrupted when a
954 blocking statement is encountered.
955 It is an error if any statement other than
956 the first one in a
957 .CW d_step
958 sequence is found to be unexecutable.
959 .IP \(bu
960 A
961 .CW d_step
962 sequence is executed as one single statement.
963 In a way, it is a mechanism for adding new types
964 of statements to the language.
965 .LP
966 None of the items listed above apply to
967 .CW atomic
968 sequences.
969 This means that the keyword
970 .CW d_step
971 can always be replaced with the keyword
972 .CW atomic ,
973 but the reverse is not true.
974 (The main, perhaps the only, reason for using
975 .CW d_step
976 sequences is to improve the efficiency of
977 verifications.)
978 .NH 3
979 Selection Structures
980 .LP
981 A more interesting construct is the selection structure.
982 Using the relative values of two variables
983 .CW a
984 and
985 .CW b
986 to choose between two options, for instance, we can write:
987 .P1
988 if
989 :: (a != b) -> option1
990 :: (a == b) -> option2
991 fi
992 .P2
993 The selection structure above contains two execution sequences,
994 each preceded by a double colon.
995 Only one sequence from the list will be executed.
996 A sequence can be selected only if its first statement is executable.
997 The first statement is therefore called a \f2guard\f1.
998 .LP
999 In the above example the guards are mutually exclusive, but they
1000 need not be.
1001 If more than one guard is executable, one of the corresponding sequences
1002 is selected nondeterministically.
1003 If all guards are unexecutable the process will block until at least
1004 one of them can be selected.
1005 There is no restriction on the type of statements that can be used
1006 as a guard: it may include sends or receives, assignments,
1007 .CW printf ,
1008 .CW skip ,
1009 etc.
1010 The rules of executability determine in each case what the semantics
1011 of the complete selection structure will be.
1012 The following example, for instance, uses receive statements
1013 as guards in a selection.
1014 .P1
1015 mtype = { a, b };
1016
1017 chan ch = [1] of { byte };
1018
1019 active proctype A()
1020 {       ch!a
1021 }
1022 .P2
1023 .P1
1024 active proctype B()
1025 {       ch!b
1026 }
1027 .P2
1028 .P1
1029 active proctype C()
1030 {       if
1031         :: ch?a
1032         :: ch?b
1033         fi
1034 }
1035 .P2
1036 The example defines three processes and one channel.
1037 The first option in the selection structure of the process
1038 of type
1039 .CW C
1040 is executable if the channel contains
1041 a message named
1042 .CW a ,
1043 where
1044 .CW a
1045 is a symbolic constant defined in the
1046 .CW mtype
1047 declaration at the start of the program.
1048 The second option is executable if it contains a message
1049 .CW b ,
1050 where, similarly,
1051 .CW b
1052 is a symbolic constant.
1053 Which message will be available depends on the unknown
1054 relative speeds of the processes.
1055 .LP
1056 A process of the following type will either increment
1057 or decrement the value of variable
1058 .CW count
1059 once.
1060 .P1
1061 byte count;
1062
1063 active proctype counter()
1064 {
1065         if
1066         :: count++
1067         :: count--
1068         fi
1069 }
1070 .P2
1071 Assignments are always executable, so the choice made
1072 here is truly a non-deterministic one that is independent
1073 of the initial value of the variable (zero in this case).
1074 .NH 3
1075 Repetition Structures
1076 .LP
1077 We can modify the above program as follows, to obtain
1078 a cyclic program that randomly changes the value of
1079 the variable up or down, by replacing the selection
1080 structure with a repetition.
1081 .P1
1082 byte count;
1083
1084 active proctype counter()
1085 {
1086         do
1087         :: count++
1088         :: count--
1089         :: (count == 0) -> break
1090         od
1091 }
1092 .P2
1093 Only one option can be selected for execution at a time.
1094 After the option completes, the execution of the structure
1095 is repeated.
1096 The normal way to terminate the repetition structure is
1097 with a
1098 .CW break
1099 statement.
1100 In the example, the loop can be
1101 broken only when the count reaches zero.
1102 Note, however, that it need not terminate since the other
1103 two options remain executable.
1104 To force termination we could modify the program as follows.
1105 .P1
1106 active proctype counter()
1107 {
1108         do
1109         :: (count != 0) ->
1110                 if
1111                 :: count++
1112                 :: count--
1113                 fi
1114         :: (count == 0) -> break
1115         od
1116 }
1117 .P2
1118 A special type of statement that is useful in selection
1119 and repetition structures is the
1120 .CW else
1121 statement.
1122 An
1123 .CW else
1124 statement becomes executable only if no other statement
1125 within the same process, at the same control-flow point,
1126 is executable.
1127 We could try to use it in two places in the above example:
1128 .P1
1129 active proctype counter()
1130 {
1131         do
1132         :: (count != 0) ->
1133                 if
1134                 :: count++
1135                 :: count--
1136                 :: else
1137                 fi
1138         :: else -> break
1139         od
1140 }
1141 .P2
1142 The first
1143 .CW else ,
1144 inside the nested selection structure, can never become
1145 executable though, and is therefore redundant (both alternative
1146 guards of the selection are assignments, which are always
1147 executable).
1148 The second usage of the
1149 .CW else ,
1150 however, becomes executable exactly when
1151 .CW "!(count != 0)"
1152 or
1153 .CW "(count == 0)" ,
1154 and is therefore equivalent to the latter to break from the loop.
1155 .LP
1156 There is also an alternative way to exit the do-loop, without
1157 using a
1158 .CW break
1159 statement:  the infamous
1160 .CW goto .
1161 This is illustrated in the following implementation of
1162 Euclid's algorithm for finding the greatest common divisor
1163 of two non-zero, positive numbers:
1164 .P1
1165 proctype Euclid(int x, y)
1166 {
1167         do
1168         :: (x >  y) -> x = x - y
1169         :: (x <  y) -> y = y - x
1170         :: (x == y) -> goto done
1171         od;
1172 done:
1173         skip
1174 }
1175 .P2
1176 .P1
1177 init { run Euclid(36, 12) }
1178 .P2
1179 The
1180 .CW goto
1181 in this example jumps to a label named
1182 .CW done .
1183 Since a label can only appear before a statement,
1184 we have added the dummy statement
1185 .CW skip .
1186 Like a
1187 .CW skip ,
1188 a
1189 .CW goto
1190 statement is always executable and has no other
1191 effect than to change the control-flow point
1192 of the process that executes it.
1193 .LP
1194 As a final example, consider the following implementation of
1195 a Dijkstra semaphore, which is implemented with the help of
1196 a synchronous channel.
1197 .P1
1198 #define p       0
1199 #define v       1
1200
1201 chan sema = [0] of { bit };
1202 .P2
1203 .P1
1204 active proctype Dijkstra()
1205 {       byte count = 1;
1206
1207         do
1208         :: (count == 1) ->
1209                 sema!p; count = 0
1210         :: (count == 0) ->
1211                 sema?v; count = 1
1212         od      
1213 }
1214 .P2
1215 .P1
1216 active [3] proctype user()
1217 {       do
1218         :: sema?p;
1219            /* critical section */
1220            sema!v;
1221            /* non-critical section */
1222         od
1223 }
1224 .P2
1225 The semaphore guarantees that only one of the three user processes
1226 can enter its critical section at a time.
1227 It does not necessarily prevent the monopolization of
1228 the access to the critical section by one of the processes.
1229 .LP
1230 \*P does not have a mechanism for defining functions or
1231 procedures.  Where necessary, though, these may be
1232 modeled with the help of additional processes.
1233 The return value of a function, for instance, can be passed
1234 back to the calling process via global variables or messages.
1235 The following program illustrates this by recursively
1236 calculating the factorial of a number
1237 .CW n .
1238 .P1
1239 proctype fact(int n; chan p)
1240 {       chan child = [1] of { int };
1241         int result;
1242
1243         if
1244         :: (n <= 1) -> p!1
1245         :: (n >= 2) ->
1246                 run fact(n-1, child);
1247                 child?result;
1248                 p!n*result
1249         fi
1250 }
1251 .P2
1252 .P1
1253 init
1254 {       chan child = [1] of { int };
1255         int result;
1256
1257         run fact(7, child);
1258         child?result;
1259         printf("result: %d\en", result)
1260 }
1261 .P2
1262 Each process creates a private channel and uses it
1263 to communicate with its direct descendant.
1264 There are no input statements in \*P.
1265 The reason is that models must always be complete to
1266 allow for logical verifications, and input statements
1267 would leave at least the source of some information unspecified.
1268 A way to read input
1269 would presuppose a source of information that is not
1270 part of the model.
1271 .LP
1272 We have already discussed a few special types of statement:
1273 .CW skip ,
1274 .CW break ,
1275 and
1276 .CW else .
1277 Another statement in this class is the
1278 .CW timeout .
1279 The
1280 .CW timeout
1281 is comparable to a system level
1282 .CW else
1283 statement: it becomes executable if and only if no other
1284 statement in any of the processes is executable.
1285 .CW Timeout
1286 is a modeling feature that provides for an escape from a
1287 potential deadlock state.
1288 The
1289 .CW timeout
1290 takes no parameters, because the types of properties we
1291 would like to prove for \*P models must be proven independent
1292 of all absolute and relative timing considerations.
1293 In particular, the relative speeds of processes can never be
1294 known with certainty in an asynchronous system.
1295 .NH 3
1296 Escape Sequences
1297 .LP
1298 The last type of compound structure to be discussed is the
1299 .CW unless
1300 statement.
1301 It is used as follows:
1302 .MT _sec5unless
1303 .P1
1304 { P } unless { E }
1305 .P2
1306 where the letters
1307 .CW P
1308 and
1309 .CW E
1310 represent arbitrary \*P fragments.
1311 Execution of the
1312 .CW unless
1313 statement begins with the execution of statements from
1314 .CW P .
1315 Before each statement execution in
1316 .CW P
1317 the executability of the first statement of
1318 .CW E
1319 is checked, using the normal \*P semantics of executability.
1320 Execution of statements from
1321 .CW P
1322 proceeds only while the first statement of
1323 .CW E
1324 remains unexecutable.
1325 The first time that this `guard of the escape sequence'
1326 is found to be executable, control changes to it,
1327 and execution continues as defined for
1328 .CW E .
1329 Individual statement executions remain indivisible,
1330 so control can only change from inside
1331 .CW P
1332 to the start of
1333 .CW E
1334 in between individual statement executions.
1335 If the guard of the escape sequence
1336 does not become executable during the
1337 execution of
1338 .CW P ,
1339 then it is skipped entirely when
1340 .CW P
1341 terminates.
1342 .LP
1343 An example of the use of escape sequences is:
1344 .P1
1345 A;
1346 do
1347 :: b1 -> B1
1348 :: b2 -> B2
1349 \&...
1350 od
1351 unless { c -> C };
1352 D
1353 .P2
1354 As shown in the example, the curly braces around the main sequence
1355 (or the escape sequence) can be deleted if there can be no confusion
1356 about which statements belong to those sequences.
1357 In the example, condition
1358 .CW c
1359 acts as a watchdog on the repetition construct from the main sequence.
1360 Note that this is not necessarily equivalent to the construct
1361 .P1
1362 A;
1363 do
1364 :: b1 -> B1
1365 :: b2 -> B2
1366 \&...
1367 :: c -> break
1368 od;
1369 C; D
1370 .P2
1371 if
1372 .CW B1
1373 or
1374 .CW B2
1375 are non-empty.
1376 In the first version of the example, execution of the iteration can
1377 be interrupted at \f2any\f1 point inside each option sequence.
1378 In the second version, execution can only be interrupted at the
1379 start of the option sequences.
1380 .NH 2
1381 Correctness Properties
1382 .LP
1383 There are three ways to express correctness properties in \*P,
1384 using:
1385 .IP
1386 .RS
1387 .br
1388 \(bu
1389 Assertions (section 1.3.1),
1390 .br
1391 \(bu
1392 Special labels (section 1.3.2),
1393 .br
1394 \(bu
1395 .CW Never
1396 claims (section 1.3.3).
1397 .RE
1398 .LP
1399 .NH 3
1400 Assertions
1401 .LP
1402 Statements of the form
1403 .P1
1404 assert(expression)
1405 .P2
1406 are always executable.
1407 If the expression evaluates to a non-zero value (i.e., the
1408 corresponding condition holds), the statement has no effect
1409 when executed.
1410 The correctness property expressed, though, is that it is
1411 impossible for the expression to evaluate to zero (i.e., for
1412 the condition to be false).
1413 A failing assertion will cause execution to be aborted.
1414 .NH 3
1415 Special Labels
1416 .LP
1417 Labels in a \*P specification ordinarily serve as
1418 targets for unconditional
1419 .CW goto
1420 jumps, as usual.
1421 There are, however, also three types of labels that
1422 have a special meaning to the verifier.
1423 We discuss them in the next three subsections.
1424 .NH 4
1425 End-State Labels
1426 .LP
1427 When a \*P model is checked for reachable deadlock states
1428 by the verifier, it must be able to distinguish valid \f2end state\f1s
1429 from invalid ones.
1430 By default, the only valid end states are those in which
1431 every \*P process that was instantiated has reached the end of
1432 its code.
1433 Not all \*P processes, however, are meant to reach the
1434 end of their code.
1435 Some may very well linger in a known wait
1436 state, or they may sit patiently in a loop
1437 ready to spring into action when new input arrives.
1438 .LP
1439 To make it clear to the verifier that these alternate end states
1440 are also valid, we can define special end-state labels.
1441 We can do so, for instance, in the process type
1442 .CW Dijkstra ,
1443 from an earlier example:
1444 .P1
1445 proctype Dijkstra()
1446 {       byte count = 1;
1447
1448 end:    do
1449         :: (count == 1) ->
1450                 sema!p; count = 0
1451         :: (count == 0) ->
1452                 sema?v; count = 1
1453         od      
1454 }
1455 .P2
1456 The label
1457 .CW end
1458 defines that it is not an error if, at the end of an
1459 execution sequence, a process of this type
1460 has not reached its closing curly brace, but waits at the label.
1461 Of course, such a state could still be part of a deadlock state, but
1462 if so, it is not caused by this particular process.
1463 .LP
1464 There may be more than one end-state label per \*P model.
1465 If so, all labels that occur within the same process body must
1466 be unique.
1467 The rule is that every label name with the prefix
1468 .CW end
1469 is taken to be an end-state label.
1470 .NH 4
1471 Progress-State Labels
1472 .LP
1473 In the same spirit, \*P also allows for the definition of
1474 .CW progress
1475 labels.
1476 Passing a progress label during an execution is interpreted
1477 as a good thing:  the process is not just idling while
1478 waiting for things to happen elsewhere, but is making
1479 effective progress in its execution.
1480 The implicit correctness property expressed here is that any
1481 infinite execution cycle allowed by the model that does not
1482 pass through at least one of these progress labels is a
1483 potential starvation loop.
1484 In the
1485 .CW Dijkstra
1486 example, for instance, we can label the
1487 successful passing of a semaphore test as progress and
1488 ask a verifier to make sure that there is no cycle elsewhere
1489 in the system.
1490 .P1
1491 proctype Dijkstra()
1492 {       byte count = 1;
1493
1494 end:    do
1495         :: (count == 1) ->
1496 progress:       sema!p; count = 0
1497         :: (count == 0) ->
1498                 sema?v; count = 1
1499         od      
1500 }
1501 .P2
1502 If more than one state carries a progress label,
1503 variations with a common prefix are again valid.
1504 .NH 4
1505 Accept-State Labels
1506 .LP
1507 The last type of label, the accept-state label, is used
1508 primarily in combination with
1509 .CW never
1510 claims.
1511 Briefly, by labeling a state with any label starting
1512 with the prefix
1513 .CW accept
1514 we can ask the verifier to find all cycles that \f2do\f1
1515 pass through at least one of those labels.
1516 The implicit correctness claim is that this cannot happen.
1517 The primary place where accept labels are used is inside
1518 .CW never
1519 claims.
1520 We discuss
1521 .CW never
1522 claims next.
1523 .NH 3
1524 Never Claims
1525 .LP
1526 Up to this point we have talked about the specification
1527 of correctness criteria with assertions
1528 and with three special types of labels.
1529 Powerful types of correctness criteria can already
1530 be expressed with these tools, yet so far our only option is
1531 to add them to individual
1532 .CW proctype
1533 declarations.
1534 We can, for instance, express the claim ``every system state
1535 in which property
1536 .CW P
1537 is true eventually leads to a system state in which property
1538 .CW Q
1539 is true,'' with an extra monitor process, such as:
1540 .P1
1541 active proctype monitor()
1542 {
1543 progress:
1544         do
1545         :: P -> Q
1546         od
1547 }
1548 .P2
1549 If we require that property
1550 .CW P
1551 must \f2remain\f1 true while we are waiting
1552 .CW Q
1553 to become true, we can try to change this to:
1554 .P1
1555 active proctype monitor()
1556 {
1557 progress:
1558         do
1559         :: P -> assert(P || Q)
1560         od
1561 }
1562 .P2
1563 but this does not quite do the job.
1564 Note that we cannot make any assumptions about the
1565 relative execution speeds of processes in a \*P model.
1566 This means that if in the remainder of the system the
1567 property
1568 .CW P
1569 becomes true, we can move to the state just before the
1570 .CW assert ,
1571 and wait there for an unknown amount of time (anything between
1572 a zero delay and an infinite delay is possible here, since
1573 no other synchronizations apply).
1574 If
1575 .CW Q
1576 becomes true, we may pass the assertion, but we need not
1577 do so.
1578 Even if
1579 .CW P
1580 becomes false only \f2after\f1
1581 .CW Q
1582 has become true, we may still fail the assertion,
1583 as long as there exists some later state where neither
1584 .CW P
1585 nor
1586 .CW Q
1587 is true.
1588 This is clearly unsatisfactory, and we need another mechanism
1589 to express these important types of liveness properties.
1590 .SH
1591 The Connection with Temporal Logic
1592 .LP
1593 A general way to express system properties of the type we
1594 have just discussed is to use linear time temporal logic (LTL)
1595 formulae.
1596 Every \*P expression is automatically also a valid LTL formula.
1597 An LTL formula can also contain the unary temporal operators â–¡
1598 (pronounced always), â—Š (pronounced eventually), and
1599 two binary temporal operators
1600 .CW U
1601 (pronounced weak until) and
1602 .BI U
1603 (pronounced strong until).
1604 .LP
1605 Where the value of a \*P expression without temporal operators can be
1606 defined uniquely for individual system states, without further context,
1607 the truth value of an LTL formula is defined for sequences of states:
1608 specifically, it is defined for the first state of a given infinite
1609 sequence of system states (a trace).
1610 Given, for instance, the sequence of system states:
1611 .P1
1612 s0;s1;s2;...
1613 .P2
1614 the LTL formula
1615 .CW pUq ,
1616 with
1617 .CW p
1618 and
1619 .CW q
1620 standard \*P expressions, is true for
1621 .CW s0
1622 either if
1623 .CW q
1624 is true in
1625 .CW s0 ,
1626 or if
1627 .CW p
1628 is true in
1629 .CW s0 
1630 and
1631 .CW pUq
1632 holds for the remainder of the sequence after
1633 .CW s0 .
1634 .LP
1635 Informally,
1636 .CW pUq
1637 says that
1638 .CW p
1639 is required to hold at least until
1640 .CW q
1641 becomes true.
1642 If, instead, we would write \f(CWp\f(BIU\f(CWq\f1,
1643 then we also require that there exists at least
1644 one state in the sequence where
1645 .CW q
1646 does indeed become true.
1647 .LP
1648 The temporal operators â–¡ and â—Š
1649 can be defined in terms of the strong until operator
1650 .BI U ,
1651 as follows.
1652 .P1
1653 â–¡ p = !â—Š !p = !(true \f(BIU\f(CW !p)
1654 .P2
1655 Informally, â–¡
1656 .CW p
1657 says that property
1658 .CW p
1659 must hold in all states of a trace, and â—Š
1660 .CW p
1661 says that
1662 .CW p
1663 holds in at least one state of the trace.
1664 .LP
1665 To express our original example requirement: ``every system state
1666 in which property
1667 .CW P
1668 is true eventually leads to a system state in which property
1669 .CW Q
1670 is true,''
1671 we can write the LTL formula:
1672 .P1
1673 â–¡ (P -> â—Š Q)
1674 .P2
1675 where the logical implication symbol
1676 .CW ->
1677 is defined in the usual way as
1678 .P1
1679 P => Q means !P || Q
1680 .P2
1681 .SH
1682 Mapping LTL Formulae onto Never Claims
1683 .LP
1684 \*P does not include syntax for specifying LTL formulae
1685 directly, but it relies on the fact that every such
1686 formula can be translated into a special type of
1687 automaton, known as a Büchi automaton.
1688 In the syntax of \*P this automaton is called a
1689 .CW never
1690 claim.
1691 If you don't care too much about the details of
1692 .CW never
1693 claims, you can skip the remainder of this section and
1694 simple remember that \*V can convert any LTL formula
1695 automatically into the proper never claim syntax with
1696 the command:
1697 .P1
1698 spin -f "...formula..."
1699 .P2
1700 Here are the details.
1701 The syntax of a never claim is:
1702 .P1
1703 never {
1704         \&...
1705 }
1706 .P2
1707 where the dots can contain any \*P fragment, including
1708 arbitrary repetition, selection, unless constructs,
1709 jumps, etc.
1710 .LP
1711 There is an important difference in semantics between a
1712 .CW proctype
1713 declaration and a
1714 .CW never
1715 claim.
1716 Every statement inside a
1717 .CW never
1718 claim is interpreted as a proposition, i.e., a condition.
1719 A
1720 .CW never
1721 claim should therefore only contain expressions and never
1722 statements that can have side-effects (assignments, sends or
1723 receives, run-statements, etc.)
1724 .LP
1725 .CW Never
1726 claims are used to express behaviors that are considered
1727 undesirable or illegal.
1728 We say that a
1729 .CW never
1730 claim is `matched' if the undesirable behavior can be realized,
1731 contrary to the claim, and thus the correctness requirement violated.
1732 The claims are evaluated over system executions, that is, the
1733 propositions that are listed in the claim are evaluated over the
1734 traces from the remainder of the system.
1735 The claim, therefore, should not alter that behavior: it merely
1736 monitors it.
1737 Every time that the system reaches a new state, by asynchronously
1738 executing statements from the model, the claim will evaluate the
1739 appropriate propositions to determine if a counter-example can
1740 be constructed to the implicit LTL formula that is specified.
1741 .LP
1742 Since LTL formulae are only defined for infinite executions,
1743 the behavior of a
1744 .CW never
1745 claim can only be matched by an infinite system execution.
1746 This by itself would restrict us to the use of progress labels
1747 and accept labels as the only means we have discussed so far
1748 for expressing properties of infinite behaviors.
1749 To conform to standard omega automata theory, the behaviors of
1750 .CW never
1751 claims are expressed exclusively with
1752 .CW accept
1753 labels (never with
1754 .CW progress
1755 labels).
1756 To match a claim, therefore, an infinite sequence of true propositions
1757 must exist, at least one of which is labeled with an
1758 .CW accept
1759 label (inside the never claim).
1760 .LP
1761 Since \*P models can also express terminating system behaviors,
1762 we have to define the semantics of the
1763 .CW never
1764 claims also for those behaviors.
1765 To facilitate this, it is defined that a
1766 .CW never
1767 claim can also be matched when it reaches its closing curly brace
1768 (i.e., when it appears to terminate).
1769 This semantics is based on what is usually referred to as a `stuttering
1770 semantics.'
1771 With stuttering semantics, any terminating execution can be extended
1772 into an equivalent infinite execution (for the purposes of evaluating
1773 LTL properties) by repeating (stuttering) the final state infinitely often.
1774 As a syntactical convenience, the final state of a
1775 .CW never
1776 claim is defined to be accepting, i.e., it could be replaced with
1777 the explicit repetition construct:
1778 .P1
1779 accept: do :: skip od
1780 .P2
1781 Every process behavior, similarly, is (for the purposes of evaluating the
1782 .CW never
1783 claims) thought to be extended with a dummy self-loop on all final states:
1784 .P1
1785         do :: skip od
1786 .P2
1787 (Note the
1788 .CW accept
1789 labels only occur in the
1790 .CW never
1791 claim, not in the system.)
1792 .SH
1793 The Semantics of a Never Claim
1794 .LP
1795 .CW Never
1796 claims are probably the hardest part of the language to understand,
1797 so it is worth spending a few extra words on them.
1798 On an initial reading, feel free to skip the remainder of this
1799 section.
1800 .LP
1801 The difference between a
1802 .CW never
1803 claim and the remainder of a \*P system can be explained
1804 as follows.
1805 A \*P model defines an asynchronous interleaving product of the
1806 behaviors of individual processes.
1807 Given an arbitrary system state, its successor states are
1808 conceptually obtained in two steps.
1809 In a first step, all the executable statements in the
1810 individual processes are identified.
1811 In a second step, each one of these statements is executed,
1812 each one producing one potential successor for the current state.
1813 The complete system behavior is thus defined recursively and
1814 represents all possible interleavings of the individual process behaviors.
1815 It is this asynchronous product machine that we call the `global
1816 system behavior'.
1817 .LP
1818 The addition of a
1819 .CW never
1820 claim defines a \f2synchronous\f1 product of the global system behavior
1821 with the behavior expressed in the claim.
1822 This synchronous product can be thought of as the construction of a
1823 new global state machine, in which every state is defined as a pair
1824 .CW (s,n)
1825 with
1826 .CW s
1827 a state from the global system (the asynchronous product of processes), and
1828 .CW n
1829 a state from the claim.
1830 Every transition in the new global machine is similarly defined by a pair
1831 of transitions, with the first element a statement from the system, and the
1832 second a proposition from the claim.
1833 In other words, every transition in this final synchronous product is
1834 defined as a joint transition of the system and the claim.
1835 Of course, that transition can only occur if the proposition from the
1836 second half of the transition pair evaluates to true in the current state
1837 of the system (the first half of the state pair).
1838 .SH
1839 Examples
1840 .LP
1841 To manually translate an LTL formula into a
1842 .CW never
1843 claim (e.g. foregoing the builtin translation that \*V
1844 offers), we must carefully consider whether the
1845 formula expresses a positive or a negative property.
1846 A positive property expresses a good behavior that we
1847 would like our system to have.
1848 A negative property expresses a bad behavior that we
1849 claim the system does not have.
1850 A
1851 .CW never
1852 claim can express only negative claims, not positive ones.
1853 Fortunately, the two are exchangeable:  if we want to express
1854 that a good behavior is unavoidable, we can formalize all
1855 ways in which the good behavior could be violated, and express
1856 that in the
1857 .CW never
1858 claim.
1859 .LP
1860 Suppose that the LTL formula â—Šâ–¡
1861 .CW p ,
1862 with
1863 .CW p
1864 a \*P expression, expresses a negative claim
1865 (i.e., it is considered a correctness violation if
1866 there exists any execution sequence in which
1867 .CW p
1868 can eventually remain true infinitely long).
1869 This can be written in a
1870 .CW never
1871 claim as:
1872 .P1
1873 never { /* <>[]p */
1874         do
1875         :: skip /* after an arbitrarily long prefix */
1876         :: p -> break   /* p becomes true */
1877         od;
1878 accept: do
1879         :: p    /* and remains true forever after */
1880         od
1881 }
1882 .P2
1883 Note that in this case the claim does not terminate, and
1884 also does not necessarily match all system behaviors.
1885 It is sufficient if it precisely captures all violations
1886 of our correctness requirement, and no more.
1887 .LP
1888 If the LTL formula expressed a positive property, we first
1889 have to invert it to the corresponding negative property
1890 .CW â—Š!p
1891 and translate that into a
1892 .CW never
1893 claim.
1894 The requirement now says that it is a violation if
1895 .CW p
1896 does not hold infinitely long.
1897 .P1
1898 never { /* <>!p*/
1899         do
1900         :: skip
1901         :: !p -> break
1902         od
1903 }
1904 .P2
1905 We have used the implicit match of a claim upon reaching the
1906 closing terminating brace.
1907 Since the first violation of the property suffices to disprove
1908 it, we could also have written:
1909 .P1
1910 never { /* <>!p*/
1911         do
1912         :: p
1913         :: !p -> break
1914         od
1915 }
1916 .P2
1917 or, if we abandon the connection with LTL for a moment,
1918 even more tersely as:
1919 .P1
1920 never { do :: assert(p) od }
1921 .P2
1922 Suppose we wish to express that it is a violation of our
1923 correctness requirements if there exists any execution in
1924 the system where
1925 .CW "â–¡ (p -> â—Š q)"
1926 is violated (i.e., the negation of this formula is satisfied).
1927 The following
1928 .CW never
1929 claim expresses that property:
1930 .P1
1931 never {
1932         do
1933         :: skip
1934         :: p && !q -> break
1935         od;
1936 accept:
1937         do
1938         :: !q
1939         od
1940 }
1941 .P2
1942 Note that using
1943 .CW "(!p || q)"
1944 instead of
1945 .CW skip
1946 in the first repetition construct would imply a check for just
1947 the first occurrence of proposition
1948 .CW p
1949 becoming true in the execution sequence, while
1950 .CW q
1951 is false.
1952 The above formalization checks for all occurrences, anywhere in a trace.
1953 .LP
1954 Finally, consider a formalization of the LTL property
1955 .CW "â–¡ (p -> (q U r))" .
1956 The corresponding claim is:
1957 .P1
1958 never {
1959         do
1960         :: skip         /* to match any occurrence */
1961         :: p &&  q && !r -> break
1962         :: p && !q && !r -> goto error
1963         od;
1964         do
1965         ::  q && !r
1966         :: !q && !r -> break
1967         od;
1968 error:  skip
1969 }
1970 .P2
1971 Note again the use of
1972 .CW skip
1973 instead of
1974 .CW "(!p || r)"
1975 to avoid matching just the first occurrence of
1976 .CW "(p && !r)"
1977 in a trace.
1978 .NH 2
1979 Predefined Variables and Functions
1980 .LP
1981 The following predefined variables and functions
1982 can be especially useful in
1983 .CW never
1984 claims.
1985 .LP
1986 The predefined variables are:
1987 .CW _pid
1988 and
1989 .CW _last .
1990 .LP
1991 .CW _pid
1992 is a predefined local variable in each process
1993 that holds the unique instantiation number for
1994 that process.
1995 It is always a non-negative number.
1996 .LP
1997 .CW _last
1998 is a predefined global variable that always holds the
1999 instantiation number of the process that performed the last
2000 step in the current execution sequence.
2001 Its value is not part of the system state unless it is
2002 explicitly used in a specification.
2003 .P1
2004 never {
2005         /* it is not possible for the process with pid=1
2006          * to execute precisely every other step forever
2007          */
2008 accept:
2009         do
2010         :: _last != 1 -> _last == 1
2011         od
2012 }
2013 .P2
2014 The initial value of
2015 .CW _last
2016 is zero.
2017 .LP
2018 Three predefined functions are specifically intended to be used in
2019 .CW never
2020 claims, and may not be used elsewhere in a model:
2021 .CW pc_value(pid) ,
2022 .CW enabled(pid) ,
2023 .CW procname[pid]@label .
2024 .LP
2025 The function
2026 .CW pc_value(pid)
2027 returns the current control state
2028 of the process with instantiation number
2029 .CW pid ,
2030 or zero if no such process exists.
2031 .LP
2032 Example:
2033 .P1
2034 never {
2035         /* Whimsical use: claim that it is impossible
2036          * for process 1 to remain in the same control
2037          * state as process 2, or one with smaller value.
2038          */
2039 accept: do
2040         :: pc_value(1) <= pc_value(2)
2041         od
2042 }
2043 .P2
2044 The function
2045 .CW enabled(pid)
2046 tells whether the process with instantiation number
2047 .CW pid
2048 has an executable statement that it can execute next.
2049 .LP
2050 Example:
2051 .P1
2052 never {
2053         /* it is not possible for the process with pid=1
2054          * to remain enabled without ever executing
2055          */
2056 accept:
2057         do
2058         :: _last != 1 && enabled(1)
2059         od
2060 }
2061 .P2
2062 The last function
2063 .CW procname[pid]@label
2064 tells whether the process with instantiation number
2065 .CW pid
2066 is currently in the state labeled with
2067 .CW label
2068 in
2069 .CW "proctype procname" .
2070 It is an error if the process referred to is not an instantiation
2071 of that proctype.
2072 .NH 1
2073 Verifications with \*V
2074 .LP
2075 The easiest way to use \*V is probably on a Windows terminal
2076 with the Tcl/Tk implementation of \s-1XSPIN\s0.
2077 All functionality of \*V, however, is accessible from
2078 any plain ASCII terminal, and there is something to be
2079 said for directly interacting with the tool itself.
2080 .LP
2081 The description in this paper gives a short walk-through of
2082 a common mode of operation in using the verifier.
2083 A more tutorial style description of the verification
2084 process can be found in [Ho93].
2085 More detail on the verification of large systems with the
2086 help of \*V's supertrace (bitstate) verification algorithm
2087 can be found in [Ho95].
2088 .IP
2089 .RS
2090 .br
2091 \(bu
2092 Random and interactive simulations (section 2.1),
2093 .br
2094 \(bu
2095 Generating a verifier (section 2.2),
2096 .br
2097 \(bu
2098 Compilation for different types of searches (section 2.3),
2099 .br
2100 \(bu
2101 Performing the verification (section 2.4),
2102 .br
2103 \(bu
2104 Inspecting error traces produced by the verifier (section 2.5),
2105 .br
2106 \(bu
2107 Exploiting partial order reductions (section 2.6).
2108 .RE
2109 .LP
2110 .NH 2
2111 Random and Interactive Simulations
2112 .LP
2113 Given a model in \*P, say stored in a file called
2114 .CW spec ,
2115 the easiest mode of operation is to perform a random simulation.
2116 For instance,
2117 .P1
2118 spin -p spec
2119 .P2
2120 tells \*V to perform a random simulation, while printing the
2121 process moves selected for execution at each step (by default
2122 nothing is printed, other than explicit
2123 .CW printf
2124 statements that appear in the model itself).
2125 A range of options exists to make the traces more verbose,
2126 e.g., by adding printouts of local variables (add option
2127 .CW -l ),
2128 global variables (add option
2129 .CW -g ),
2130 send statements (add option
2131 .CW -s ),
2132 or receive statements (add option
2133 .CW -r ).
2134 Use option
2135 .CW -n N
2136 (with N any number) to fix the seed on \*V's internal
2137 random number generator, and thus make the simulation runs
2138 reproducible.
2139 By default the current time is used to seed the random number
2140 generator.
2141 For instance:
2142 .P1
2143 spin -p -l -g -r -s -n1 spec
2144 .P2
2145 .LP
2146 If you don't like the system randomly resolving non-deterministic
2147 choices for you, you can select an interactive simulation:
2148 .P1
2149 spin -i -p spec
2150 .P2
2151 In this case you will be offered a menu with choices each time
2152 the execution could proceed in more than one way.
2153 .LP
2154 Simulations, of course, are intended primarily for the
2155 debugging of a model.  They cannot prove anything about it.
2156 Assertions will be evaluated during simulation runs, and
2157 any violations that result will be reported, but none of
2158 the other correctness requirements can be checked in this way.
2159 .NH 2
2160 Generating the Verifier
2161 .LP
2162 A model-specific verifier is generated as follows:
2163 .P1
2164 spin -a spec
2165 .P2
2166 This generates a C program in a number of files (with names
2167 starting with
2168 .CW pan ).
2169 .NH 2
2170 Compiling the Verifier
2171 .LP
2172 At this point it is good to know the physical limitations of
2173 the computer system that you will run the verification on.
2174 If you know how much physical (not virtual) memory your system
2175 has, you can take advantage of that.
2176 Initially, you can simply compile the verifier for a straight
2177 exhaustive verification run (constituting the strongest type
2178 of proof if it can be completed).
2179 Compile as follows.
2180 .P1
2181 \*C -o pan pan.c                # standard exhaustive search
2182 .P2
2183 If you know a memory bound that you want to restrict the run to
2184 (e.g., to avoid paging), find the nearest power of 2 (e.g., 23
2185 for the bound $2 sup 23# bytes) and compile as follows.
2186 .P1
2187 \*C '-DMEMCNT=23' -o pan pan.c
2188 .P2
2189 or equivalently in terms of MegaBytes:
2190 .P1
2191 \*C '-DMEMLIM=8' -o pan pan.c
2192 .P2
2193 If the verifier runs out of memory before completing its task,
2194 you can decide to increase the bound or to switch to a frugal
2195 supertrace verification.  In the latter case, compile as follows.
2196 .P1
2197 \*C -DBITSTATE -o pan pan.c
2198 .P2
2199 .NH 2
2200 Performing the Verification
2201 .LP
2202 There are three specific decisions to make to
2203 perform verifications optimally: estimating the
2204 size of the reachable state space (section 2.4.1),
2205 estimating the maximum length of a unique execution
2206 sequence (2.4.2), and selecting the type of correctness
2207 property (2.4.3).
2208 No great harm is done if the estimates from the first two
2209 steps are off.  The feedback from the verifier usually provides
2210 enough clues to determine quickly what the optimal settings
2211 for peak performance should be.
2212 .NH 3
2213 Reachable States
2214 .LP
2215 For a standard exhaustive run, you can override the default choice
2216 for the size for the hash table ($2 sup 18# slots) with option
2217 .CW -w .
2218 For instance,
2219 .P1
2220 pan -w23
2221 .P2
2222 selects $2 sup 23# slots.
2223 The hash table size should optimally be roughly equal to the number of
2224 reachable states you expect (within say a factor of two or three).
2225 Too large a number merely wastes memory, too low a number wastes
2226 CPU time, but neither can affect the correctness of the result.
2227 .sp
2228 For a supertrace run, the hash table \f2is\f1 the memory arena, and
2229 you can override the default of $2 sup 22# bits with any other number.
2230 Set it to the maximum size of physical memory you can grab without
2231 making the system page, again within a factor of say two or three.
2232 Use, for instance
2233 .CW -w23
2234 if you expect 8 million reachable states and have access to at least
2235 8 million ($2 sup 23#) bits of memory (i.e., $2 sup 20# or 1 Megabyte of RAM).
2236 .NH 3
2237 Search Depth
2238 .LP
2239 By default the analyzers have a search depth restriction of 10,000 steps.
2240 If this isn't enough, the search will truncate at 9,999 steps (watch for
2241 it in the printout).
2242 Define a different search depth with the -m flag.
2243 .P1
2244 pan -m100000
2245 .P2
2246 If you exceed also this limit, it is probably good to take some
2247 time to consider if the model you have specified is indeed finite.
2248 Check, for instance, if no unbounded number of processes is created.
2249 If satisfied that the model is finite, increase the search depth at
2250 least as far as is required to avoid truncation completely.
2251 .LP
2252 If you find a particularly nasty error that takes a large number of steps
2253 to hit, you may also set lower search depths to find the shortest variant
2254 of an error sequence.
2255 .P1
2256 pan -m40
2257 .P2
2258 Go up or down by powers of two until you find the place where the
2259 error first appears or disappears and then home in on the first
2260 depth where the error becomes apparent, and use the error trail of
2261 that verification run for guided simulation.
2262 .sp
2263 Note that if a run with a given search depth fails to find
2264 an error, this does not necessarily mean that no violation of a
2265 correctness requirement is possible within that number of steps.
2266 The verifier performs its search for errors by using a standard
2267 depth-first graph search.  If the search is truncated at N steps,
2268 and a state at level N-1 happens to be reachable also within fewer
2269 steps from the initial state, the second time it is reached it
2270 will not be explored again, and thus neither will its successors.
2271 Those successors may contain errors states that are reachable within
2272 N steps from the initial state.
2273 Normally, the verification should be run in such a way that no
2274 execution paths can be truncated, but to force the complete exploration
2275 of also truncated searches one can override the defaults with a compile-time
2276 flag
2277 .CW -DREACH .
2278 When the verifier is compiled with that additional directive, the depth at
2279 which each state is visited is remembered, and a state is now considered
2280 unvisited if it is revisited via a shorter path later in the search.
2281 (This option cannot be used with a supertrace search.)
2282 .NH 3
2283 Liveness or Safety Verification
2284 .LP
2285 For the last, and perhaps the most critical, runtime decision:
2286 it must be decided if the system is to be checked for safety
2287 violations or for liveness violations.
2288 .P1
2289 pan -l  # search for non-progress cycles
2290 pan -a  # search for acceptance cycles
2291 .P2
2292 (In the first case, though, you must compile pan.c with -DNP as an
2293 additional directive. If you forget, the executable will remind you.)
2294 If you don't use either of the above two options, the default types of
2295 correctness properties are checked (assertion violations,
2296 completeness, race conditions, etc.).
2297 Note that the use of a
2298 .CW never
2299 claim that contains
2300 .CW accept
2301 labels requires the use of the
2302 .CW -a
2303 flag for complete verification.
2304 .LP
2305 Adding option
2306 .CW -f
2307 restricts the search for liveness properties further under
2308 a standard \f2weak fairness\f1 constraint:
2309 .P1
2310 pan -f -l       # search for weakly fair non-progress cycles
2311 pan -f -a       # search for weakly fair acceptance cycles
2312 .P2
2313 With this constraint, each process is required to appear
2314 infinitely often in the infinite trace that constitutes
2315 the violation of a liveness property (e.g., a non-progress cycle
2316 or an acceptance cycle), unless it is permanently blocked
2317 (i.e., has no executable statements after a certain point in
2318 the trace is reached).
2319 Adding the fairness constraint increases the time complexity
2320 of the verification by a factor that is linear in the number
2321 of active processes.
2322 .LP
2323 By default, the verifier will report on unreachable code in
2324 the model only when a verification run is successfully
2325 completed.
2326 This default behavior can be turned off with the runtime option
2327 .CW -n ,
2328 as in:
2329 .P1
2330 pan -n -f -a
2331 .P2
2332 (The order in which the options such as these are listed is
2333 always irrelevant.)
2334 A brief explanation of these and other runtime options can
2335 be determined by typing:
2336 .P1
2337 pan --
2338 .P2
2339 .NH 2
2340 Inspecting Error Traces
2341 .LP
2342 If the verification run reports an error,
2343 any error, \*V dumps an error trail into a file named
2344 .CW spec.trail ,
2345 where
2346 .CW spec
2347 is the name of your original \*P file.
2348 To inspect the trail, and determine the cause of the error,
2349 you must use the guided simulation option.
2350 For instance:
2351 .P1
2352 spin -t -c spec
2353 .P2
2354 gives you a summary of message exchanges in the trail, or
2355 .P1
2356 spin -t -p spec
2357 .P2
2358 gives a printout of every single step executed.
2359 Add as many extra or different options as you need to pin down the error:
2360 .P1
2361 spin -t -r -s -l -g spec
2362 .P2
2363 Make sure the file
2364 .CW spec
2365 didn't change since you generated the analyzer from it.
2366 .sp
2367 If you find non-progress cycles, add or delete progress labels
2368 and repeat the verification until you are content that you have found what
2369 you were looking for.
2370 .sp
2371 If you are not interested in the first error reported,
2372 use pan option
2373 .CW -c
2374 to report on specific others:
2375 .P1
2376 pan -c3
2377 .P2
2378 ignores the first two errors and reports on the third one that
2379 is discovered.
2380 If you just want to count all errors and not see them, use
2381 .P1
2382 pan -c0
2383 .P2
2384 .SH
2385 State Assignments
2386 .LP
2387 Internally, the verifiers produced by \*V deal with a formalization of
2388 a \*P model in terms of extended finite state machines.
2389 \*V therefore assigns state numbers to all statements in the model.
2390 The state numbers are listed in all the relevant output to make it
2391 completely unambiguous (source line references unfortunately do not
2392 have that property).
2393 To confirm the precise state assignments, there is a runtime option
2394 to the analyzer generated:
2395 .P1
2396 pan -d  # print state machines
2397 .P2
2398 which will print out a table with all state assignments for each
2399 .CW proctype
2400 in the model.
2401 .NH 2
2402 Exploiting Partial Order Reductions
2403 .LP
2404 The search algorithm used by \*V is optimized
2405 according to the rules of a partial order theory explained in [HoPe94].
2406 The effect of the reduction, however, can be increased considerably if the verifier
2407 has extra information about the access of processes to global
2408 message channels.
2409 For this purpose, there are two keywords in the language that
2410 allow one to assert that specific channels are used exclusively
2411 by specific processes.
2412 For example, the assertions
2413 .P1
2414 xr q1;
2415 xs q2;
2416 .P2
2417 claim that the process that executes them is the \f2only\f1 process
2418 that will receive messages from channel
2419 .CW q1 ,
2420 and the \f2only\f1 process that will send messages to channel
2421 .CW q2 .
2422 .LP
2423 If an exclusive usage assertion turns out to be invalid, the
2424 verifier will be able to detect this, and report it as a violation
2425 of an implicit correctness requirement.
2426 .LP
2427 Every read or write access to a message channel can introduce
2428 new dependencies that may diminish the maximum effect of the
2429 partial order reduction strategies.
2430 If, for instance, a process uses the
2431 .CW len
2432 function to check the number of messages stored in a channel,
2433 this counts as a read access, which can in some cases invalidate
2434 an exclusive access pattern that might otherwise exist.
2435 There are two special functions that can be used to poll the
2436 size of a channel in a safe way that is compatible with the
2437 reduction strategy.
2438 .LP
2439 The expression
2440 .CW nfull(qname)
2441 returns true if channel
2442 .CW qname
2443 is not full, and
2444 .CW nempty(qname)
2445 returns true if channel
2446 .CW qname
2447 contains at least one message.
2448 Note that the parser will not recognize the free form expressions
2449 .CW !full(qname)
2450 and
2451 .CW !empty(qname)
2452 as equally safe, and it will forbid constructions such as
2453 .CW !nfull(qname)
2454 or
2455 .CW !nempty(qname) .
2456 More detail on this aspect of the reduction algorithms can be
2457 found in [HoPe94].
2458 .SH
2459 Keywords
2460 .LP
2461 For reference, the following table contains all the keywords,
2462 predefined functions, predefined variables, and
2463 special label-prefixes of the language \*P,
2464 and refers to the section of this paper in
2465 which they were discussed.
2466 .KS
2467 .TS
2468 center;
2469 l l l l.
2470 _last (1.4)     _pid (1.1.1)    accept (1.3.2)  active (1.1.1)
2471 assert (1.3.1)  atomic (1.2.1)  bit (1.1.2)     bool (1.1.2)
2472 break (1.2.4)   byte (1.1.2)    chan (1.1.3)    d_step (1.2.2)
2473 do (1.2.4)      else (1.2.4)    empty (1.1.3)   enabled (1.4)
2474 end (1.3.2)     fi (1.2.3)      full (1.1.3)    goto (1.2.2)
2475 hidden (not discussed)  if (1.2.3)      init (1.1.1)    int (1.1.2)
2476 len (1.1.3)     mtype (1.1.3)   nempty (2.6)    never (1.3.3)
2477 nfull (2.6)     od (1.2.4)      of (1.1.3)      pc_value (1.4)
2478 printf (1.1.1)  proctype (1.1.1)        progress (1.3.2)        run (1.1.1)
2479 short (1.1.2)   skip (1.2)      timeout (1.2.4) typedef (1.1.2)
2480 unless (1.2.5)  xr (2.6)        xs (2.6)
2481 .TE
2482 .KE
2483 .SH
2484 References
2485 .LP
2486 [Ho91]
2487 G.J. Holzmann,
2488 .I
2489 Design and Validation of Computer Protocols,
2490 .R
2491 Prentice Hall, 1991.
2492 .LP
2493 [Ho93]
2494 G.J. Holzmann, ``Tutorial: Design and Validation of Protocols,''
2495 .I
2496 Computer Networks and ISDN Systems,
2497 .R
2498 1993, Vol. 25, No. 9, pp. 981-1017.
2499 .LP
2500 [HoPe94]
2501 G.J. Holzmann and D.A. Peled, ``An improvement in
2502 formal verification,''
2503 .I
2504 Proc. 7th Int. Conf. on Formal Description Techniques,
2505 .R
2506 FORTE94, Berne, Switzerland. October 1994.
2507 .LP
2508 [Ho95]
2509 G.J. Holzmann, ``An Analysis of Bitstate Hashing,''
2510 technical report 2/95, available from author.
2511 .LP
2512 [HS99]
2513 G.J. Holzmann, ``Software model checking: extracting
2514 verification models from source code,''
2515 .I
2516 Proc. Formal Methods in Software Engineering and Distributed
2517 Systems,
2518 .R
2519 PSTV/FORTE99, Beijng, China, Oct. 1999, Kluwer,pp. 481-497.