L’actualité de l’OAMP
Interruptions
18/12/08

 

Interruptions

Plan

Problèmes à résoudre

Définitions
   Evénements
   Synchrone et asynchrone

Programmation par événements
   Utilité des interruptions
   Classes d'interruptions

Prise en compte d'une interruption
   Déclenchement d'une interruption
   Masquage d'une interruption
   Contexte
   Traitement d'une interruption
   Codage d'une interruption ; Hiérarchisation
     Interruption chaînées
     Niveaux d'interruption
     Niveaux et sous-niveaux

Micro-interruptions


Problèmes à résoudre

Les interruptions ont été définies pour faire face à certaines situations dans lesquelles un programme est en cours de traitement, et une situation nouvelle, extérieure au programme, nécessite un traitement urgent. Dans la vie courante, on peut trouver une situation de ce genre, lorsque vous lisez un livre, et que le téléphone sonne. Si vous ne posez pas votre livre assez rapidement, le téléphone s'arrêtera de sonner, et vous ne saurez pas qui vous appellait. La bonne façon de faire consiste à poser le livre après y avoir mis un marque-page, a décrocher le téléphone, puis une fois la conversation terminée, poser le téléphone, reprendre le livre et continuer la lecture à l'endroit où vous aviez mis la marque.

Ce comportement habituel va se traduire assez fidèlement dans la machine, comme nous le verrons plus loin. Dans l'immédiat, nous allons considérer quelques situations dans lesquelles les interruptions vont rendre des services :

Définitions

Evénements

Un événement est l'apparition d'une situation nouvelle, non directement liée à l'activité en cours. Les exemples données ci-dessus sont informels. Dans une machine, il faut représenter l'événement par des signaux électriques particuliers. C'est le mécansime des interruptions qui va le représenter.

Exemple : décision de l'opérateur d'arrêter le programme en cours.

Remarque : le terme événement possède un autre sens dans certains langages de programmation ou systèmes ; il s'agit alors d'une variable représentant une intervention extérieure. Par exemple, les événements font partie du langage PL/1.

Synchrone et asynchrone

On qualifie de Synchrone un événement qui est inscrit dans le texte (code) du programme ; il est provoqué par une instruction particulière, ni par la précédente ni par la suivante. Les erreurs telles que division par zéro font partie de cette catégorie. Bien que le traitement au niveau du matériel soit le même, cette classe est nommée exceptions. Ce terme indique bien qu'il s'agit d'un comportement du programme lui-même, mais qui présente un aspect exceptionnel.

Est Asynchrone ce qui ne dépend pas des instructions en cours. L'intervention de l'opérateur est asynchrone ! Ce qui est asynchrone peut se produire à n'importe quel endroit du programme, et ne dépend pas des instructions. Lorsque l'utilisateur tape un caractère sur le clavier, le périphérique (clavier) déclenche un événement en direction de la machine.

Traitement des événements

En monoprogrammation, la machine est dédiée totalement au programme en cours ; les événements peuvent se traiter de façon simple :

Attente de la fin d'une E/S : il suffit d'écrire une boucle de test de l'état du périphérique après le lancement de l'opération ; la boucle continue tant que l'état du périphérique n'indique pas la présence d'un caractère ;

Erreur de programmation : par exemple après une division, on insère une instruction de test qui vérifie que l'opération s'est bien passée (une division par zéro est intermédiaire entre synchrone et asynchrone : elle ne peut se produire que sur une instruction de division, mais en général cette instruction se passe bien...

On remarque toutefois qu'il est nécessaire de prévoir toutes les possibilités et de les inclure dans chaque programme ! Ceci est parfois réalisé par les compilateurs, mais cette méthode accroît beaucoup la longueur du code produit..

Exemples

Système sans interruptions

L'apple ][, ancêtre des micro-ordinateurs, fonctionnait sans interruptions, bien que le processeur 6802 comportait les mécanismes indispensables.

Système intermédiaire

Le Macintosh a longtemps utilisé une présentation intermédiaire : au niveau du système, les interruptions étaient gérées normalement ; leur traitement par le système donne lieu à deux types de réponses :

- intervention immédiate du système (au cours d'une E/S disque par exemple) ;

- alerte de l'utilisateur qui doit prendre en compte lui-même le traitement (récupération d'un caractère sur le clavier par exemple) ; dans ce dernier cas, l'interruption est transformée en événement, rangé dans une file d'attente où l'utilisateur ira le chercher. L'interruption est donc traitée en asynchrone, alors que l'événement auquel elle donne naissance sera traité de manière synchrone, au moment où le programme le décide.

Si plusieurs caractères sont tapés rapidement, ils sont stockés dans la file d'attente, et ne seront donc pas perdus.

Programmation par événements

Une généralisation des événements (externes) permet en outre de communiquer entre modules du système, entre système et utilisateur, ou entre deux utilisateurs. On crée ce qu'on appelle des événements logiciels.

Evénements logiciels

Ce sont des événements qui n'ont rien à voir avec l'environnement de la machine ; ils sont créés par un programme qui désire communiquer avec un autre :

Lorsque l'utilisateur déplace une fenêtre sur l'écran, le système place dans la file des événements de mise à jour ;

le programme de l'utilisateur peut ensuite récupérer ces événement et prendre les dispositions pour redessiner la fenêtre.

Cette technique de programmation est appelée programmation par événements. Le cœur du programme est une boucle (dans le module B sur le dessin) qui teste la file d'événements, et exécute les actions correspondantes.

Une application peut demander à une autre de lui transmettre des données, ou de lancer l'impression d'un document... par l'intermédiaire du système, elle peut démarrer une application.

Utilité des interruptions

Recouvrement des E/S et du calcul

Sans interruptions, le processeur doit périodiquement interroger le périphérique :

Si la machine doit gérer de nombreux périphériques, elle passe son temps à les interroger et ne peut plus calculer...

Les interruptions, au contraire, permettent à un programme de tourner pendant qu'un périphérique travaille ; lorsque l'E/S sera terminée, le périphérique préviendra le processeur. Ceci se manifeste différemment pour les périphériques lents comme un clavier, ou rapides comme un disque. Le premier échange un caractère à la fois (son tampon ne contient qu'un caractère, s'il n'est pas vidé rapidement avant l'arrivée du caractère suivant, le premier sera perdu) ; le second échange des blocs d'information directement avec la mémoire, et le processeur ne sera prévnu par une interruption qu'à la fin de l'échange du bloc.

Présentation des programmes

Une autre différence importante entre les deux méthodes est dans la présentation des programmes de traitement :

Classes d'interruptions

Le traitement associé à une interruption d'E/S n'est pas du tout le même que celui concernant une division par zéro. Il faut donc que l'interruption indique la cause à laquelle elle est associée. Il est donc nécessaire de créer des classes d'interruptions, permettant d'associer à chacune le traitement qui convient. On va d'abord considérer une distinction entre celles concernant les E/S (externes) et celles produites par le fonctionnement de la machine elle-même.

Interruption externes

Elles proviennent de l'extérieur de la machine, donc d'unités périphériques. Elles servent à gérer le comportement des périphériques, qui sont commandés par le processeur :

les IT (interruptions) de fin d'échange produites par un canal (processeur spécialisé d'E/S) ; elles résultent d'une demande préalable d'E/S ;

les IT de présence de donnée, par exemple l'apparition d'un caractère sur un clavier ;

les IT de défaut, comme la fin de papier sur une imprimante, ou bien l'ouverture du capot d'une unité de disque (qui provoque l'arrêt de l'unité) pour changement de cartouche.

Interruptions internes

Celles-ci sont produites par le fonctionnement de la machine elle-même ; c'est une façon de communiquer de l'information entre deux organes différents, ou d'activer un module système particulier.

Dans cette catégorie :

Horloge : elle permet de laisser tourner un programme normalement jusqu'à expiration d'un délai fixé à l'avance ;

Erreurs : essentiellement causées par l'arithmétique ;

Débordements (Overflow) concernant les entiers, les mantisses ou exposants des flottants...

Protection mémoire : adressage en dehors de la mémoire, zone interdite en mode esclave...

Code opération inconnu : on tente d'exécuter une instruction dont le code n'existe pas (c'est souvent une donnée...).

Attention : sur la famille de microprocesseurs MC68000, cette interruption était utilisée pour appeler des procédures système (A Traps) ; elle est considérée comme erreur seulement s'il n'existe pas non plus de procédure associée.

Dans d'autres machines, cette interruption permet de gérer des options : opérateur flottant cablé en option, s'il n'est pas présent, les instructions flottantes sont simulées par des procédures activées par l'IT.

Instruction privilégiée exécutée en mode esclave ;

Pannes matérielles comme défaut de parité en mémoire, ou coupure de courant impliquant la sauvegarde immédiate des données importantes sur disque en utilisant les condensateurs qui assurent une autonomie de quelques secondes.

Interruptions logicielles

Sur certaines machines, une instruction spéciale provoque une interruption (notez que cette interruption est alors strictement synchrone, ce qui est paradoxal...) ; la prise en compte de cette interruption provoque un passage en mode maître, et l'exécution d'une routine de traitement particulière ; ensuite, le contrôle peut (mais pas forcément) revenir au programme qui a provoqué l'IT.

Il s'ensuit que cette IT logicielle est presque équivalente à un appel superviseur (SVC) ; toutefois, la reprise du programme qui a appelé n'est pas garantie immédiate.

Distinction des processus

On distingue deux catégories de processus :

Il existe donc deux mécanismes d'activation des tâches différents, implémentant des algorithmes distincts.

Ordonnanceur

L'ordonnanceur est l'organe de la machine chargé de décider à quel processus de calcul sera alloué le processeur.

L'ordonnanceur peut être entièrement cablé ; il est en général en partie programmé pour faciliter le choix de l'algorithme.

Il est activé par certaines instructions qui décident de restituer le processeur :

Les instructions sur sémaphores, lorsqu'elles sont cablées, activent directement l' ordonnanceur.

Prise en compte d'une interruption

La prise en compte d'une IT consiste à passer du programme en cours, qui est interrompu, à l'exécution d'un module du système.

En fin de traitement, il faut revenir à la tâche interrompue, ou à une autre plus prioritaire.

Ce passage ne se fait pas à l'instant précis où l'IT se produit pour plusieurs raisons :

Le déclenchement d'une interruption étant réalisé par cablage, celui-ci doit permettre de :

Déclenchement d'une IT

Le traitement d'une IT est réalisé par des instructions, donc utilise les mêmes organes (registres, processeur...) que le programme interrompu. Il n'est donc pas possible de glisser le traitement de l'IT au milieu de l'exécution d'une instruction (sauf cas particulier des micro-interruptions).

- IT provenant de l'extérieur : elle est traitée à la fin d'une instruction ;

- IT erreur : c'est l'instruction en cours qui produit l'interruption, dont le rôle est justement de suspendre le calcul ! il ne faut donc pas attendre la fin de l'instruction, et donc le processeur doit être capable de suspendre l'instruction en cours sur certaines conditions ;

- instruction inconnue : le code ne correspond à rien dans le processeur (en général, le registre pointeur d'intruction contient une adresse erronée, et désigne une donnée ! ) ; le processeur n'exécute pas, positionne l'IT, et n'incrémente pas le compteur ordinal ;

- instruction privilégiée, exécutée en mode esclave ; abandon de l'instruction en cours sans incrémentation du compteur ordinal ;

- instructions très longues : MOVE par exemple dont la durée dépend du nombre d'octets à déplacer ; c'est un raccourci offert par le processeur à la place d'une boucle de quelques instructions ; le temps d'exécution est bien moins long. Ce genre d'instruction ne se présente pas sur les processeurs actuels de type RISC. Ces instructions travaillent sur les registres mêmes du processeur ; équivalentes à des séquences de programme, il est possible de les interrompre en cours de calcul, en des points particuliers ;

- interruptions masquées : il est en général possible de masquer les interruptions par programme ; une IT masquée est positionnée, mais non prise en compte. Lorsqu'elle sera démasquée (toujours par programme) elle sera prise en compte normalement ; son traitement n'aura été que différé.

Masquage

Le masquage des interruptions est réalisé par un registre Masque dont les bits correspondent aux différents types d'IT ; tout bit à 1 diffère le traitement des IT correspondantes.

Une instruction privilégiée, permet d'échanger le contenu du registre Masque et d'un registre programmable quelconque dans lequel on a préparé le nouveau masque ; un second échange permet de restaurer l'ancien Masque.

Contexte

En général, le programme interrompu doit être repris rapidement après traitement de l'IT. Tout se passe donc comme si ce traitement était réalisé par un appel de sous-programme.

Un appel de procédure consiste à sauvegarder le compteur ordinal, pour autoriser le retour ; la procédure appelée utilise des registres, et donc sauvegarde leur contenu avant de les modifier, pour que l'apppelant les retrouve inchangés.

Transfert de contrôle ⇒ modification des registres ⇒ sauvegarde

Le déclenchement d'une interruption doit faire la même chose, mais de manière automatique pour la rapidité.

D'autre part, l'adresse à laquelle le traitement (celui de l'IT) doit continuer est indépendante du programme en cours ⇒ il faut charger le registre Pointeur d'instruction.

On prévoit alors un mécanisme de sauvegarde général de tous les registres programmables de la machine, dans une zone mémoire système.

Pouir activer, le programme qui doit maintenant s'exécuter, il faut placer dans le registre pointeur d'instruction l'adresse de l'instruction à exécuter en premier. si ce processus a déjà été exécuté, ce sera tout simplement l'instruction suivante. Son adresse a dû être sauvegardée lors de sa dernière interruption, et doit se trouver dans le contexte. De même, le programme relancé doit retrouver les valeurs qu'il a laissées dans les autres registres (pointeur de pile, registres de travail, registres de base...). Donc il fa ut charger son contexte en totalité, tel qu'il a été sauvé lors de l'arrêt.

Pour placer les contextes en mémoire, on distingue deux méthodes :

dans une zone spécifique de l'IT (PST) adresses réservées, connues a priori de ce fait, adressage efficace
dans la pile du système calcul si on veut savoir où se trouve le contexte d'un programme suspendu ; fixe a priori l'ordre de retour

Après sauvegarde du contexte de la tâche interrompue, il faut charger celui de la tâche à activer. L'ensemble de l'opération se nomme changement de contexte.

Traitement d'une IT

Tâches

On appellera Tâche un programme (ensemble d'instructions) ET l'ensemble des informations qu'il traite à un instant donné ; une tâche est définie par le contenu de la mémoire qu'elle occupe, mais aussi par le contenu des registres de la machine, dans lesquels elle stocke des valeurs en cours de traitement.

Lorsqu'une tâche est suspendue, le contenu des registres (son contexte) est sauvé en mémoire ; les registres sont alloués à une autre tâche ; la tâche suspendue est alors caractérisée par le contenu de la mémoire qu'elle possède, et de son contexte.

Pendant le calcul (phase 1), les registres contiennent les valeurs que le programme utilise. Lorsque l'interruption se produit (en 2) elle est notée dans le registre interruption. A la fin de l'instruction qui était en cours losrque l'interruption s'est produite, ou bien lorsque ce type d'interruption est démasqué, l'interruption est prise en compte (phase 3). Pour cela, le contenu des registres est sauvegardé dans la PST du processus interrompu (4), puis le contexte de la tâche de traitement de l'interruption est chargé dans les registres (5). Ces deux opérations constituent l'échange de contexte. Lorsque l'échange de contexte est terminé, le registre pointeur d'instruction contient l'adresse de la prochaine instruction à exécuter dans le processus de traitement de l'interruption (flèche 6) ; c'est cette instruction qui va être exécutée.

Lorsque le traitement de l'interruption sera terminé, si le processus interrompu peut être poursuivi, un échange de contexte en sens inverse doit être fait. A la fin de cet échange, le registre pointeur d'instruction contiendra l'adresse suivant la dernière exécutée. Les autres registres retrouvent aussi la valeur qu'ils avaient au moment de la prise" en compte de l'interruption. Le programme reprendra donc comme si l'interruption n'avait pas eu lieu. Pour lui, elle est totalement transparente.

La situation se complique lorsque cette tâche est rejetée de la mémoire (par le mécanisme de Va-et-Vient par exemple) ; son code est renvoyé sur disque, mais son contexte reste présent en mémoire (en particulier la valeur de son registre pointeur d'instruction P). Dans ce cas, la tâche système qui a traité l'interruption doit vérifier si la tâche à réactiver est toujours présente en mémoire, et si ce n'est pas le cas, au lieu de relancer cette tâche elle-même, il doit relancer une autre tâche système de rechargement de la tâche suspendue (Swapp In). C'est cette dernière qui passera le contrôle (encore par un échange de contexte bien sûr) à la tâche utilisateur interrompue après chargement.

Codage des IT ; Hiérarchisation

Nous avons vu qu'on distinguait plusieurs types d'interruptions, selon la cause qui les a produites. Par conséquent :

Urgences différentes ⇒ hiérarchisation du traitement ⇒ codage matériel de la hiérarchie

En effet, le traitement d'un caractère provenant d'un clavier peut attendre qu'un bloc d'information provenant d'un disque rapide soit traité, sans grand risque de perdre le caractère.

Interruptions chainées

Les périphériques sont chainés ; une IT demandée par un périphérique éloigné doit transiter par les plus proches, à leur bon vouloir, i.e. si ceux-ci n'ont pas eux-même d'IT à transmettre. La hiérarchie des IT est donc assurée par la chaîne.

Si l'UC est en train de traiter une IT provenant du périphérique 1, et que le périphérique 2 plus proche désire appeler, il peut le faire, et sa demande interrompt donc la précédente. C'est donc un mécanisme prioritaire.

Par contre, le traitement d'une IT provenant de P1 ne peut pas traverser P2, dont l'IT n'a pas encore été acquittée.

Par le chaînage, les priorités sont toutes différentes. On placera un disque au début de la chaîne (proche de la machine), et un clavier loin.

Niveaux d'interruptions

Le traitement des IT est différent selon la cause :

Séparation logicielle : UNE routine unique, appelée sur IT, analyse la cause et appelle un sous-programme spécialisé. Cette méthode est coûteuse, car elle consiste à mélanger toutes les interruptions au moment où elles se produisent, puis à les séparer pour les traiter.
Séparation matérielle : Dispositif cablé qui active directement des modules dinctincts ⇒ beaucoup plus rapide.

 

Niveaux et Sous-Niveaux

Le codage à Niveaux et Sous-Niveaux est un compromis efficace. Il consiste à regrouper les interruptions qui ont une même cause, mais des sources différentes. La cause définit le niveau, la source définit le sous-niveau. Par exemple, la cause étant un appel de périphérique, la source indique le périphérique qui appelle.

Par contre, pour passer du traitement d'un niveau à un autre, il faut un changement de contexte.

Deux instructions spéciales sont associées à ce traitement :

ACK (Acknowledge) permet de remettre à 0 le sous-niveau en cours de traitement ; la routine de traitement du niveau fera donc une boucle, tant que ACK ne la bloquera pas.

ACQ acquitte le niveau ; elle n'est exécutée que lorsque tous les sous-niveaux ont été traités. Cette instruction, si aucun sous-niveau n'est enclenché, provoque un changement de contexte ;

Micro-interruptions

Certains événements de bas niveau ne nécessitent pas toute la puissance de l'UC pour leur traitement ; une sauvegarde de contexte partiel seulement est effectuée, et la reprise est très rapide ; l'ordonnandeur n'est pas utilisé en fin de traitement.

Les micro-interruptions sont des interruptions au niveau de la micro-machine, c'est-à-dire à l'intérieur du processeur.