# Un modèle pour le traitement des erreurs dans un système a domaines

Claude Kaiser, Didier Lanciaux

<figure><img src="image_1.png" /></figure>

## To cite this version:

Claude Kaiser, Didier Lanciaux. Un modèle pour le traitement des erreurs dans un système a domaines. [Rapport de recherche] IRIA-RR-173, IRIA. 1976, pp.28. hal-04716366

HAL Id: hal-04716366

https://inria.hal.science/hal-04716366v1

Submitted on 1 Oct 2024

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_2.png" /></figure>

Distributed under a Creative Commons Attribution 4.0 International License
IRIA

laboria

Institut de Recherche
d'Informatique
et d'Automatique

Domaine de Voluceau
Rocquencourt
B.P. 5 78150 - Le Chesnay
France
Tél.: 954 90 20

laboratoire de recherche
en informatique
et automatique

<figure><img src="image_3.png" /></figure>

UN MODÈLE POUR
LE TRAITEMENT DES ERREURS
DANS
UN SYSTÈME A DOMAINES

Claude KAISER
Didier LANCIAUX

Rapport de Recherche N° 173

Juin 1976
# UN MODELE POUR LE TRAITEMENT DES ERREURS DANS UN SYSTEME A DOMAINES

C. Kaiser, D. Lanciaux

## Résumé :

Le traitement des erreurs prend une importance fondamentale dans une architecture de système destinée à assurer une certaine protection car celle-ci ne doit pas pouvoir être tournée par le biais des erreurs. Ce rapport propose un schéma unique de traitement à l'exécution des erreurs détectées tant dans les parties câblées que programmées. Ce schéma repose sur la structuration du système en domaines.

## Abstract :

Error processing is an important feature in any system design, especially when the architecture includes protection mechanisms since protection rules should not be circumvented by error propagation. This paper presents a uniform schema for run time processing of errors which are detected by hardware as well by software. This schema relies on the division of the system addressing space into domains.
# SOMMAIRE

1. Introduction

2. Etat actuel des recherches

3. Comportement des erreurs

4. Une étude de cas

5. Schéma pour le traitement des erreurs

6. Exemple

7. Modèle pour une machine à domaines
# 1. Introduction

Le traitement des erreurs prend une importance fondamentale dans une architecture de système informatique destinée à assurer une certaine protection car celle-ci ne doit pas pouvoir être tournée par le biais des erreurs. De même que l'on gagne en sûreté, en simplicité et en extensibilité à n'avoir qu'un seul mécanisme de base pour la protection [Ferrié 74], de même il se révèle nécessaire de disposer d'un schéma unique de traitement des erreurs et de l'utiliser dans tout le système, dans les parties câblées et microprogrammées tout autant que dans les programmes.

On prend comme hypothèse de travail que la réalisation des programmes s'effectue en suivant des règles de découpage modulaire, que certains modules ont reçu des preuves de validité et que le compilateur utilisé exécute lui-même ou génère toute une série de tests de validité.

On suppose cependant que, même dans ces conditions de travail, les meilleurs programmeurs peuvent se tromper, que le matériel peut avoir des défaillances, que dans la pratique les programmes sont modifiés et que ces modifications sont sources d'erreurs nouvelles. C'est de ces dernières hypothèses que découle la nécessité du traitement des erreurs à l'exécution.

# 2. Etat actuel des recherches

La complexité des systèmes et de leur programmation est une des causes de leur peu de fiabilité actuelle. Les conséquences économiques de cette faiblesse ont entraîné un grand nombre de recherches pour dégager des méthodes de découpage et pour étudier les relations entre les éléments des systèmes. L'effort porte sur les méthodes d'analyse et de spécification [Boulenger 75, Descartes 37, Dijkstra 72, Hoare 74, Liskov 72, Parnas 72b], sur les techniques de programmation [Boulenger 75, Brinch Hansen 74a, 74b, Krakowiak 75, Liskov 74, Parnas 72a] et sur les mécanismes d'exécution [England 74, Ferrié 74, Guiboud Ribaud 74, Spier 74].

Malgré leur importance pratique, l'analyse et la correction des erreurs ont été peu étudiées pour les systèmes informatiques [Kaiser 74, Rustin 71]; ce n'est que récemment que la nécessité de schémas conçus pour traiter systématiquement les erreurs a été montrée, à l'occasion d'études sur la programmation modulaire [Parnas 72c, Wulf 75], la protection et la sécurité dans les systèmes [Horning 74, Walker 74],
les architectures de systèmes [Creech 70, Guiboud Ribaud 74] ou la
définition de langage universel (structure du "on condition" de PL1).

3. Comportement des erreurs

Le terme erreur recouvre plusieurs notions qu'il faut expliciter
avant d'aller plus loin. Nous développons ici la terminologie introduite
dans [Kaiser 74].

Qu'il soit câblé, programmé ou microprogrammé, l'unité de découpage,
ou module, est un mécanisme déterministe qui est conçu pour réaliser
certaines actions en réponse à des signaux reçus. Il est décrit à ses
utilisateurs potentiels par une spécification qui définit le critère
de validité des signaux reçus, les actions réalisées en réponse aux
signaux valides et les observations sur l'état du module fournies en
cas de refus d'action.

Par exemple, la spécification d'une unité de contrôle d'un disque
précise qu'un ordre de lecture ne peut être accepté si un transfert est
déjà en cours, et que cette cause de refus est indiquée dans le registre
d'état de l'unité de contrôle.

Lorsqu'on spécifie un module, on fait l'hypothèse que la réalisation
du module (le câblage du circuit, ou l'écriture du programme) sera
conforme à cette spécification et que les composants (pièces détachées de
matériel, modules ou instructions de programmes) sont en parfait état. En
pratique ce n'est pas le cas. D'un côté le nombre de tests de validité des
signaux reçus est tel qu'il est impossible ou irréaliste de les faire
tous ; d'un autre côté, faire le test du bon fonctionnement des composants
avant chaque action est trop coûteux en temps et quand bien même cela
serait possible le matériel peut encore avoir une défaillance entre le
moment du test et son utilisation. Enfin la fiabilité du matériel de test
lui même n'est pas totale.

Pour toutes ces raisons, on doit s'attendre à trouver un module dans
des états non voulus qui correspondent à des actions mal engagées.
Nous dirons qu'il y a production d'une erreur si l'exécution d'une action
ne correspond pas à la spécification qui en est donnée. Cette divergence
peut provenir d'une défaillance du matériel, d'une faute dans la
réalisation (câblage ou programmation) ou d'une lacune de l'analyse de
détail à partir de la spécification.
Comme tous les tests ne sont pas effectués, il en résulte que la détection d'une erreur ne se fait pas toujours dans le module où elle se produit et qu'une erreur se propage d'un module à un autre. Cette propagation a des conséquences sur le traitement de l'erreur détectée ; il faut d'une part corriger les actions néfastes entreprises pendant cette propagation (éradication de l'erreur), et d'autre part identifier de façon précise la source de l'erreur détectée (identification de l'erreur). Ce traitement introduit une propagation en sens inverse dans les modules, ou rétropropagation. Seule l'identification de l'erreur permet sa correction, c'est-à-dire la réparation du modèle erroné ou son remplacement par un substitut.

Lorsque le traitement de l'erreur aboutit à l'éradication totale et à la correction de l'erreur, nous parlons alors d'un incident dans un sous système. Dans le cas contraire il s'agit d'une panne du sous système.

### 4. Une étude de cas

Soit un sous système chargé d'imprimer les fichiers des utilisateurs [Baudet 72, Crocus 75]. En fonctionnement normal, 4 modules interviennent (figure 1) :

- le module `USAGER` contient le programme de l'utilisateur et adresse des demandes d'impression sous la forme `FACTEUR.PRINT(LANSERLIA)` où `LANSERLIA` désigne le fichier à imprimer,

- le module `FACTEUR` assure l'impression de tout un fichier, en le découplant en morceaux qu'il place chacun dans un tampon et dont il demande la sortie par `PILOTE.OUTPUT(CHAUDRON)` où `CHAUDRON` est le nom du tampon à imprimer,

- le module `PILOTE` contrôle l'impression d'un tampon et envoie les ordres ligne par ligne sous la forme `IMPRIMANTE.SIO(STIC)` où `STIC` désigne une ligne à imprimer,

- le module `IMPRIMANTE` réalise l'impression d'une ligne.

<figure><img src="image_4.png" /><figcaption>Figure 1. Chaîne d'appel des modules en fonctionnement normal.</figcaption></figure>
Pour nous permettre d'écarter momentanément les erreurs dues au partage et au parallélisme, nous supposons, pour commencer cette étude de cas, que :

- les modules ne sont utilisés que par un seul processus à la fois, ce qui élimine la nécessité de la réentrance,

- les composants d'un module ne sont partageables avec d'autres modules que dans la mesure où ces composants sont eux-mêmes des modules,

- l'appel d'un module est analogue à un appel de procédure ; ce n'est pas une création de processus.

Ces hypothèses étant posées, nous nous intéressons aux erreurs suivantes qui peuvent survenir, dans le sous système, en réponse aux actions demandées.

a) `FACTEUR.PRINT(LANSERLIA)`

1. Le fichier `LANSERLIA` ne peut pas être utilisé, soit parce qu'il n'existe pas, soit parce que son accès n'est pas autorisé à l'utilisateur qui le demande.

2. La demande d'impression ne peut pas être satisfaite par suite de défaillance des périphériques.

3. Il se passe quelque chose d'anormal et de non identifié.

b) `PILOTE.OUTPUT(CHAUDRON)`

1. Le tampon `CHAUDRON` ne peut être utilisé, soit parce qu'il n'existe pas, soit parce qu'il est incorrectement rempli.

2. L'impression ne peut pas se faire par suite de défaillance des périphériques.

3. Il se passe quelque chose d'anormal et de non identifié.

c) `IMPRIMANTE.SIO(STIC)`

1. La ligne `STIC` n'existe pas ou n'est pas dans un format correct.

2. L'imprimante n'est pas dans un état où elle peut imprimer la ligne (hors tension, pas de papier...).

3. L'impression a été tentée, mais elle n'a pas abouti.

L'élaboration d'un tel sous système passe par des versions successives au cours desquelles on prévoit des réactions de plus en plus précises aux erreurs.
VERSION 1. On réalise une première maquette pour étudier le fonctionnement normal des modules et procéder à la mise au point de leur construction. Quand une erreur est détectée, elle est corrigée par une intervention humaine. Comme l'erreur a pu se propager avant d'être détectée, la correction de l'erreur nécessite de connaître la chaîne des modules appelés et d'avoir copie de leurs états et des paramètres qui leur ont été passés. Pour ce faire, quand l'erreur est détectée, le processus utilisateur du sous système appelle un module de mise au point en lui passant ces informations, puis il retourne au module appelant en lui signalant l'erreur. Le module de mise au point édite les informations d'erreur dans une forme exploitable par le programmeur. En cas de mise au point interactive, le processus utilisateur est interrompu le temps nécessaire à l'interaction, mais le cheminement dans les modules reste inchangé (figure 2).

<figure><img src="image_5.png" /><figcaption>Figure 2. Cheminement dans les modules pour la version 1.</figcaption></figure>

Remarque : On suppose que le module de mise au point est correct et n'introduit pas de nouvelles erreurs.
VERSION 2. Pour améliorer le comportement du sous système en cas d'erreur, on veut prendre en compte l'expérience acquise sur les erreurs de l'imprimante. Par exemple on s'est aperçu, pour l'erreur n°3 de IMPRIMANTE.SIO(STIC), que recommencer deux fois est une heuristique qui a de bonnes chances de succès. Par contre quand l'imprimante n'est pas en état (erreur n° 2), il y a peu de chance de réussir à s'en servir sans l'aide de l'opérateur (pour la mettre sous tension, pour débourrer le papier ou en remettre,...).

On est ainsi amené à prévoir deux sortes de réactions dans le module PILOTE :

a) tenter une correction à l'intérieur du module, pour l'erreur n° 3,

b) faire appel, pour l'erreur n° 2, à un module extérieur de dialogue avec l'opérateur.

La rétropropagation correspondante apparaît sur la figure 3.

<figure><img src="image_6.png" /><figcaption>Figure 3. Rétropropagation particulière à la version 2.</figcaption></figure>

VERSION 3. On veut mettre à profit la présence d'autres matériels (une deuxième imprimante et un disque) qui peuvent servir de substitut en cas de panne de l'imprimante. Comme l'unité manipulée est le fichier et qu'il ne serait pas judicieux de demander à l'utilisateur de reconstituer lui même le texte de son fichier à partir de feuilles imprimées sur diverses imprimantes, cette substitution intervient dans le module FACTEUR qui manipule les fichiers.
Quand l'appel `PILOTE.OUTPUT(CHAUDRON)` ne peut être honoré par suite des erreurs 2 ou 3, l'impression est demandée sur une autre imprimante par l'intermédiaire d'un module `PILOTE 2`.

Si cette imprimante tombe également en panne, le fichier est conservé sur disque par le biais de `PILOTE 3`, en attendant la réparation d'une des deux imprimantes.

Ce n'est que lorsque ce disque est plein que le facteur retourne une indication d'erreur (n° 2).

La rétropropagation particulière à cette version apparaît sur la figure 4.

<figure><img src="image_7.png" /><figcaption>Figure 4. Rétropropagation propre à la version 3</figcaption></figure>

On remarque que les périphériques ne sont pas connus directement, mais seulement par leurs modules d'accès. Qu'ils soient réels ou virtuels, accessibles directement ou par un réseau, ne modifie rien.

VERSION 4. A ce point nous modifions les conditions d'utilisation des modules ; nous supposons que le module `FACTEUR` peut être appelé par plusieurs processus à la fois et que les fichiers qui lui sont passés en paramètre sont partagés entre plusieurs utilisateurs. Nous conservons cependant l'hypothèse que les appels de module sont analogues à des appels de procédure.

Certaines actions du module `FACTEUR` doivent alors s'exécuter en section critique et il doit "ouvrir" le fichier à imprimer pour s'en réserver l'emploi. Si alors le traitement d'erreur conduit à sortir du module par retour au module appelant, avec
indication d'erreur, il peut être au préalable nécessaire de
"fermer" le fichier à imprimer ou de sortir de la section
critique. On retrouve ici la nécessité d'introduire dans la
structure de module un prologue et un épilogue chargés de
gérer la synchronisation et le partage [Krakowiak 75].
Une difficulté nouvelle apparaît quand l'erreur se produit
en section critique, que sa correction fait appel à un autre
module et que ce nouveau module doit aussi avoir accès aux
données partagées et critiques. La section critique s'étend
alors, en cas d'erreur, sur plusieurs modules car il faut bien
interdire à tout autre processus l'accès aux données partagées
tant qu'il y a doute sur leur qualité. Rappelons qu'une bonne
règle de programmation consiste à éviter de commencer une
section critique dans un module et de la terminer dans un autre
[Brinch Hansen 74a, Hoare 74] ; on doit, même en cas d'erreur,
restreindre à un seul module la manipulation d'une variable de
synchronisation.

VERSION 5. On désire maintenant expérimenter une organisation différente pour ce système. On introduit un processus pour coordonner l'impression de tout un fichier (processus P-FACTEUR) et un processus pour contrôler l'impression d'un tampon (processus P-PILOTE). Les processus associés aux utilisateurs (processus P-USAGER), P-FACTEUR, et P-PILOTE communiquent entre eux par messages, ce qui permet de découpler leurs rythmes de progression. On suppose que les processus P-USAGER, P-FACTEUR et P-PILOTE appellent d'autres modules que ceux du présent exemple ; autrement dit ce ne sont pas des processus dont l'activité, cyclique, serait entièrement décrite par un seul module. Les communications entre modules ne sont plus des appels procéduraux et un nombre indéterminé d'instructions peut être exécuté par un processus entre :
- sa demande d'action et l'exécution de celle-ci par un autre processus,

- l'émission de la réponse, positive ou négative, à une action demandée et la réception de cette réponse par le processeur demandeur.
Pour préciser l'exemple, introduisons deux nouveaux modules M1 et M2 :

M1 gère le transfert de messages entre P-USAGER et P-FACTEUR, M2 gère le transfert de messages entre P-FACTEUR et P-PILOTE.

Considérons la situation suivante :

- P-USAGER a envoyé à P-FACTEUR le nom d'un fichier à imprimer (LANSERLIA), puis continue d'autres traitements;

- P-FACTEUR a reçu ce message, appelé le module FACTEUR, puis le module M2 et a envoyé à P-PILOTE un tampon à imprimer (CHAUDRON) ; ensuite il a effectué d'autres traitements;

- P-PILOTE a reçu ce message, appelé le module PILOTE, puis l'imprimante. C'est alors qu'il a détecté une erreur : la ligne qu'on lui a fournie n'est pas dans un format correct.

P-USAGER
utilise M1 pour
envoyer LANSERLIA ;
autres traitements ;
utilise M1 pour
recevoir LANSERLIA ;
utilise FACTEUR qui appelle PILOTE ;
utilise M2 pour
envoyer CHAUDRON ;
autres traitements ;
utilise M2 pour
appelle IMPRIMANTE ;
retour erreur n° 1 ;

Nota : utilise X signifie que l'action du module X a été complète et que l'opération de retour du module X a été exécutée, appelle X signifie que le module X est appelé et que l'opération de retour n'a pas été exécutée.

Supposons que cette erreur ait son origine chez l'usager et que l'on veuille lui permettre de la corriger, quelles sont alors les contraintes à imposer pour rendre possible une retropropagation qui ramène jusqu'à lui ?

Sans apporter une solution à ce problème, citons néanmoins les points suivants :

- il faut que le demandeur existe encore au moment où arrive la réponse (par exemple l'utilisateur ne doit pas avoir quitté le système) ou alors il doit avoir désigné un chargé de pouvoir ;

- il faut qu'il ait accès au module d'où est parti la demande. Remarquons que dans les systèmes classiques, on n'essaie pas de réaliser cette rétropropagation : on traiterait l'exemple ci-dessus en avortant l'impression de la ligne ou de tout le fichier LANSERLIA.
## 5. Schéma pour le traitement séquentiel des erreurs

Les versions 1 à 4 de l'exemple précédent montrent le besoin dans chaque module d'une analyse d'erreur qui puisse faire appel à d'autres modules et qui se termine par la correction de l'erreur ou par un retour au module appelant en lui signalant l'existence de l'erreur.

**Propriétés des modules.** Avant de proposer un schéma pour le traitement séquentiel des erreurs, nous allons énoncer quelques hypothèses sur les modules pour préciser le domaine de validité de ce schéma.

**Hypothèse 1.** Les seuls objets partageables du système sont les modules et les paramètres.

Il en résulte que même en cas d'erreur un module n'a pas accès aux variables locales d'un autre module et que les procédures d'erreur sont écrites dans les termes de la machine abstraite utilisée pour les procédures normales du module. (Il n'y a pas de variables globales).

**Hypothèse 2.** Tout module n'est connu de ses utilisateurs que par une spécification qui définit, à l'aide d'un modèle abstrait, ce que sont les objets construits par le module, quelles sont les opérations qu'il implémente et quelles contraintes de synchronisation il leur impose [Kronental 75].

Il en résulte que la réalisation d'un module n'est pas connue de ses utilisateurs et que les informations d'erreur transmises hors du module doivent être définies dans le modèle abstrait de la spécification du module.

**Hypothèse 3.** La réalisation du module est définie par une représentation qui indique comment sont composés les objets construits par le module, comment sont réalisées les opérations du module, comment sont appliquées les contraintes de synchronisation et quelles sont les variables internes que le module utilise.

Il en résulte que les procédures de détection et de traitement d'erreur, apparaissent dans la représentation du module.

**Hypothèse 4.** Les appels de modules sont des appels procéduraux vers des points d'entrée spécifiés. Ce sont les seules façons d'utiliser un module. Le retour d'un module renvoie au module appelant.
Hypothèse 5. On appelle processus une suite d'actions réalisées par une machine (ou un système) informatique. Il lui correspond un cheminement parmi les modules.

En général le contrôle du système fait considérer plusieurs processus à un instant donné. On introduit alors une représentation en machine d'un processus complet ou partiel et on donne également le nom de processus à cette représentation. A cause de l'hypothèse 4, il n'est pas nécessaire de représenter tout un processus mais seulement le sous suite des modules appelés mais non terminés.

On suppose alors que cette représentation est gérée en pile. (On l'appellera pile des contextes dans le paragraphe 7).

Hypothèse sur l'apparition d'une erreur. Quand une erreur apparait, on suppose a priori qu'elle a son origine dans les actions intreprises par les modules appelés mais non terminés. Il en résulte que :

- la pile des contextes peut être utilisée pour la rétropropagation,

- tout module terminé n'intervient pas a priori dans la recherche de l'erreur.

Propriétés du traitement des erreurs

Nous cherchons à doter le schéma de traitement des erreurs de quelques propriétés qui soient utiles pour la conception des systèmes.

Localité. Les variables internes d'un module, de même que la réalisation du module, ne sont pas accessibles aux procédures d'erreur des autres modules.

Cette propriété résulte des hypothèses 1 et 2 sur les modules.
Généralité. Le même schéma de traitement d'erreur s'applique au logiciel et au matériel.

Cette propriété peut guider certains choix. Par exemple, il existe deux façons de déceler la présence de l'indication d'erreur au retour d'un module : par un test programmé ou par un test câblé.

Dans le premier cas, chaque utilisation d'un module est suivie d'une instruction de test d'un paramètre de retour. La généralisation de cette méthode implique l'utilisation d'un "code condition" au niveau des instructions de la machine. On notera qu'on peut supprimer le test si on accepte le risque de la propagation de l'erreur.
Dans le second cas, le cycle d'exécution d'une instruction de la machine se termine par le test d'un indicateur booléen dont la valeur est recalculée par chaque instruction. En cas d'erreur il y a branchement à une adresse standard. C'est la technique de la trappe ou du déroutement. La généralisation de cette méthode câblée implique l'introduction au niveau du module appelé d'une instruction de retour avec placement de l'indicateur boolean et la réactivation du module appelant à une adresse standard dans ce module. Dans cette solution on peut supprimer le test par "masquage" ou négliger son effet en mettant, à l'adresse standard, une instruction de retour à l'adresse normale.

## Présentation du schéma.

Un module peut se trouver dans l'un des trois états d'exécution :

- normal : aucune erreur n'a été détectée, le module donne toutes les apparences du bon fonctionnement ;

- incident : une erreur a été détectée soit par le module lui-même, soit par un module appelé, soit par une instruction de la machine, et le module essaie, seul ou avec l'aide d'autres modules, de corriger cette erreur ;

- panne : le module est incapable de corriger l'erreur qui a été détectée.

Les transitions d'un état à l'autre sont régies par des événements spécifiques (figure 5) :

- la détection d'une erreur par programme dans le module ( avatar local) ou par le matériel ( avatar machine), la rétropropagation d'une erreur (rétro avatar) font passer le module de l'état normal à l'état incident, ou de l'état incident à l'état panne ;

- l'insuffisance d'information impose de continuer la rétropropagation vers le module appelant (retour anormal), tout en ramenant le module de l'état incident à l'état normal ;

- l'impossibilité de corriger l'erreur (échec) met le module de l'état incident à l'état panne ;

- l'aboutissement de la correction (succès) fait passer le module de l'état incident à l'état normal et arrête la rétropropagation.
<figure><img src="image_8.png" /><figcaption>**Figure 5.** Etats d'un module et transitions entre ces états.</figcaption></figure>

La représentation du module est divisée en trois régions qui correspondent à ces trois états : la région normale décrit la réalisation des fonctions normales du module, la région incident décrit les traitements d'erreur et la région panne indique la réaction à suivre en cas de panne.

Le passage d'une région à l'autre se fait selon des règles strictes. L'entrée dans la région incident n'est possible que par des points d'accès déclarés et se fait comme un appel de procédure. Il en est de même pour l'entrée dans la région panne. Le passage de la région incident à la région normale est traité comme un retour de procédure.

La région incident comprend deux points d'entrée standards correspondant à la rétropropagation (rétro avatar) et à une erreur de machines (avatar machine). Les autres points d'entrée correspondant aux erreurs détectées par le programme du module sont programmés.

La région panne ne comprend qu'un unique point d'entrée standard connu du matériel et utilisé par lui pour connaître le module extérieur à alerter.

Ce schéma utilise des instructions spéciales :

- *appel pour avatar* : c'est un appel de procédure qui génère un avatar local et qui conduit à l'un des points d'entrée de la région incident ou de la région panne.

- *retour d' avatar* : c'est un retour de procédure qui remet le module dans l'état normal, qui le ramène à l'adresse du traitement normal (ou à l'adresse suivante ou à un point d'entrée du module) et qui stoppe la rétropopagation de l'erreur.

- *retour anormal de module* : c'est un retour vers le module appelant qui entraîne l'appel dans ce module de la procédure associée au rétro avatar, au lieu de poursuivre le traitement normal.
La figure 6 donne un résumé du schéma complet.

<figure><img src="image_9.png" /><figcaption>Figure 6. Représentation graphique du schéma</figcaption></figure>

### Modules terminaux

Quand on compose les modules, deux d'entre eux sont amenés à jouer un rôle particulier, le module machine et le module initial d'un processus.

a) Par définition le module machine est celui qui n'est jamais empilé car une instruction de la machine est indivisible et n'est jamais reprise en son milieu. Le module machine n'appelle aucun autre module. Les seules réactions possibles du module machine sont le retour de module ou le retour anormal du module. Son schéma est donné en figure 7a.
Cette organisation a comme conséquence que les déroutements pour défaut de ressource (page, segment, liaison ...) ne sont pas traités dans le module machine et que les instructions où ils se sont produits doivent être recommencées une fois la ressource acquise.

b) Le module initial du processus n'a pas été invoqué par un appel habituel de module ; il ne peut pas émettre d'instruction de retour de module ou de retour anormal de module. La rétropropagation des erreurs doit s'y éteindre : les seules réactions standards possibles sont l'appel d'un domaine du système (pour appeler un autre processus ou le noyau du système). Le schéma de ce module apparaît dans la figure 7b.

A titre d'exemple dans une architecture du type de la Burroughs B6500, les modules initiaux de tous les processus seraient le même module car les piles de tous les processus ont une racine commune (pile cactus ou pile arborescente)

<figure><img src="image_10.png" /><figcaption>Figure 7. Schémas des modules terminaux</figcaption></figure>
## 6. Exemple

Nous avons représenté, figure 8, les liaisons inter modules dans la version 3 du sous système d'impression étudié au paragraphe 4.

<figure><img src="image_11.png" /><figcaption>Figure 8. Liaisons inter modules du sous système</figcaption></figure>

Il est maintenant possible d'esquisser les programmes des modules USAGER, FACTEUR et PILOTE de cette version.
module USAGER

région panne : appeler le module système de gestion des processus

région incident :

debut

retro avatar

cas FACTEUR.PRINT(X)

debut

cas avatar 2 ou 3 : appeler le module de mise au point

cas avatar 1 :

debut

mettre dans le fichier de sortie du processus le message

"erreur X" ;

retour d' avatar ( post ) ;

commentaire : conduit dans la région normale à l'instruction

suivant FACTEUR.PRINT

fin

fin

:

fin

région normale

debut

.....

FACTEUR.PRINT (LANSERLIA) ;

.....

fin
module FACTEUR

région panne : appeler le module de mise au point

région incident

debut

retro avatar

cas PILOTE.OUTPUT(X)

debut

cas avatar 1 ou 3 : appel du module de mise au point ;

cas avatar 2 :

debut

fermer le fichier X ;

si pilote = pilote 3 alors

retour anormal de FACTEUR (avatar 2) ;

pilote := si pilote 2 alors pilote 3 sinon pilote 2 ;

retour avatar (entrée PRINT(X)) ; commentaire :
on recommence toute l'impression ;

fin

fin

......

fin

région normale

entrée PRINT (X) :

variable externe PILOTE dans (pilote 1, pilote 2, pilote 3) ;

debut

......

ouvrir le fichier X

......

PILOTE.OUTPUT(CHAUDRON) :

......

fermer le fichier X

......

fin

......

initial PILOTE = pilote 1 ;
module PILOTE 1

région panne : appeler le module de mise au point :

région incident

debut

avatar machine

cas SIO(X)

debut

cas avatar 1 : appel du module de mise au point ;

cas avatar 2 :

debut

appel du module OPERATEUR ; commentaire : le retour du
module OPERATEUR est accompagné d'une réponse ;

si réponse = imprimante en état alors retour avatar
(idem)

sinon retour anormal de PILOTE ( avatar 2 )

fin ;

cas avatar 3 :

debut

OK := false ;

retour avatar (post)

fin ;

cas avatar 4 : retour anormal de PILOTE ( avatar 2 ) ;

région normale

entrée OUTPUT(X) ;

debut boolean OK ;

.....

procedure sortie(Y) ;

debut

entier compte ; compte := 0 ; OK := true ;

repeter

debut

compte := compte + 1 ;

SIO(Y)

fin

tant que (¬OK) ou (compte<3) ;

si compte = 3 alors appel pour avatar 4 ;

fin

.....

sortie(STIC)

.....

fin
# 7. Modèle pour une machine à domaines

## La machine à domaines

L'étude de ce schéma d'erreur s'intègre dans la conception d'une architecture de système adapté à la protection. Dans un tel système, chaque utilisateur peut construire son propre sous système et y définir des règles particulières de partage et de protection. L'architecture du système doit permettre de contrôler le bon emploi des objets et de limiter la propagation des erreurs et il y est fondamental que la protection ne soit pas mise en échec lors de l'apparition d'erreurs.

Les objets protégés et les opérations définies sur eux sont contrôlés par l'emploi de descripteurs câblés contenant des informations utilisables seulement par le noyau de protection (type, droits d'accès et nom unique de l'objet) [Ferrié 74]. Le schéma de traitement des erreurs met en jeu deux types d'objets, le domaine et le processus.

Le domaine matérialise en machine la notion de module : un domaine est un ensemble d'objets qui n'est accessible qu'en des points contrôlés. A chacun d'eux est associé le descripteur d'une procédure qui est exécutée à l'entrée dans le domaine par l'instruction d'appel de domaine. Le retour de domaine se fait toujours vers le domaine appelant ; un cheminement dans les domaines prend toujours la forme d'un aller-retour.

Un processus est un objet qui, à l'exécution, permet de garder trace d'un cheminement particulier parmi les domaines. Il comporte une pile, dite pile des contextes, qui conserve les contextes des domaines qu'il a traversés pendant le sens aller du cheminement mais par lesquels il n'est pas encore passé pour le cheminement de retour. Par contexte du domaine, on désigne les objets qui sont mis en place pour l'exécution d'un appel spécifique du domaine (paramètres effectifs, locaux, procédures...).

L'adressage de cette machine est tel qu'un processus ne peut désigner seulement que les objets du dernier contexte du cheminement, qu'on désigne sous le nom de contexte courant. Chaque appel et retour de domaine change donc l'ensemble des objets adressables par le processus [Kaiser 76].

## Mécanismes de traitement des erreurs

Nous avons proposé de réagir aux erreurs d'une façon propre à chaque module. Ceci nous conduit à associer un mécanisme câblé de traitement d'erreur à l'objet domaine, et non pas à l'objet processus, et à introduire dans la structure du domaine des éléments spéciaux pour ce traitement.
a) On doit considérer 4 éventualités et décrire pour chacune d'elles le mode de réaction à adopter.

Entrée panne : si le descripteur est du type domaine, il indique le domaine à appeler en cas de panne ; sinon l'option par défaut consiste à exécuter un retour anormal vers le domaine appelant.

Entrée avatar machine : si le descripteur est du type domaine, il indique le domaine à appeler en cas d'erreur ; si le descripteur est de type segment exécutable (procédure), il indique la procédure du domaine à appeler en cas d'erreur ; sinon l'option par défaut consiste à appeler l'entrée panne du module.

Entrée avatar local : idem.

Entrée rétro avatar : idem.

On notera que l'option par défaut des entrées avatar permet de traiter systématiquement certaines erreurs des procédures d'erreur elles-mêmes (absence d'un descripteur correct à l'entrée avatar).

b) Les entrées pour avatar local ne sont utilisables qu'à l'intérieur d'un domaine. Les conventions de leur désignation sont identiques à celles des procédures classiques et comme elles peuvent être réglées à la compilation du domaine. Ces conventions n'ont pas à être les mêmes pour tous les domaines.

Les entrées avatar machine et rétro avatar sont connus à l'extérieur du module ; il faut des conventions universelles pour les désigner : on les matérialise à l'aide de registres spécialisés du contexte. Ces registres sont programmables pour permettre éventuellement de redéfinir dynamiquement la réaction du module.

c) Le traitement des erreurs se fait localement au domaine, l'identification de la procédure courante et des procédures d'erreur doit se faire à l'aide de noms locaux à ce domaine et non à l'aide des noms uniques contenus dans les descripteurs. Le compteur ordinal et les registres du contexte associés aux points d'entrée pour incident ou pour panne contiennent des noms locaux de procédure ou des noms locaux d'externes.
d) L'état d'exécution du domaine ("normal" ou "incident") est conservé dans la pile des contextes du processus.

e) Des paramètres d'erreurs sont transmis d'un domaine à un autre (que ce soit à l'appel ou au retour de domaine) dans un registre spécialisé.

f) Les changements d'états des domaines sont régis par les opérations décrites au paragraphe 5 :

* appel pour avatar,
* retour d' avatar,
* retour anormal de module.

En particulier l'instruction *retour anormal de module* renvoie au module appelant et charge dans le compteur ordinal le contenu du registre point d'entrée rétroavatar après avoir contrôlé qu'il désignait bien un segment exécutable. Cette instruction sauvegarde aussi l'adresse de retour normal dans le module et place l'indicateur d'état d'exécution à la valeur "incident".

## Erreurs détectées dans le domaine machine

Revenons sur le fonctionnement d'une machine à domaines et remarquons, qu'à tout niveau d'observation il intervient non pas un seul, mais deux domaines qui sont :

- le domaine programmé que l'on a considéré jusqu'à présent et qui a été appelé par une instruction d'appel de domaine,

- et le domaine machine qui exécute les opérations élémentaires du niveau d'observation considéré.

Nous avons proposé un schéma pour la détection et la correction des erreurs découvertes par le domaine programmé. Nous devons l'étendre aux erreurs qui sont détectées pendant l'exécution d'une instruction, c'est à dire dans le domaine machine. On trouve parmi ces erreurs :

- des erreurs arithmétiques : dépassement de capacité, division par zéro,...,

- des erreurs de frontière : dépassement de longueur d'un segment, opération interdite,...,

- des absences de ressources : défaut de page, descripteur nul, débordement de la pile des contextes ...

- des erreurs du matériel : parité mémoire,...

La réaction à chacune de ces erreurs varie selon les systèmes et il serait dangereux de la fixer a priori. Ainsi une erreur pour descripteur nul peut conduire :
- à avorter un programme dans un système séquentiel,

- à appeler un programme de mise au point dans un système intéractif,

- à appeler l'éditeur de liens dans un système à édition de liens dynamique.

Par contre, dans un système donné, il existe des erreurs qui ne peuvent être traitées que par des domaines spéciaux (par exemple : le défaut de page ou la parité mémoire) tandis que d'autres erreurs sont tantôt traitées dans le contexte courant, tantôt par un domaine spécial (par exemple : la division par zéro). Enfin, il est des erreurs dont la gravité dépend du domaine programmé où elles se produisent (par exemple un défaut de page dans le domaine résident chargé du traitement de ce défaut de page doit être considéré comme une panne).

Pour conserver toute la souplesse possible au traitement des erreurs du domaine machine, on introduit 2 filtres consécutifs dont :

- l'un, le filtre amont, est considéré comme un objet du domaine machine et sert à marquer les erreurs que seuls des domaines spéciaux peuvent traiter,

- et l'autre, le filtre aval, est considéré comme un objet du contexte courant et sert à indiquer, pour chaque erreur non filtrée en amont, la réaction à lui associer : rétropropagation dans le contexte courant, appel d'un domaine spécial, indifférence (erreur à ne pas considérer).

Au filtre amont, on associe la liste des descripteurs et des points d'entrées des domaines spéciaux ; ce filtre et cette liste constituent un objet construit dont l'accès est contrôlé par un descripteur qu'on ne trouve en général que dans des domaines très privilégiés du système. Par exemple, le domaine résident chargé du traitement de défaut de page pourrait ainsi modifier la liste des descripteurs des domaines spéciaux pour ne pas être rappelé en cas de défaut de pages pendant sa propre exécution.

Le filtre aval n'est qu'un aiguillage câblé sur le point d'entrée avatar machine du domaine. On lui associe une liste de noms locaux de domaines externes (avec leurs points d'entrées) ou de procédures internes au domaine courant.

Dans tous les cas, le compteur ordinal désigne l'instruction qui a engendré l'erreur et il est sauvegardé. Il est ensuite chargé avec une nouvelle valeur qui est :
- soit le nom local d'une procédure du même domaine (rétropropagation),

- soit le nom local d'un point d'entrée dans la nouveau domaine courant.

En cas de rétropropagation, l'état d'exécution de la machine prend la valeur "incident".

<figure><img src="image_12.png" /><figcaption>Figure 9. Action des filtres</figcaption></figure>

<figure><img src="image_13.png" /><figcaption>Figure 10. Localisation des données du traitement d'erreur.</figcaption></figure>
## Traitement des pannes

La détection d'une panne du domaine se fait alors que celui-ci se trouve dans l'état incident et traduit l'impossibilité de poursuivre le traitement d'un incident. Cette impossibilité peut avoir deux origines :

- elle provient d'une décision prise dans la région incident (détection par programme). Alors le choix d'un mode de réaction peut également être fait dans cette région et ne nécessite pas de mécanismes particuliers,

- elle provient de la détection d'une nouvelle erreur par le domaine machine. Alors, les mécanismes décrits au paragraphe précédent peuvent être utilisés. La région panne d'un domaine est donc définie par le filtre aval.

On notera que l'absence de région incident ou une erreur lors de l'activation de cette région sont des causes de panne d'un domaine. Le choix d'un mode de réaction est alors encore possible dans la mesure où le domaine a été muni d'une région panne. Lorsque ce n'est pas le cas ou lorsque cette région panne est à nouveau source d'une erreur, un mode de réaction doit être imposé implicitement ; la logique du modèle veut que ce mode soit la rétropropagation.

L'état panne n'est pas matérialisé. En effet, il provoque :

- un appel de domaine, auquel cas le retour dans le domaine aura lieu à l'état incident,

- une retropropagation qui conduit à la destruction du contexte courant.
BIBLIOGRAPHIE

Baüdet 72 : G.Baudet, J.Ferrié, C. Kaiser, J. Mossière. Entrées-sorties dans un système à mémoire virtuelle. *Congrès AFCET Grenoble (1972).*

Boulenger 75 : J.Boulenger, M.Kronental. Aspects de la notion de type. *Rapport Laboria* n° 108 (1975).

Brinch Hansen 74a : P.Brinch Hansen. Concurrent Pascal, a programming language for operating systems design. *Inf. Sc. TR 10, Calif. Inst. of Technology* (April 1974).

Brinch Hansen 74b : P.Brinch Hansen. Deamy : a structured operating system. *Inf. Sc. TR 11. Calif. Inst. of Technology* (May 1974).

Creech 70 : B.Creech. Architecture of the B6500. *Software engineering* (TOU edit) Academic Press (1970).

Crocus 75 : Crocus. *Systèmes d'exploitation des ordinateurs : principes de conception*. Dunod 1975.

Descartes 37 : R. *Discours de la méthode*. Paris (1637).

Dijkstra 72 : E.W.Dijkstra. Notes on structured programming. *Structured programming*. (Dahl, Dijkstra, Hoare). Academic Press (1972).

England 74 : D.M.England. Capability concept, mechanism, and structure in System 250. *Int. workshop on protection in operating systems*. IRIA (August 1974).

Ferrié 74 : J.Ferrié, C.Kaiser, D.Lanciaux, B.Martin. An extensible structure for protected systems design. *Int. workshop on protection in operating systems*. IRIA (August 1974).

Guiboud-Ribaud 74 : S. Guiboud-Ribaud, J. Briat. Espace d'adressage et espace d'exécution du système Gemau. *Operating Systems, Lecture notes in Computer Science*, 16, Springer Verlag (1974).

Hoare 74 : C.A.R. Hoare. Monitors : an operating system structuring concept. *CACM* 17, 12 (December 1974).
Horning 74 : J.J.Horning, H.C.Lauer, P.M.Melliar-Smith, B.Randell. A program structure for error detection and recovery. *Operating systems. Lecture notes in computer science*, 16, Springer Verlag (1974).

Kaiser 74 : C.Kaiser, S.Krakowiak. Analyse de quelques pannes d'un système d'exploitation. *Operating Systems, Lecture notes in Computer Science*, 16, Springer Verlag (1974).

Kaiser 76 : C. Kaiser, D. Lanciaux, B. Martin. Un adressage pour une architecture à domaine. *Rapport Laboria*

Krakowiak 75 : S. Krakowiak, M.Lucas, J.Montuelle, J.Mossière. A modular approach to the structured design of operating systems. *RR n° 3*, Université de Grenoble (1975).

Kronental 75 : M.Kronental. Contribution au développement d'une méthode de conception des systèmes informatiques. *Thèse de 3e cycle*. Université de Paris VI (1975).

Liskov 72 : B.H.Liskov. A design methodology for reliable software systems. *Proc. AFIPS FJCC* (1972).

Liskov 74 : B.H.Liskov, S.Zilles. Programming with abstract data types. *Proc. Symp. on very high level languages*, SIGPLAN notice 9,4 (1974).

Parnas 72a : D.L.Parnas. A technique for software module specifications with examples. *CACM*, 15, 5 (May 1972).

Parnas 72b : D.L.Parnas. On the criteria to be used in decomposing a system into modules. *CACM*, 15,12, (December 1972).

Parnas 72c : D.L.Parnas. Response to detected errors in well-structured programs. *Internal report Carnegie Mellon University* (1972).

Rustin 71 : R.Rustin (editor). Debugging techniques in large systems. *Prentice Hall* 1971.
Spier 74 : M.J.Spier, T.N.Hastings, D.N.Cutler. A storage mapping technique for the implementation of protective domains. *Software practice and experience* 4,3 (september 1974).

Walker 74 : R.Walker. The structure of a well-protected computer. PhD. Thesis. *Cambridge University, GB.* (1974).

Wulf 75 : W.A.Wulf. Reliable hardware software architecture. *Sigplan notice*, 10,6 (1975).