Introduction to SPIN Radu Iosif (iosif@cis.ksu.edu)

Post on 05-Jan-2016

223 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

Transcript

Introduction to SPIN

Radu Iosif (iosif@cis.ksu.edu)

PROMELA (PROcess MEta LAnguage) is:– a language to describe concurrent (distributed)

systems: • network protocols, telephone systems• multi-threaded (-process) programs

– similar with some structured languages (e.g. C, Pascal)

SPIN (Simple Promela INterpreter) is a tool for:– detecting logical errors in the design of systems e.g:

• deadlocks• assertions (e.g. race conditions)• temporal logic formulas (in a future lecture)

Given a PROMELA model (program), SPIN can do:

– a random simulation i.e. it interprets the program• this mode cannot be used in exhaustive verification• useful for viewing error traces

– an exhaustive analysis• considers all possible executions of the program• finds all potential errors, both deadlock and user-specified

Deadlock: – situation in which at least one process remains blocked

forever while waiting for an inexistent event to happen

User specified constraints: – assertions– temporal (never) claims

PROMELA “Hello World”

The simplest erroneous specification

init {

0;

}

init {

printf(“Hello World\n”);

}

The SPIN simulation

init { printf(“Hello World\n”);}

SPIN

0: proc - (:root:) creates proc 0 (:init:)

Hello World

1: proc 0 (:init:) line 3 "pan_in" (state 1) [printf(‘Hello World\\n')]

simulation trace

C:\> spin –p hello.prom

The SPIN analysis (1)

init { 0;} SPIN C:\> spin –a dlock.prom

pan.t pan.m pan.b pan.h pan.c

GCC

pan.exe

The SPIN analysis (2)

pan.exe dlock.prom.trail

SPIN C:\> spin –p -t dlock.prom

#processes: 1 -4: proc 0 (:init:) line 3 "pan_in" (state 1)1 processes created

error trace

OK

ERROR

The PROMELA language

Similar to C, for instance:

• all C pre-processor directives can be used

• definitions of types, variables, processes

•if,do,break,goto control flow constructs

Basic types and ranges

At most one enumeration type

bit, bool 0..1

byte 0..255

short - 2^15 - 1 .. 2^15 - 1

int -2^31 – 1 .. 2^31 - 1Warning: type ranges are OS-

dependent (just like in C)

mtype = {one, two, three};

Record types (user-defined)

• look like C structures

typedef S {

short a, b;

byte x;

};

Variables (same C syntax)

Processes (like C procedures)

• the init process (like main in C)– has no parameters

int x, y;

int z = 0;

mtype m = one;

proctype foo(int x, y; bit b){...}

Scoping rules

– variables are global if declared outside any process

– variables are local a process if declared within its proctype declaration

– local variables shadow globals with the same name

Vectors

– declared like variables:

– indexes are zero-based– scoping rules apply (there might be

global and local vectors)

int vector[32];

Expressions

– logical: ||, &&, !– arithmetic: +, -, /, %– relational: >,<,<=,>=,==,!=

– vector access: v[i]– record access: x.f– process creation: run X()

Statements (1) – are execution steps of processes – an important characteristic is

executability:

For instance:

is the (proper) way of expressing something like:

x <= 10;

while(x <= 10);

Statements (2)

• Expression statements• not executable iff expression evaluates to 0

• Assignment statements• always executable

• Skip statements• always executable• do “nothing” (only change control location)

• Print statements• always executable

Statements (3)

• Assert statements

• always executable• expression evaluates to zero => program

exits

• Statements are atomic• in a concurrent program, each statement is

executed without interleaving with other processes

assert( <expression> );

Control flow (1)• Select construct

• What does it do?• if a (random) choice is executable, continues

execution with the corresponding branch• if no choice is executable, the whole select is not

executable• if more than one choice is executable, we say the

selection is non-deterministic

if

:: <choice1> -> <stat11>; <stat12>; …

:: <choice2> -> <stat21>; <stat22>; …

fi;

Control flow (2)• Loop construct

• What does it do?• same as the selection, except that at the

end of a branch it loops back and repeats the choice selection

do

:: <choice1> -> <stat11>; <stat12>; …

:: <choice2> -> <stat21>; <stat22>; …

od;

Control flow (3) (more C syntax)

• The else choice• is executable only when no other choice

is executable

• The break statement• transfers control at the end of loop

• The goto statement• transfers control to a labeled location

Traffic light example

mtype = {red, yellow, green};

byte state = green;

init {

do

:: (state == green) -> state = yellow;

:: (state == yellow) -> state = red;

:: (state == red) -> state = green;

od

}

Concurrency• Processes can spawn other processes

using the run expression

proctype foo(int x; byte y) {…}

init {

int pid;

pid = run foo(256, 255);

/* or simply: */

run foo(256, 255);

}

Interleaving

• Premises:– two or more processes composed of atomic

statements– one processor shared between processes

• Problems:– worst-case complexity is exponential in no of

processes– improper mutex (locking) may cause race

conditions

Complexity

s11

s12

s21

s22

s12

s11

s21

s21

. . .

• how many states can be reached in this example?

• express this number as function of:

K = number of processes

N = number of states/process

Reducing complexity (1)

• if a statement inside atomic is not executable, transfer temporarily control to another process

s12

s11

s21

s21s11

s12

s21

s22

atomic

. . .

Reducing complexity (2)

• if a statement inside d_step is not executable => error (block inside d_step)

• no if, do, break, goto, run allowed inside d_step (i.e., deterministic step)

s11+s12

s21

s21s11

s12

s21

s22

d_step

. . .

Apprentice example• Good apprentice

• Bad apprentice

int counter = 0;

active[2] proctype incr() {

counter = counter + 1;

}

int counter = 0;

active[2] proctype incr() {

int tmp;

tmp = counter + 1;

counter = tmp;

}

atomic

Mutual exclusion (bad) example

proctype B() {

y = 1;

x == 0;

mutex ++;

mutex --;

y = 0;

}

proctype A() {

x = 1;

y == 0;

mutex ++;

mutex --;

x = 0;

}

proctype monitor() {

assert(mutex != 2);

}

Dekker’s mutual exclusion

proctype A() {

x = 1;

turn = Bturn;

(y == 0) || (turn == Aturn);

mutex ++;

mutex --;

x = 0;

}

proctype B() {

y = 1;

turn = Aturn;

(x == 0) || (turn == Bturn);

mutex ++;

mutex --;

y = 0;

}

proctype monitor() {

assert(mutex != 2);

}

Bakery mutual exclusion

• does verification terminate?

proctype A() {

do

:: 1 -> turnA = 1;

turnA = turnB + 1;

(turnB == 0) || (turnA < turnB);

mutex ++; mutex --;

turnA = 0;

od

}

(Some formal issues)

Formal Concurrent Systems (FCS)

• Mathematical descriptions of concurrent systems

• Important tools for reasoning about such systems

• Composed of states and transitions• Graphical representations of FCS: directed

graphs– nodes represent states, edges are transitions

FCS preliminaries

• Let A,B be two sets• A relation R is a subset of A x B

– we also write aRb for (a, b) in R

• A function F: A B is a relation such that1. for each a A there exists b in B such that aFb2. such b is unique

• Some notation:– [a b]F is a function G such that G(a) = b

and, for all x other than a, G(x) = F(x)

States

• Let P be a set of processes P = {p1, … , pn}

• Let L be a set of control locations L = {l1, …, lm}

• Let loc : P L be a control function

• Let I be a set of variables I = {x1, …, xk }

• Let V be a set of values V = {v1, v2, … }

• Let mem : I V be a memory function

• A state is a pair:S = (loc, mem)

Transitions (1)

• A condition C is a boolean expression on a subset of I

• An assignment A is a pair (x, v) from I x V also denoted by x v

• A transition is a 5-tuple:t = (p, ls, ld, C, A)

where ls and ld are elements of L called source and destination locations

Transitions (2)

• A transition t = (p, ls, ld, C, A) is executable in state s = (loc, mem) iff:– loc(p) = ls and C = true

• The result of executing transition t in state s is– s’ = ([p ld]loc, [A]mem)– also denoted by s t s’

Transition systems (TS)• A transition system is a pair TS = (S, s0, T)

– S is a set of states; s0 S is the initial state

– T is a transition relation (S x S)• A TS can be built from each FCS:

– S = {(loc, mem) | loc: P L, mem : I V}– for each two states s, s’ such that s t s’

for some transition t introduce (s, s’) in T• s1,s2, …, sn, … is an (in)finite execution

sequence of the TS iff:– s1 = s0 (initial state condition)– (si, si+1) T (successor condition)

Labeled transition systems (LTS)• LTS = (, S, s0, )

is the alphabet– S is a set of states; s0 S is the initial

state

– : S x P(S) is a transition function• Also known in compilers as finite automata• s1,a1,s2,a2, …, sn,an,sn+1, … is an

(in)finite execution sequence of the LTS iff– s1 = s0 (initial state condition)

– si+1 (si, ai) (successor condition)

Parallel product of LTSs• Given

– LTS1 = (1, S1, s01, 1), – LTS2 = (2, S2, s02, 2)

• The parallel product of LTS1 and LTS is– LTS1 || LTS2 = (, S, s0, ) where: = 1 U 2– S = S1 x S2; s0 = (s01, s02)– (s1’, s2’) ((s1, s2), a) iff either:

• a 1 and s1’ 1(s1, a) or• a 2 and s2’ 2(s2, a)

Synchronous product of LTSs• Given

– LTS1 = (1, S1, s01, 1), – LTS2 = (2, S2, s02, 2)

• The synchronous product of LTS1 and LTS2 is– LTS1 x LTS2 = (, S, s0, ) where: = 1 2– S = S1 x S2; s0 = (s01, s02)– (s1’, s2’) ((s1, s2), a) iff both hold:

• s1’ 1(s1, a) and• s2’ 2(s2, a)

Execution traces, words and languages (1)• Let F S be a set of states• We say LTS = (, S, s0, , F) accepts a

word w = a1, a2, … over iff there exists an execution sequence of LTS:– = s1, a1, s2, a2, …

such that there exists some state from F that repeats infinitely often in

• L(LTS) is the set of all words accepted by LTS

• Also known as the language of LTS

Execution traces, words and languages (2)• Given

–LTS1 = (1, S1, s01, 1, S1), –LTS2 = (2, S2, s02, 2, S2)

– L(LTS1 || LTS2) is the set of all interleavings between words generated by LTS1 and LTS2

– L(LTS1 x LTS2) = L(LTS1) L(LTS2)

– we say an LTS is empty iff L(LTS) =

(Some formal issues)END

Communication (1)

1. Message passing2. Rendez-vous synchronization

• Both methods rely on channels:

– if dim is 0 then q is a rendez-vous port– otherwise q is an asynchronous

channel

chan q = [<dim>] of {<type>};

chan q; /* just declaration */

Communication (2)

• Send statement

– for rendez-vous channels is executable iff another process is ready to receive at the same time both processes are involved in a rendez-vous

– for asynchronous queues is executable iff the queue is not full

q ! <expr>;

Communication (3)

• Receive statement

– for rendez-vous channels is executable iff another process is ready to send at the same time both processes are involved in a rendez-vous

– for asynchronous queues is executable iff the queue is not empty

q ? <var>;

q ? _;

Communication (4)

• Channel test statement

– same as receive for rendez-vous channels

– for asynchronous queues is executable iff the first value in the queue matches the result of expr

q ? <expr>;

Inter-locking example

chan lock = [1] of bit;

proctype foo(chan q) {

q ? 1;

/* critical section */

q ! 1;

}

init {

lock ! 1;

run foo(lock);

run foo(lock);

}

Recursion example

proctype fact(int n; chan r) {

int tmp;

chan c = [1] of {bit};

if

:: n == 0 -> r ! 1;

:: else ->

run fact(n - 1, c);

c ? tmp; r ! n*tmp;

fi

}

More advanced issues

Fair transition systems (FTS)• FTS = (, S, s0, , J, C)

– a statement labeled by lab is enabled in a state s iff (s, lab)

– J is the justice set; • any statement labeled by lab J cannot be

continuously enabled but not executed beyond a certain point

– C is the compassion set; • any statement labeled by lab J cannot be

enabled infinitely many times but executed only a finite number of times

Weak fairness (1)

proctype foo(){

do

l0: :: (x == 0) ->

l1: y = y + 1;

:: else ->

l2: break;

od

}

proctype bar(){

m0: x = 1;

m1:

}

Pnueli’s ANY-Y

Weak fairness (2)• An execution trace of ANY-Y:

({(foo,l0), (bar,m0)}, {(x,0), (y,0)}), l0, ({(foo,l1), (bar,m0)}, {(x,0), (y,0)}), l1,

({(foo,l0), (bar,m0)}, {(x,0), (y,1)}), l0, ({(foo,l1), (bar,m0)}, {(x,0), (y,1)}), l1,

({(foo,l0), (bar,m0)}, {(x,0), (y,2)}), l0, ({(foo,l1), (bar,m0)}, {(x,0), (y,2)}), l1,

• The execution is not acceptable because bar never gets a chance to execute the program doesn’t terminate

• Solution: include m0 into the justice set don’t care about executions in which m0 is continuously enabled but never taken

Strong fairness (1)

proctype foo() {

do

l0: :: lock ? 1;

l1: /* critical */

l2: lock ! 1;

od

}

proctype bar() {

do

m0: :: lock ? 1;

m1: /* critical */

m2: lock ! 1;

od

}Pnueli’s MUX-SEM

Strong fairness (2)• An execution trace of MUX-SEM:

({(foo,l0), (bar,m0)}, {(lock, [1])}), l0, ({(foo,l1), (bar,m0)}, {(lock, [])}), l1,

({(foo,l2), (bar,m0)}, {(lock, [])}), l2, ({(foo,l0), (bar,m0)}, {(lock, [1])}), l0,

({(foo,l1), (bar,m0)}, {(lock, [])}), l1, ({(foo,l2), (bar,m0)}, {(lock, [])}), l2,

({(foo,l0), (bar,m0)}, {(lock, [1])}), …

• Not acceptable because bar never gets a chance to enter the critical section, even though he has infinitely often the chance to add m0 to the compassion set

• NOTE: this is not a justice violation because m0 is not continuously enabled, only from time to time

End labels• An endstate in PROMELA is a state

with no successors• Endstates can be labeled as valid by

introducing labels that start with end– end0,endsome, …

• At the end of each process there is a default valid endstate

• A deadlock is a state with no successors in which at least one process is not in a valid enstate

Timeouts

• A timeout is similar to else or break but:– becomes executable only when no

other transition from any other process is executable

• Provides an escape from deadlock states

Progress labels (a.k.o. strong fairness)• Marked states that must be executed

in order for the program to make progress

• Any infinite execution trace that does not contain at least one progress state is a potential starvation loop

• Like for endstates, label names begin with progress

• Must instruct the model checker to look after non-progress cycles (-l)

Unless construct

{ stat11;

stat12;

} unless {

stat21;

stat22;

}

• Executes the statements in the main sequence until the first statement in the escape sequence becomes executable

top related