Introduction à l’outil Spin et au langage Promela
Module SDSC Institut Galilée Master 2 PLS
Page web : http://lipn.fr/~rodriguez/teach/sdsc/2016-17/
Enseignant : César Rodríguez
Transparents : préparés par Sami Evangelista et César Rodríguez
Présentation de l’outil Spin
2/38Ï
Logiciel open source développé initialement par Bell Labs.
Ï
Permet d’analyser formellement des programmes concurrents.
Ï
Langage de description : promela (process meta language).
Ï
Propriétés analysables : accessibilité, temporelles.
Ï
Page web : http://spinroot.com/spin/whatispin.html.
Ï
Cours en ligne avec plus d’informations :
http://lipn.univ-paris13.fr/~petrucci/poly_spin.ps.gz
Plan
3/38Langage Promela : processus
Langage Promela : variables et assertions Utilisation de Spin
Langage Promela : canaux et instructions bloquantes
Langage Promela : if, do
Structure d’un programme Promela
4/38Un programme Promela est constitué d’un ensemble de processus.
Ï
Un processus est donné par une déclaration proctype .
Ï
Spin transforme chaque proctype vers un automate.
Ï
Une fois créé, un processus s’exécute en parallèle aux autres processus.
Deux mécanismes de synchronisation entre processus :
Ï
Les variables globales (déclarées hors processus).
Ï
Les canaux de communication permettant l’échange de messages entre
processus.
Structure d’un programme Promela — Exemple
5/38Éléments de base du langage
6/38 ÏBeaucoup de points communs avec le C :
Ï le “ ;” pour terminer les instructions
Ï la déclaration des variables
Ï les types de base : bit (oubool),byte,short, int
Ï les tableaux
Ï les affectations
Ï le printf
Ï
Mais on ne retrouve
Ï ni les instructions de contrôle (if, for, . . . ) du C,
Ï ni la possibilité de définir et appeler des fonctions.
Exemple : i n t i = 1 0 ; short s [ 1 0 ] ; i ++;
s [ 2 ] = 4 ;
p r i n t f ( " i ␣=␣%d␣ e t ␣ s [ 2 ] ␣=␣%d\ n" , i , s [ 2 ] ) ;
Déclaration des processus
7/38proctype p r o c ( t y p e A r g 1 a r g 1 ; . . . ; typeArgN argN ) { /∗ code du processus ∗/
}
Remarques :
Ï
Un processus peut recevoir des arguments à sa création.
Ï
Attention, on utilise ; au lieu de , pour la déclaration d’arguments
Ï
Un processus peut être créé :
Ï statiquement : à l’initialisation du programme (mot-cléactive)
Ï dynamiquement : avec une instructionrunexécutée par un autre processus
Le processus init
8/38i n i t {
/∗ code du processus i n i t ∗/
}
Remarques :
Ï
Le processus init (facultatif) est créé à l’initialisation du programme.
Ï
On l’utilise généralement pour
Ï initialiser des variables globales
Ï et lancer d’autres processus.
Processus créés statiquement
9/38Ï
On les déclare avec le mot-clé active .
Ï
On peut déclarer N processus.
Ï
Les arguments prennent alors une valeur par défaut.
Ï Exemple : 0 pour les arguments de type int.
active [ N ] proctype p r o c ( t y p e A r g 1 a r g 1 ; . . . , typeArgN argN ) { /∗ code du processus ∗/
}
Processus créés dynamiquement
10/38Ï
On les lance avec l’instruction run .
Ï
On doit lui passer tous les arguments déclarés pour le processus.
proctype p r o c ( t y p e A r g 1 a r g 1 ; . . . ; typeArgN argN ) { /∗ code du processus ∗/
} . . .
run p r o c ( x1 , . . . , xN )
. . .
Les processus — Exemple
11/38active [ 2 ] proctype p r o c 1 ( ) { p r i n t f ( " s t a t i q u e \ n" ) ;
}
proctype p r o c 2 ( i n t x ; i n t y ) {
p r i n t f ( " d y n a m iq u e ␣ : ␣(%d,%d ) \ n " , x , y ) ; }
i n i t {
run p r o c 2 ( 1 , 2 ) ; run p r o c 2 ( 3 , 4 ) ; }
Simulation du programme :
$ s p i n p r o g . pml
d y n a m i q u e : (1 ,2) s t a t i q u e
s t a t i q u e
d y n a m i q u e : (3 ,4)
Plan
12/38Langage Promela : processus
Langage Promela : variables et assertions
Utilisation de Spin
Langage Promela : canaux et instructions bloquantes
Langage Promela : if, do
Les variables
13/38 ÏComme en C, nous avons des variables globales et locales
Ï
A différence de C, les variables sont initialisées à une valeur par défaut
Ï 0 pour des variables numériques.
Exemple :
b i t g1 ; /∗ 0 ∗/
byte g2 ; /∗ 0 ∗/
i n t g3 ; /∗ 0 ∗/
i n t t a b [ 1 0 ] ; /∗ {0 , 0 , . . . , 0} ∗/
short x = 1 2 3 ; /∗ 123 ∗/
active proctype myproc ( ) { i n t l o c 1 ; // 0
p r i n t f ( " g1 ␣%d ␣ l o c 1 ␣%d\ n" , g1 , l o c 1 ) ; a s s e r t ( t a b [ 2 ] == 0 ) ;
a s s e r t ( l o c 1 == 0 ) ;
}
Les assertions
14/38a s s e r t ( c o n d i t i o n ) ;
Ï
Si la condition n’est pas vérifiée le programme s’arrête.
Exemple : byte i ;
active proctype myproc ( ) { i n t j ;
a s s e r t ( i == j ) ;
}
Les assertions — Exemple
15/38Existe-t-il un contrexemple pour l’assertion ? i n t i ;
active proctype i n c r ( ) { i n t j ;
j = i ; i = j + 1 ;
a s s e r t ( i == j + 1 ) ; }
active proctype s e t 1 0 ( ) { i = 1 0 ;
}
Plan
16/38Langage Promela : processus
Langage Promela : variables et assertions Utilisation de Spin
Langage Promela : canaux et instructions bloquantes
Langage Promela : if, do
Spin en mode simulation
17/38On appelle spin en lui donnant le programme à simuler.
$ s p i n p r o g r a m m e . pml
Ï
En mode simulation, spin simule une exécution possible du système.
Ï
Les instructions printf sont évaluées.
Ï
La simulation s’arrête en cas d’assertion non vérifiée ou deadlock.
Options de ligne commande importantes :
Ï
-T : ne pas indenter la sortie des printfs
Ï
-p : afficher les opérations exécutées
Ï
-l : afficher la valeur des variables locales
Ï
-g : afficher la valeur des variables globales
Ï
-i : simulation interactive, l’utilisateur choisit la transition suivante
Ï
-c : afficher "graphiquement" les émissions et réceptions sur les canaux
Spin en mode vérification (1)
18/381. On appelle spin avec l’option
−a.
⇒ Spin génère un fichierpan.c(pan = protocol analyser) qui est l’algorithme d’exploration de l’espace des états accessibles.
2. On compile puis exécute pan.c.
3. Si une erreur est trouvée, un fichier avec l’extension trail est créé.
Ï Ce fichier décrit une exécution qui mène à l’erreur trouvée.
4. On utilise alors spin avec l’option -t pour afficher cette exécution.
$ s p i n - a p r o g r a m m e . pml
$ gcc pan . c - o pan
$ ./ pan
$ s p i n - t p r o g r a m m e . pml
Ï
En mode vérification, spin explore l’espace des états accessibles du programme (= simule toutes les exécutions possibles du programme).
Ï
Les instructions printf sont ignorées.
Ï
L’exploration s’arrête en cas d’assertion non vérifiée.
Spin en mode vérification (2)
19/38En mode vérification, il est possible d’automatiser la génération du pan.c, sa compilation, son exécution, ainsi que l’affichage des contrexemples :
Ï
-search : spin génère, compile et exécute pan.c
Ï
-replay : affiche le contrexemple, similaire à spin -t
Exercice — proctypes, variables, assert
20/38Écrire un programme Promela dans lequel 4 processus incrémentent une variable global g initialisée à 0. Afficher avec printf la valeur après l’incrément.
Ajouter un 5ème processus qui vérifie que la valeur est toujours entre 0 et 4.
1. Simuler avec spin. Est-ce que tous les processus affichent une valeur différente ? Pourquoi ?
2. Vérifier le programme avec spin. L’assertion, est-elle violée ? Modifier la borne supérieure pour qu’elle soit violée et afficher le contrexemple.
Interpréter le format d’affichage du contrexemple.
(Les options -T, -p, -g, pourraient être utiles).
Plan
21/38Langage Promela : processus
Langage Promela : variables et assertions Utilisation de Spin
Langage Promela : canaux et instructions bloquantes
Langage Promela : if, do
Les canaux de communication
22/38Ï
Les canaux sont utilisés par les processus pour s’échanger des messages.
Ï
Il faut se les représenter comme des files FIFO de messages.
Ï
Les messages stockés dans les canaux sont typés.
Ï
Déclaration d’un canal c de N messages contenant des N-uplets.
chan c = [ N ] of { t y p e 1 , . . . , typeN }
Ï
Bonne pratique : mettre un nom symbolique (un mtype ) dans le type des messages pour pouvoir distinguer les messages.
Exemple :
mtype = { r e q u e t e , r e p o n s e , e r r e u r }
chan c = [ 1 ] of { mtype , i n t }
Réception/émission sur un canal
23/38c a n a l ! d o n n e e s /∗ é mission ∗/
c a n a l ? d o n n e e s /∗ r é ception ∗/
Remarques :
Ï
Le récepteur est bloqué si le canal est vide (il attend un message).
Ï
L’émetteur est bloqué si le canal est plein (il attend qu’il se vide).
Ï
Pour un rendez-vous (canal de taille 0) émetteur et récepteur doivent être simultanèment sur les instructions d’envoi.
Ï
Côté récepteur :
Ï On affecte aux variables apparaissant après le ’ ?’ les valeurs contenues dans le message.
Ï Si des constantes apparaissent dans les données le message reçu devra contenir ces valeurs (sinon le processus sera bloqué).
Exemple :
c ? i ; /∗ j ’ attends un e n t i e r que j e stocke dans i ∗/
c ? 5 ; /∗ j ’ attends l ’ e n t i e r 5 ∗/
Réception/émission sur un canal — Exemple
24/38chan c = [ 0 ] of { int , i n t } ; active proctype p ( ) {
i n t x , y ;
c ! 1 0 , 1 2 ; c ? x , y ; /∗ p envoie puis re co i t ∗/
p r i n t f ( "p␣ : ␣ j ’ a i ␣ r e c u ␣(%d , ␣%d ) \ n" , x , y ) ; }
active proctype q ( ) { i n t x , y ;
c ? x , y ; c ! 1 7 , 4 4 ; /∗ q re co i t puis envoie ∗/
p r i n t f ( "q␣ : ␣ j ’ a i ␣ r e c u ␣(%d , ␣%d ) \ n" , x , y ) ; }
Simulation du programme :
$ s p i n t e s t . pml
q : j ’ ai r e c u (10 , 12) p : j ’ ai r e c u (17 , 44) 2 p r o c e s s e s c r e a t e d
Expressions = instructions (bloquantes)
25/38A différence de C, chaque expression Promela est aussi une instruction : i = 3 ; /∗ affectation , ne bloque jamais ∗/
i == 3 ; /∗ exé cution bloquée jusqu ’ à que i s o i t 3 ∗/
i < 4 | | t a b [ 7 ] == 4 /∗ s i t u a t i o n analogue ∗/
p r i n t f ( " . . . " ) ; /∗ ne bloque pas (en p r i n c i p e ) ∗/
Ï
Le processus est bloqué tant qu’une condition n’est pas réalisée.
Ï
Dès que la condition se réalise (grâce à l’action d’un autre processus) il peut continuer à exécuter des instructions.
Les opérations sur les canaux peuvent aussi bloquer l’exécution :
Ï
can ! var bloque le processus si can est plein
Ï
can ? var bloque le processus si can est vide
Ï
can ? 5 bloque le processus si can ne contient pas l’entier 5
Instructions bloquantes — Exemple 1
26/38Instructions bloquantes — Exemple 2
27/38Ce programme, termine-t-il correctement ? chan m = [ 1 ] of { byte } ;
i n i t { m ! 1 0 ; m ! 1 9 ; }
Simulation du programme :
$ spin -T -p -l -g test.pml
0: proc - (:root:) creates proc 0 (:init:) 1: proc 0 (:init::1) test.pml:3 (state 1) [m!10]
queue 1 (m): [10]
timeout
#processes: 1
queue 1 (m): [10]
1: proc 0 (:init::1) test.pml:4 (state 2)
1 process created
Instructions bloquantes — Exemple 3
28/38Existe-t-il un contrexemple pour l’assertion ? byte a , b ;
active proctype i n c r ( ) { a = a + 1 ;
b = b + 1 ; }
active proctype v e r i f ( ) { a s s e r t ( a == b ) ;
}
Instructions bloquantes — Exemple 3’
29/38Et maintenant ? byte a , b ; b i t m = 1 ;
active proctype i n c r ( ) { m = 0 ;
a = a + 1 ; b = b + 1 ; m = 1 ; }
active proctype v e r i f ( ) { m == 1 ;
a s s e r t ( a == b ) ;
}
Instructions bloquantes — Exemple 3”
30/38Et maintenant ? byte a , b ; b i t m = 1 ;
active proctype i n c r ( ) { m == 1 ;
m = 0 ; a = a + 1 ; b = b + 1 ; m = 1 ; }
active proctype v e r i f ( ) { m == 1 ;
m = 0 ;
a s s e r t ( a == b ) ; m = 1 ;
}
Séparateurs d’instructions
31/38Ï
On sépare les instructions par des ; ou des
−>
Ï
Tous les deux ont exactement la même sémantique , mais :
Ï −> souvent après une expression pouvant bloquer le processus
Ï ; souvent après une instruction ne pouvant pas bloquer le processus
Ï
Ceci améliore la lisibilité du code.
Exemple :
( p o r t e F e r m e e == 1 )
−> a s c e n c e u r D e m a r r e = 1 ; e t a g e ++
Ï
Dès que la condition se réalise (grâce à l’action d’un autre processus) il
peut continuer à exécuter des instructions.
Plan
32/38Langage Promela : processus
Langage Promela : variables et assertions Utilisation de Spin
Langage Promela : canaux et instructions bloquantes
Langage Promela : if, do
L’instruction if
33/38i f
: : a l t e r n a t i v e 1 . . . : : a l t e r n a t i v e N
: : e l s e
−> a l t e r n a t i v e E l s e f i
1. Évalue les alternatives 1 à N dont la garde est exécutable.
Ï (La garde est la première instruction de chaque alternative.)
2. Sélectionne de manière non-déterministe une alternative parmi les N données, et l’exécute.
3. Exécute alternative else si aucune des gardes n’est exécutable.
4. Si aucune des gardes n’est exécutable et qu’il n’y a pas de else, le processus est bloqué.
Ï Il pourra s’exécuter si une des gardes devient exécutable (ex : en cas de réception d’un message).
B
L’ordre des alternatives n’a pas d’importance :
Ï Les gardes seront toutes évaluées.
Ï On n’exécute pas forcément la première alternative dont la garde est vraie.
L’instruction if — Exemple
34/38i f
/∗ branche exé cutable sur r é ception d ’ un message de type msg contenant une valeur i sur l e canal c ∗/
: : c ?msg , i
−> . . .
/∗ branche exé cutable sur r é ception d ’ un message de type ack contenant une valeur i sur l e canal c ∗/
: : c ? ack , i
−> . . .
/∗ branche exé cutable s i l a v a r i a b l e k vaut 1 ∗/
: : k == 1
−> . . .
/∗ branche exé cutable s i aucune autre ne l ’ est ∗/
: : e l s e
−> . . .
f i
L’instruction do
35/38do
: : a l t e r n a t i v e 1 . . . : : a l t e r n a t i v e N
: : e l s e
−> a l t e r n a t i v e E l s e od
Ï
Même sémantique que le if mais le bloc do est réexécuté après l’exécution d’une des branches.
Ï
Par défaut, on ne sort jamais du do : il faut pour cela placer une
instruction break dans une des branches.
L’instruction do — Exemple
36/38/∗ on f a i t l a somme de dix e n t i e r s r é ceptionn é s sur l e canal c et on termine ∗/
i = 0 ; y = 0 ; do
: : i < 10
−>
c ? x ;
y = y + x ; i = i + 1 : : i == 10
−>
break
od
Interface graphique ispin.tcl
37/38D’autres caractéristiques importantes
38/38Spin :
Ï
Utilisation des macros #define, Spin utilise le préprocesseur cpp Variables :
Ï
_pid : identifiant d’un processus
Ï
_nr_pr : numéro de processus actives en ce moment Instructions :
Ï
select : selection non-deterministe d’une valeur dans une intervalle.
Ï
for : boucle for Bien plus d’autres :
Ï