Hello World CS477 Formal Software Development Methods 11 SC, UIUC egunter@illinois.edu http://courses.engr.illinois.edu/cs477 inners April 3, 014 /* A "Hello World" Promela model for SPIN. */ active Hello() { printf("hello process, my pid is: %d\n", pid); init { int lastpid; printf("init process, my pid is: %d\n", pid); lastpid = run Hello(); printf("last pid was: %d\n", lastpid); inners April 3, 014 1 Hello World, Sample Execution Hello Processes bash-3.$ spin hello.pml init process, my pid is: 1 Hello process, my pid is: 0 Hello process, my pid is: last pid was: 3 processes created bash-3.$ spin hello.pml Hello process, my pid is: 0 init process, my pid is: 1 last pid was: Hello process, my pid is: 3 processes created Hello() print "Hello" init() print "init" run Hello() 3 Hello() print "last" print "Hello" inners April 3, 014 3 Hello Processes Interleavings Interleaving Semantics Hello() init() print "init" print "Hello" run Hello() 3 3 Hello() print "last" print "Hello" Promela processes execute concurrently. Non-deterministic scheduling of the processes. Processes are interleaved Only one process can execute a statement at each point in time. Exception: rendez-vous communication. All statements are Each statement is executed without interleaving it parts with other processes. Each process may have several different possible actions enabled at each point of execution. Only one choice is made, non-deterministically (ranmly). inners April 3, 014 5
eo C. Ruys - SPIN 13 September 00 Variables and Types () 13 September 0 Variables should be declared. Variables can be given a value by: assignment argument passing message passing (see communication) Variables can be used in expressions. Most arithmetic, relational, and logical operators of C/Java are supported, including bitshift operators. bb=1; ii=; short s=-1; typedef Foo { ; Foo f; f.bb = 0; f.ii = -; assignment = declaration + initialisation equal test == ii*s+7 == 3; printf( value: %d, s*s); Variables should be declared. Variables can be given a value by: assignment argument passing message passing (see communication) Variables can be used in expressions. o C. Ruys - SPIN 13 September 00 1 Most arithmetic, relational, and logical operators of C/Java are supported, including bitshift operators. Statements () Variables and Types () inners April 3, 014 7 The skip statement is always executable. es nothing, only changes process process counter Statements (1) A run statement is only executable if a new process can be created (remember: the number of processes is bounded). The body of a process consists of a sequence of statements. A printf statement A statement is always is either executable (but is not executable/blocked evaluated during verification, of course). depends on the global executable: the statement can int x; state of the system. be executed Aap() immediately. blocked: { the statement cannot Executable be executed. if Noot can int y=1; skip; run Noot(); x=; An assignment is always executable. be created Can only become executable An expression x> && y==1; is also a statement; if a some it other is executable process if it evaluates skip; to non-zero. makes x greater than. < 3 always executable 3 x < 7 only executable if value of x is smaller 7 3 + x executable if x is not equal to 3 inners April 3, 014 9 bb=1; ii=; short s=-1; typedef Foo { ; Foo f; f.bb = 0; f.ii = -; assignment = declaration + initialisation equal test == 13 September 0 ii*s+7 == 3; printf( value: %d, s*s); 113 September 0 Statements are separated by a Xspin in a nutshell semi-colon: ;. Xspin allows the user to edit Promela models (+ syntax check) Statements () simulate Promela models ranm The skip statement is always executable. interactive es guided nothing, only changes process process counter Statements with (1) dialog boxes to set A run verify statement Promelais models only executable if a new process can be created exhaustive (remember: the number of processes is bounded). The body bitstate of hashing a process mode consists of a sequence of statements. A printf statement A statement is always is either executable executable/blocked (but is not additional features evaluated during verification, of course). depends on the global executable: Xspin suggest the abstractions statement to can a Promela model (slicing) int x; state of the system. be Xspin executed can draw immediately. automata for each process Aap() LTL property manager blocked: { the statement cannot Executable be executed. if Noot can int Helpy=1; system (with verification/simulation guidelines) be created An assignment skip; is always executable. Statements are separated by a semi-colon: ;. various options and directives to tune the verification process run Noot(); 7 x=; Can only become executable An expression x> && y==1; is also a statement; if a some it other is executable process if it evaluates skip; to non-zero. makes x greater than. < 3 always executable x Thursday < 7 11-Apr-00 only executable Theo C. Ruys - SPIN if value of x is smaller 7 3 Elsa 3 L+ Gunter x CS477 executable Formal Software if Development x is not Methods equal to 3 IN 00 Workshop, Grenoble, 11-13 April 00 11 Statements (3) WRONG! Mutual Exclusion (1) assert(<expr>); The assert-statement is always executable. If <expr> evaluates to zero, SPIN will exit with an error, as the <expr> has been violated. The assert-statement is often used within Promela models, to check whether certain properties are valid in a state. monitor() { assert(n <= 3); receiver() { toreceiver? msg; assert(msg!= ERROR); bit flag; /* signal entering/leaving the section */ byte mutex; /* # procs in the critical section. */ P(bit i) Statements { (3) flag!= 1; models: flag = 1; assert(<expr>); while (flag == 1) /* wait */; The printf("msc: assert-statement P(%d) has is entered always section.\n", executable. i); If <expr> evaluates to zero, SPIN will exit with an error, as flag = 0; the <expr> has been violated. Problem: assertion violation! The assert-statement is often Bothused processes within can Promela pass the models, monitor() { assert(mutex to check whether!= ); certain properties flag!= are 1 at valid the same in a state. time, i.e. before flag is set to 1. monitor() { init { assert(n <= 3); { run P(0); run P(1); run monitor(); receiver() { starts two instances of process P 4 Thursday toreceiver 11-Apr-00? msg; 8 inners assert(msg April 3, 014!= 11 ERROR); Elsa L Gunter IN 00 Workshop, Grenoble, 11-13 April 00 SPIN 00 Workshop, 1 Grenoble, 11-13 April 00 4
:: Both processes can pass execute x = 1 and y = 1 at the same time, and will then be waiting for each other. 13 September 0 9 o C. Ruys - SPIN 13 September 00 Mutual Exclusion (4) Bakery Mutual Exclusion () bit x, y; /* signal entering/leaving the section */ byte mutex; /* # of procs in the critical section. */ active A() { x = 1; Process A waits for y == 0; process B to end. x = 0; active B() { y = 1; x == 0; y = 0; active monitor() { assert(mutex!= ); Problem: invalid-end-state! Both processes can pass execute x = 1 and y = 1 at the same time, and will then be waiting for each other. 9 WRONG! o C. Ruys - SPIN 13 September 00 byte turn[]; /* who s turn is it? */ byte mutex; /* # procs in critical section */ Dekker [196] Mutual Exclusion (3) P(bit i) { Problem (in Promela/SPIN): turn[i] will overrun after 55. bit x, y; /* signal entering/leaving the section */ :: turn[i] = 1; byte mutex; /* # of procs in the critical section. */ turn[i] = turn[1-i] + 1; byte turn; /* who's turn is it? */ (turn[1-i] == 0) (turn[i] < turn[1-i]); active A() { x = 1; turn turn[i] = B_TURN; = 0; od y == 0 active B() { y = 1; turn = A_TURN; More x == mutual 0 exclusion algorithms (turn == A_TURN); in (turn (good-old) == B_TURN); [Ben-Ari 1990]. monitor() Can be generalised { assert(mutex!= ); x = 0; init { y = 0; to {run a single P(0); process. run P(1); run monitor() active monitor() { Theo C. Ruys - SPIN assert(mutex!= ); 3113 September First software-only solution to the mutex problem (for two processes). 30 if-statement () inners April 3, 014 13 if Bakery :: (n %!= 0) -> n=1 else inspired by: SPIN 00 Workshop, :: (n Grenoble, >= 0) 11-13 -> n=n- April 00 Mutual Exclusion (4) if-statement (1) Dijkstra s guarded :: (n % 3 == 0) -> n=3 command language :: else -> skip byte turn[]; /* who s turn is it? */ fi if byte mutex; /* # procs in critical section */ Dekker [196] Mutual Exclusion (3) P(bit i) { Problem (in Promela/SPIN): give n:: a ranm value non-deterministic branching turn[i] will overrun after 55. :: choice n -> stat n.1 ; stat n. ; stat n.3 ; bit :: turn[i] x, y; = /* 1; signal entering/leaving the section */ if fi; byte mutex; /* # of procs in the critical section. */ :: skip -> n=0 turn[i] = turn[1-i] + 1; byte turn; /* who's turn is it? */ :: skip -> n=1 (turn[1-i] == 0) (turn[i] < turn[1-i]); :: If skip there -> is at n= least one choice active A() { i (guard) executable, the ifstatement is executable and SPIN non-deterministically active B() { :: skip -> n=3 x = 1; y = 1; fi turn turn[i] = B_TURN; = 0; turn = A_TURN; chooses one of the executable choices. od y == 0 More x == mutual 0 exclusion algorithms skips are redundant, because assignments If no choice i is executable, the if-statement is blocked. (turn == A_TURN); in (turn (good-old) == B_TURN); [Ben-Ari 1990]. are themselves always executable The Thursday operator 11-Apr-00 -> is equivalent Theo C. Ruys to - SPIN ;. By convention, it is used 33 monitor() Can be generalised { assert(mutex!= ); within if-statements to separate the guards from the x = 0; init { y = 0; to {run a single P(0); process. run P(1); run monitor() statements that follow the guards. active monitor() { o C. Ruys - SPIN assert(mutex!= ); 3113 September 00 3 inners April 3, 014 15 CS477 Formal Software First Development software-only Methods solution to the mutex problem (for two processes). 30 if-statement () if :: (n %!= 0) -> n=1 else inspired by: IN 00 Workshop, :: (n Grenoble, >= 0) 11-13 -> n=n- April 00 15 if-statement (1) Dijkstra s guarded :: (n % 3 == 0) -> n=3 command language :: else -> skip fi if give n:: a ranm value non-deterministic branching :: choice n -> stat n.1 ; stat n. ; stat n.3 ; if fi; :: skip -> n=0 :: skip -> n=1 :: If skip there -> is at n= least one choice i (guard) executable, the if- is executable and SPIN non-deterministically :: skip -> n=3 fistatement chooses one of the executable choices. skips are redundant, because assignments If no choice are i themselves is executable, always the executable if-statement is blocked. The Thursday operator 11-Apr-00 -> is equivalent Theo C. Ruys to - SPIN ;. By convention, it is used 33 within if-statements to separate the guards from the statements that follow the guards. -statement (1) :: :: choice n -> stat n.1 ; stat n. ; stat n.3 ; With respect to the choices, a -statement behaves in the same way as an if-statement. However, instead of ending the statement at the end of the choosen list of statements, a -statement repeats the choice selection. The (always executable) break statement exits a -loop statement and transfers control to the end of the loop. 34 inners April 3, 014 17 3 IN 00 Workshop, Grenoble, 11-13 April 00 16 -statement (1)
! Sending - putting a message into a channel 13 September o C. Ruys - SPIN 13 September 00 -statement () if- and -statements Example modelling a traffic light are ordinary Promela Communication statements; so they can -statement () be nested. mtype = { RED, YELLOW, GREEN ; if- and -statements Major models of communication mtype (message type) models enumerations in Promela Example modelling a traffic light are ordinary Promela 1 Shared variables statements; so they can active one writes, many read TrafficLight() later { be nested. mtype = { RED, YELLOW, GREEN ; Point-to-Point byte state synchronous = GREEN; message passing one sends, one other receives at the same time mtype (message type) models enumerations in Promela send blocks until receieve can happen :: (state == GREEN) -> state = YELLOW; 3 Point-to-Point asynchronous message passing active TrafficLight() { :: (state == YELLOW) -> state = RED; one sends, one other receives some time later byte state = GREEN; :: (state == RED) -> state = GREEN; send never blocks 4 Point-to-Point buffered message passing :: (state == GREEN) -> state = YELLOW; When buffer not full behaves Note: like this asynchronous -loop es not contain :: (state == YELLOW) -> state = RED; When buffer full, two variations: any non-deterministic block or drop choice. message :: (state == RED) -> state = GREEN; Thursday send never 11-Apr-00 blocks 5 Synchronous broadcast 3513 September 0 Note: this -loop es not contain any non-deterministic choice. one sends, many receive synchronously First variation: send never blocks process may receive if ready to ready Second variation: send blocks until all possible recipients ready to 35 receive Communication () inners April 3, 014 19 Communication in SPIN Communication (1) With more or less complexity sr each can implement the others Sender Receiver Spin supports 1 and 4 (blocks send when buffer full), but with rs bounded buffers Buffer size = 0 = synchronous communication Large buffer size MSG approximates asynchronous communication sr!msg sr?msg ACK rs!ack Communication between processes is via channels: message passing Communication (1) rendez-vous synchronisation (handshake) sr also called: queue or buffer Sender Receiver chan <name> = [<dim>] of {<t rs 1 >,<t >, <t n >; Both are defined as channels: name of type of the elements that will be the channel transmitted over the channel sr!msg MSG number of elements in the channel dim==0 is special case: rendez-vous sr?msg chan c = [1] of {bit; chan tor = [] of {mtype, bit; ACK rs!ack chan line[] = [1] of {mtype, Record; array of channels rs?ack 37! is sending? is receiving rs?ack eo C. Ruys - SPIN 13 September 00! is sending? is receiving 36 inners April 3, 014 1 36 Communication () Both are defined as channels: chan <name> = [<dim>] of {<t 1 >,<t >, <t n >; name of the channel type of the elements that will be transmitted over the channel number of elements in the channel dim==0 is special case: rendez-vous 37 Communication between processes is via channels: channel = FIFO-buffer (for dim>0) IN 00 Workshop, message Grenoble, passing 11-13 April 00 18 rendez-vous synchronisation (handshake) also called: queue or buffer chan c = [1] of {bit; chan tor = [] of {mtype, bit; chan line[] = [1] of {mtype, Record; array of channels Communication (3)! Sending - putting a message into a channel ch! <expr 1 >, <expr >, <expr n >; The values of <expr i > should correspond with the types of the channel declaration. A send-statement is executable if the channel is not full.? Receiving - getting a message out of a channel <var> + ch? <var 1 >, <var >, <var n >; message passing <const> If the channel is not empty, the message is fetched from the channel can be and the individual parts of the message are stored into the <var i >s. mixed ch? <const 1 >, <const >, <const n >; message testing If the channel is not empty and the message at the front of the channel evaluates to the individual <const i >, the statement is executable and the message is removed from the channel. 38 inners April 3, 014 3 Communication (3) channel = FIFO-buffer (for dim>0)
Q wants to ch? 1, x Then after the communication, x will have the value 10. 39 eo C. Ruys - SPIN 13 September 00 Communication (4) Alternating Bit Protocol (1) Rendez-vous communication <dim> == 0 The number of elements in the channel is now zero. If send ch! is enabled and if there is a corresponding receive ch? that can be executed simultaneously and the constants match, then both statements are enabled. Both statements will handshake and together take the transition. 39 4013 September 0 inners April 3, 014 5 can be used to group statements into an sequence; Alternating Bit Protocol () all statements are executed in a single step mtype {MSG, (no interleaving ACK; with channel statements of other Receiver(chan processes) in, out) length of { no pure ity { stat 1 ; stat ; stat n is executable if stat 1 is executable chan tos = [] of {mtype, bit; bit recvbit; if a stat can be used to group statements into an sequence; chan tor = [] Alternating of i (with i>1) is blocked, {mtype, bit; Bit the ity token is Protocol (1) (temporarily) lost and other processes :: in? MSG(recvbit) may a step -> all statements are executed in a single step Sender(chan in, out) out! ACK(recvbit); (no interleaving with statements of other processes) od { Alternating (Hardware) solution Bit Protocol the mutual no pure ity exclusion problem: is executable if stat bit sendbit, recvbit; 1 is executable if a stat i (with i>1) is blocked, the ity token is :: out! MSG, sendbit -> (temporarily) lost and other processes may a step To every message, P(bit i) the { sender init adds a bit. {flag!= 1; flag { = 1; in? ACK, recvbit; The run Sender(toS, tor); if receiver acknowledges each message by sending run Receiver(toR, tos); the :: recvbit received == bit sendbit back. -> flag sendbit = = 0; 1-sendbit :: else Alternative notation: To fi receiver only excepts messages ch with! MSG(par1, a bit that ) it excepted to receive. ch? MSG(par1, ) 47 Alternating Bit Protocol To every message, the sender adds a bit. The receiver acknowledges each message by sending the received bit back. To receiver only excepts messages with a bit that it excepted to receive. Example: If the sender is sure that the receiver has correctly chan ch = [0] of {bit, byte; received the previous message, it sends a new eo C. Ruys - SPIN P wants to ch! 1, 3+7 13 September 00 message and it alternates the accompanying bit. Q wants to ch? 1, x Then after the communication, x will have the value 10. eo C. Ruys - SPIN 13 September 00 od { stat 1 ; stat ; stat n (Hardware) solution to the mutual exclusion problem: P(bit i) { {flag!= 1; flag = 1; flag = 0; If the sender is sure that the receiver has correctly received the previous message, it sends a new 41 4713 September message and it alternates the accompanying bit. inners April 3, 014 7 40 P1() { t1a; t1b; t1c No ity P() { ta; tb; tc init { run P1(); run P() { stat 1 ; stat ; stat n [Ruys & Brinksma 1998] IN 00 Workshop, more Grenoble, efficient 11-13 version April of 00 : no intermediate states are 0 P1 t1a ta P generated Cookie: and stored hippies problem 0 t1b (1,0) 0 ta t1a (0,1) may only contain deterministic steps t1a { ta stat 1 ; stat(,0) ; stat n tb t1c it is a run-time error if stat i (i>1) blocks. ta t1b (1,1) more efficient version of : no intermediate tb states are Germany is especially :: Rout?i(v) -> { 1 1 t1a (0,) ta Holland generated and stored t1c (,1) tc k++; tb useful to perform t1b <= 60 min? may only tb t1b (1,) e[k].ind = i; contain deterministic (3,1) steps tc t1a (0,3) intermediate computations e[k].val = v; it is a run-time error if stattb i (i>1) blocks. in a single transition i=0; v=0 ; t1c (,) tc t1b (1,3) t1c is tc especially (3,) :: Rout?i(v) -> {........ tc k++; holes useful to perform t1c (,3) e[k].ind = i; and can be used to lower the number coffee 3 3 of intermediate computations (3,3) e[k].val = v; shop states of the model in a single transition i=0; v=0 ; 5 10 0 5 Not completely correct as each process has an implicit end-transition <= pers 48 inners April 3, 014 9 49 and can be used to lower the number of CS477 Formal Software Development Methods states of the model 4 IN 00 Workshop, Grenoble, 11-13 April 00 4 48 IN 00 Workshop, Grenoble, 11-13 April 00 SPIN 00 Workshop, 1 Grenoble, P1() { 11-13 April {t1a; 00 t1b; t1c P() { ta; tb; tc init { run P1(); run P()
active Receiver() (3,3) Not completely correct as each process has an implicit end-transition eo C. Ruys - SPIN 4913 September 00 P1() { {t1a; t1b; t1c P() { ta; tb; tc init { run P1(); run P() 13 September P1() { {t1a; t1b; t1c P() { ta; tb; tc init { run P1(); (1,0) run P() (0,1) (3,) (,3) 51 Although clauses cannot (3,3) be interleaved, the intermediate states are still constructed. 50 inners April 3, 014 31 abp-1.pr IN 00 Workshop, Grenoble, 11-13 April 00 5 perfect lines P1() { {t1a; t1b; t1c P() { ta; tb; tc init { run P1(); run P() (,0) (1,1) (0,) (,1) (1,0) (1,)(0,1) If one of P1 s transitions (1,0) (0,1) (3,1) (0,3) (,0) blocks, these transitions (,)(1,1) (,0) may get executed (1,1) (1,3) (0,) (0,) (3,) (,1) (,1) (,3) (1,) (1,) (3,1) No (0,3) intermediate states will (3,1) (0,3) (3,3) (,) be constructed. (,) (1,3) (1,3) (3,) 13 September (,3) Checking for pure ity (3,3) No intermediate states will be constructed. 5113 September Alternating Bit Protocol (3) How large should MAX be such that we are sure that the ABP works correctly? timeout (1) abp-.pr only Suppose we want to check that none of the clauses Promela stealing es daemon not have (models real-time lossy features. channels) three! in our model are ever blocked (i.e. pure ity). In how Promela we know we can that only the specify protocol functional works correctly? behaviour. Most Checking protocols, however, for pure use timers ity or a timeout 1. Add a global bit variable:. Change all clauses to: abp-3.pr mechanism to resend messages or acknowledgements. Suppose model different we want messages { to check that by a none sequence of the numberclauses bit aflag; stat 1 ; timeout in assert our model that are the ever protocol blocked works (i.e. correctly pure ity). aflag=1; SPIN s how can timeout we be sure becomes that different executable messages if there are is no being stat 1. Add other a global bit variable:. Change all clauses to: transmitted? process in the system which is executable 3. Check that aflag is always 0. so, { bit timeout aflag; models a global timeout []!aflag timeout provides an escape from deadlock stat 1 ; states aflag=1; stat e.g. active process monitor { n beware of statements Theo that C. Ruys are - SPIN always stat executable 55 assert(!aflag); aflag=0; 3. Check that aflag is always 0. []!aflag eo C. Ruys - SPIN 513 September 00 stat e.g. active process monitor { n 53 inners April 3, 014 33 assert(!aflag); aflag=0; CS477 Formal Software Development Methods IN 00 Workshop, Grenoble, 11-13 April 00 6 timeout (1) 5 goto Promela es not have real-time features. goto label In Promela we can only specify functional behaviour. SPIN 00 Workshop, transfers Grenoble, execution 11-13 April to 00 label timeout () Most protocols, however, use timers or a timeout each Promela statement might be labelled mechanism to resend messages or acknowledgements. quite useful in modelling communication protocols Example to recover from message loss: timeout wait_ack: active Receiver() Timeout modelled by a channel. SPIN stimeout becomes executable if there is no if { :: B?ACK -> ab=1-ab ; goto success other process in the system which is executable :: bit ChunkTimeout?SHAKE recvbit; -> so, timeout models a global timeout if timeout provides an escape from deadlock states :: :: tor (rc <? MAX) MSG, recvbit -> rc++; -> F!(i==1),(i==n),ab,d[i]; tos! ACK, recvbit; :: timeout goto -> wait_ack tos! ACK, recvbit; beware of statements that are always executable :: (rc >= MAX) -> goto error od fi fi ; Part of model of BRP 53 Premature timeouts can be modelled by replacing the timeout by skip (which is always executable). 56 inners April 3, 014 35 One might want to limit the number of premature timeouts (see [Ruys & Langerak 1997]). 54 timeout () Example to recover from message loss:
o C. Ruys - SPIN Theo 13 September C. Ruys - 00 SPIN 13 September unless { <stats> unless { guard; <stats> Statements in <stats> are executed until the first statement (guard) in the escape sequence becomes executable. resembles exception handling in languages like Java Example: MicroProcessor() { { /* execute normal instructions */ unless { port? INTERRUPT; unless { <stats> unless { guard; <stats> Statements in <stats> are executed until the first statement (guard) in the escape sequence becomes executable. resembles exception handling in languages like Java Example: MicroProcessor() { { /* execute normal instructions */ unless { port? INTERRUPT; eo C. Ruys - SPIN 13 September 00 57 57 inners April 3, 014 37 inline poor man s procedures Promela also has its own macro-expansion feature using the inline-construct. macros cpp preprocessor inline init_array(a) { { Promela uses i=0; cpp, the Should C preprocessor be declared somewhere to preprocess Promela models. else (probably as a local variable). This is useful to define: :: i<n -> a[i] = 0; i++ constants :: else -> break All cpp commands start with a hash: #define MAX 4 i=0; #define, #ifdef, #include, etc. macros Be sure to reset temporary variables. #define RESET_ARRAY(a) \ { a[0]=0; a[1]=0; #define a[]=0; a[3]=0; conditional Promela model fragments #define LOSSY 1 59 #ifdef LOSSY Elsactive L Gunter CS477 Formal Daemon() Software Development { /* Methods steal messages */ #endif macros cpp preprocessor Promela uses cpp, the C preprocessor to preprocess Promela models. This is useful to define: constants #define MAX 4 inners April 3, 014 39 All cpp commands start with a hash: #define, #ifdef, #include, etc. macros #define RESET_ARRAY(a) \ { a[0]=0; a[1]=0; a[]=0; a[3]=0; conditional Promela model fragments #define LOSSY 1 #ifdef LOSSY active Daemon() { /* steal messages */ #endif 58 58 IN 00 Workshop, Grenoble, 11-13 April 00 SPIN 00 Workshop, 9 Grenoble, 11-13 April 00 Properties (1) M M With SPIN one may check the following type of properties: deadlocks (invalid endstates) assertions unreachable code LTL formulae liveness properties non-progress cycles (livelocks) acceptance cycles 60 IN 00 Workshop, Grenoble, 11-13 April 00 30