2519 lines · 65.9 KB · Text
RawDownload
.HTML "Using SPIN.\" runoff as:.\" eqn file | tbl | troff -ms.\".ds P \\s-1PROMELA\\s0.ds V \\s-1SPIN\\s0.ds C pcc.\" .tr -\(hy.EQdelim $#.EN.TLUsing \*V.AUGerard J. Holzmanngerard@plan9.bell-labs.com.AB\*V can be used for proving or disproving logical propertiesof concurrent systems.To render the proofs, a concurrent system is firstmodeled in a formal specification language called \*P.The language allows one to specify the behaviorsof asynchronously executingprocesses that may interact through synchronousor asynchronous message passing, or through directaccess to shared variables..LPSystem models specified in this way can be verifiedfor both safety and liveness properties. The specificationof general properties in linear time temporal logic isalso supported..LPThe first part of this manualdiscusses the basic features of the specification language \*P.The second part describes the verifier \*V..AE.NH 1The Language \*P.LP\*P is short for Protocol Meta Language [Ho91].\*P is a \f2modeling\f1 language, not a programming language.A formal model differs in two essential ways from an implementation.First, a model is meant to be an abstraction of a designthat contains only those aspects of the design that aredirectly relevant to the properties one is interested in proving.Second, a formal model must contain things that are typically not partof an implementation, such as worst-case assumptions aboutthe behavior of the environment that may interact with thesystem being studied, and a formal statement of relevant correctnessproperties. It is possible to mechanically extract abstract modelsfrom implementation level code, as discussed, for instance in [HS99]..LPVerification with \*V is often performed in a series of steps,with the construction of increasingly detailed models.Each model can be verified under different types ofassumptions about the environment and for differenttypes of correctness properties.If a property is not valid for the given assumptions aboutsystem behavior, the verifier can produce a counter-examplethat demonstrates how the property may be violated.If a property is valid, it may be possible to simplify themodel based on that fact, and prove still other properties..LPSection 1.1 covers the basic building blocks of the language.Section 1.2 introduces the control flow structures.Section 1.3 explains how correctness properties are specified.Section 1.4 concludes the first part with a discussion ofspecial predefined variables and functions that can be used toexpress some correctness properties..LPUp to date manual pages for \*V can always be found online at:.CWhttp://cm.bell-labs.com/cm/cs/what/spin/Man/.R.NH 2Basics.LPA \*P model can contain three different types of objects:.IP.RS\(bu Processes (section 1.1.1),.br\(bu Variables (section 1.1.2),.br\(bu Message channels (section 1.1.3)..RE.LPAll processes are global objects.For obvious reasons, a \*P model must contain at least oneprocess to be meaningful.Since \*V is specifically meant to prove properties ofconcurrent systems, a model typically contains more thanone process..LPMessage channels and variables, the two basic types of data objects,can be declared with either a global scope or a local scope.A data object with global scope can be referred to by all processes.A data object with a local scope can be referred to by just asingle process: the process that declares and instantiates the object.As usual, all objects must be declared in the specificationbefore they are referenced..NH 3Processes.LPHere is a simple process that does nothing except printa line of text:.P1init {	printf("it works\en")}.P2There are a few things to note..CW Initis a predefined keyword from the language.It can be used to declare and instantiatea single initial process in the model.(It is comparable to the.CW mainprocedure of a C program.)The.CW initprocess does not take arguments, but it canstart up (instantiate) other processes that do..CW Printfis one of a few built-in procedures in the language.It behaves the same as the C version.Note, finally, that no semicolon follows the single.CW printfstatement in the above example.In \*P, semicolons are used as statement separators,not statement terminators.  (The \*V parser, however, islenient on this issue.).LPAny process can start new processes by using anotherbuilt-in procedure called.CW run .For example,.P1proctype you_run(byte x){	printf("my x is: %d\en", x)}.P2.P1init {	run you_run(1);	run you_run(2)}.P2The word.CW proctypeis again a keyword that introduces the declarationof a new type of process.In this case, we have named that type.CW you_runand declared that all instantiations of processesof this type will take one argument:  a data objectof type.CW byte ,that can be referred to within this process by the name.CW x .Instances of a.CW proctypecan be created with the predefined procedure.CW run ,as shown in the example.When the.CW runstatement completes, a copy of the processhas been started, and all its arguments have beeninitialized with the arguments provided.The process may, but need not, have performedany statement executions at this point.It is now part of the concurrent system,and its execution can be interleaved arbitrarily withthose of the other, already executing processes.(More about the semantics of execution follows shortly.).LPIn many cases, we are only interested in creating asingle instance of each process type that is declared,and the processes require no arguments.We can define this by prefixing the keyword.CW proctypefrom the process declaration with another keyword:.CW active .Instances of all active proctypes are created when thesystem itself is initialized.We could, for instance, have avoided the use of.CW initby declaring the corresponding process in the last exampleas follows:.P1active proctype main() {	run you_run(1);	run you_run(2)}.P2Note that there are no parameters to instantiate in thiscase.  Had they been declared, they would default to azero value, just like all other data objectsthat are not explicitly instantiated..LPMultiple copies of a process type can also be created inthis way.  For example:.P1active [4] proctype try_me() {	printf("hi, i am process %d\en", _pid)}.P2creates four processes.A predefined variable.CW _pidis assigned to each running process, and holdsits unique process instantiation number.In some cases, this number is needed when a referencehas to be made to a specific process..LPSummarizing:  process behavior is declared in.CW proctypedefinitions, and it is instantiated with either.CW runstatements or with the prefix.CW active .Within a proctype declaration, statements are separated(not terminated) by semicolons.As we shall see in examples that follow, instead of thesemicolon, one can also use the alternative separator.CW "->"(arrow), wherever that may help to clarify the structureof a \*P model..SHSemantics of Execution.LPIn \*P there is no difference between a condition orexpression and a statement.Fundamental to the semantics of the language is thenotion of the \f2executability\f1 of statements.Statements are either executable or blocked.Executability is the basic means of enforcingsynchronization between the processes in a distributed system.A process can wait for an event to happen by waitingfor a statement to become executable.For instance, instead of writing a busy wait loop:.P1while (a != b)	/* not valid Promela syntax */	skip;	/* wait for a==b */\&....P2we achieve the same effect in \*P with the statement.P1(a == b);\&....P2Often we indicate that the continuation of an executionis conditional on the truth of some expression by usingthe alternate statement separator:.P1(a == b) -> \&....P2Assignments and.CW printfstatements are always executable in \*P.A condition, however, can only be executed (passed) when it holds.If the condition does not hold, execution blocks until it does.There are similar rules for determining the executabilityof all other primitive and compound statements in thelanguage.The semantics of each statement is defined in terms ofrules for executability and effect.The rules for executability set a precondition on the stateof the system in which a statement can be executed.The effect defines how a statement will alter asystem state when executed..LP\*P assumes that all individual statements are executedatomically: that is, they model the smallest meaningful entitiesof execution in the system being studied.This means that \*P defines the standard asynchronous interleavingmodel of execution, where a supposed scheduler is free ateach point in the execution to select any one of the processesto proceed by executing a single primitive statement.Synchronization constraints can be used to influence theinterleaving patterns.  It is the purpose of a concurrent system'sdesign to constrain those patterns in such a way that nocorrectness requirements can be violated, and all servicerequirements are met.  It is the purpose of the verifiereither to find counter-examples to a designer's claim that thisgoal has been met, or to demonstrate that the claim is indeed valid..NH 3Variables.LPThe table summarizes the five basic data types used in \*P..CW Bitand.CW boolare synonyms for a single bit of information.The first three types can store only unsigned quantities.The last two can hold either positive or negative values.The precise value ranges of variables of types.CW shortand.CW intis implementation dependent, and correspondsto those of the same types in C programsthat are compiled for the same hardware.The values given in the table are most common..KS.TScenter;l llw(10) lw(12).=\f3Type	Range\f1_bit   	0..1bool   	0..1byte   	0..255short	   $-2 sup 15# .. $2 sup 15 -1#int	   $-2 sup 31# .. $2 sup 31 -1#_.TE.KE.LPThe following example program declares a array oftwo elements of type.CW booland a scalar variable.CW turnof the same type.Note that the example relies on the fact that.CW _pidis either 0 or 1 here..MT _sec5critical.P1/* * Peterson's algorithm for enforcing * mutual exclusion between two processes * competing for access to a critical section */bool turn, want[2]; active [2] proctype user(){again:	want[_pid] = 1; turn = _pid; 	/* wait until this condition holds: */	(want[1 - _pid] == 0 || turn == 1 - _pid); 	/* enter */critical:	skip;	/* leave */ 	want[_pid] = 0;	goto again}.P2In the above case, all variables are initialized to zero.The general syntax for declaring and instantiating avariable, respectively for scalar and array variables, is:.P1type name = expression;type name[constant] = expression.P2In the latter case, all elements of the array are initializedto the value of the expression.A missing initializer fields defaults to the value zero.As usual, multiple variables of the same type can be groupedbehind a single type name, as in:.P1byte a, b[3], c = 4.P2In this example, the variable.CW cis initialized to the value 4; variable.CW aand the elements of array.CW bare all initialized to zero..LPVariables can also be declared as structures.For example:.P1typedef Field {        short f = 3;        byte  g}; typedef Msg {        byte a[3];        int fld1;        Field fld2;        chan p[3];        bit b}; Msg foo;.P2introduces two user-defined data types, the first named.CW Fieldand the second named.CW Msg .A single variable named.CW fooof type.CW Msgis declared.All fields of.CW foothat are not explicitly initialized (in the example, all fields except.CW foo.fld2.f )are initialized to zero.References to the elements of a structure are written as:.P1foo.a[2] = foo.fld2.f + 12.P2A variable of a user-defined type can be passed as a singleargument to a new process in.CW runstatements.For instance,.P1proctype me(Msg z) {	z.a[2] = 12}init {	Msg foo;	run me(foo)}.P2.LPNote that even though \*P supports only one-dimensional arrays,a two-dimensional array can be created indirectly with user-definedstructures, for instance as follows:.P1typedef Array {	byte el[4]}; Array a[4];.P2This creates a data structure of 16 elements that can bereferenced, for instance, as.CW a[i].el[j] ..LPAs in C, the indices of an array of.CW Nelements range from 0 to.CW N-1 ..SHExpressions.LPExpressions must be side-effect free in \*P.Specifically, this means that an expression cannotcontain assignments, or send and receive operations (see section 1.1.3)..P1c = c + 1; c = c - 1.P2and.P1c++; c--.P2are assignments in \*P, with the same effects.But, unlike in C,.P1b = c++.P2is not a valid assignment, because the right-hand sideoperand is not a valid expression in \*P (it is not side-effect free)..LPIt is also possible to write a side-effect free conditionalexpression, with the following syntax:.P1(expr1 -> expr2 : expr3).P2The parentheses around the conditional expression are required toavoid misinterpretation of the arrow.The example expression has the value of \f(CWexpr2\f1 when \f(CWexpr1\f1evaluates to a non-zero value, and the value of \f(CWexpr3\f1 otherwise..LPIn assignments like.P1variable = expression.P2the values of all operands used inside the expression are first cast tosigned integers before the operands are applied.After the evaluation of the expression completes, the value producedis cast to the type of the target variable before the assignment takes place..NH 3Message Channels.LPMessage channels are used to model the transfer of databetween processes.They are declared either locally or globally,for instance as follows:.P1chan qname = [16] of { short, byte }.P2The keyword.CW chan

Lines 1–500 of 2519.