600 likes | 619 Views
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)
E N D
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
init { printf(“Hello World\n”); } PROMELA “Hello World” The simplest erroneous specification init { 0; }
init { printf(“Hello World\n”); } The SPIN simulation SPIN C:\> spin –p hello.prom simulation trace 0: proc - (:root:) creates proc 0 (:init:) Hello World 1: proc 0 (:init:) line 3 "pan_in" (state 1) [printf(‘Hello World\\n')]
init { 0; } The SPIN analysis (1) SPIN C:\> spin –a dlock.prom pan.t pan.m pan.b pan.h pan.c GCC pan.exe
dlock.prom.trail pan.exe ERROR The SPIN analysis (2) OK SPIN C:\> spin –p -t dlock.prom error trace #processes: 1 -4: proc 0 (:init:) line 3 "pan_in" (state 1) 1 processes created
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 Warning: type ranges are OS-dependent (just like in C) mtype = {one, two, three};
typedef S { short a, b; byte x; }; Record types (user-defined) • look like C structures
int x, y; int z = 0; mtype m = one; Variables (same C syntax) Processes (like C procedures) • the init process (like main in C) • has no parameters 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> );
if :: <choice1> -> <stat11>; <stat12>; … :: <choice2> -> <stat21>; <stat22>; … … fi; 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
do :: <choice1> -> <stat11>; <stat12>; … :: <choice2> -> <stat21>; <stat22>; … … od; 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
Control flow (3)(more C syntax) • The elsechoice • is executable only when no other choice is executable • The breakstatement • transfers control at the end of loop • The gotostatement • transfers control to a labeled location
mtype = {red, yellow, green}; byte state = green; init { do :: (state == green) -> state = yellow; :: (state == yellow) -> state = red; :: (state == red) -> state = green; od } Traffic light example
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
s12 s11 s11 s21 s21 s12 s22 s21 Complexity . . . • how many states can be reached in this example? • express this number as function of: • K = number of processes • N = number of states/process
s12 s11 s11 s21 s21 atomic s12 s22 s21 Reducing complexity (1) • if a statement inside atomic is not executable, transfer temporarily control to another process . . .
s11 s21 s12 s22 s21 s11+s12 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) s21 d_step . . .
int counter = 0; active[2] proctype incr() { counter = counter + 1; } Apprentice example • Good apprentice • Bad apprentice int counter = 0; active[2] proctype incr() { int tmp; tmp = counter + 1; counter = tmp; } atomic
proctype A() { x = 1; y == 0; mutex ++; mutex --; x = 0; } proctype B() { y = 1; x == 0; mutex ++; mutex --; y = 0; } Mutual exclusion (bad) example proctype monitor() { assert(mutex != 2); }
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; } Dekker’s mutual exclusion proctype monitor() { assert(mutex != 2); }
proctype A() { do :: 1 -> turnA = 1; turnA = turnB + 1; (turnB == 0) || (turnA < turnB); mutex ++; mutex --; turnA = 0; od } Bakery mutual exclusion • does verification terminate?
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 relationR is a subset of A x B • we also write aRb for (a, b) in R • A functionF: A B is a relation such that • for each a A there exists b in B such that aFb • 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 processesP = {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 variablesI = {x1, …, xk } • Let V be a set of valuesV = {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 assignmentA 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; s0S 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; s0S 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) =
Communication (1) • Message passing • 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 */
q ! <expr>; 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 • forasynchronous queues is executable iff the queue is not full
q ? <var>; q ? _; 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 • forasynchronous queues is executable iff the queue is not empty
q ? <expr>; Communication (4) • Channel test statement • same as receive for rendez-vous channels • forasynchronous queues is executable iff the first value in the queue matches the result of expr
chan lock = [1] of bit; proctype foo(chan q) { q ? 1; /* critical section */ q ! 1; } init { lock ! 1; run foo(lock); run foo(lock); } Inter-locking 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 } Recursion example