Ravi
Welcome
Documentation
Documentation
About Ravi
Documentation
Introduction
Premiers pas avec Ravi
ravitool
Scheme Tutorial
Objets Scheme
Le shell ravi
Starting Ravi
Le module trace
Les ports d'E/S
The C Parser
load, require, modules
Système d'interruptions
Scheme compiler
C++ mode
Generating C++ Modules
La déclaration struct
Le type "C-object"
More information
Installation

[PREV][SUIV]

Système d'interruptions

Un système d'interruptions est un outil technique crucial pour qui veut programmer du contrôle; or, le contrôle est un objectif majeur du projet Ravi. Il fallait donc concocter une système d'ITs à la hauteur donc voici le début.

Question évidente: à quoi ca sert dans l'immédiat? Réponse: il y a dès maintenant de quoi faire du multi-tasking non-préemptif. C'est important pour des interfaces du style xforms, tk; pour une gestion sophistiquée du ^C. Prochainement il y aura les interruptions timer.

Dans le fichier ~lux/Ravi/Demo/FORMS/xftools.scm on trouve un exemple convaincant des nouvelles possibilités!

Principe

Au coeur de Ravi se trouve une machine virtuelle qui, comme toute machine qui se respecte, exécute des instructions. Entre deux instructions il y a un test systématique: si une interruption est intervenue, il y a déroutement vers le gestionnaire (handler) associé.

Ca parait simple, mais c'est un principe très fort: les gestionnaires étant écrits en Scheme, un programme Scheme peut interrompre un autre à un rythme de l'ordre de 1MHz (vitesse de la machine virtuelle).

Les interruptions sont :

  • error-signal 1 {le bit 2 est réservé en interne}
  • alarm-signal 4
  • break-signal 8
  • poll-signal 256
  • user1-signal 512

Chaque type d'interruption peut être masqué ou démasqué.

Chaque type d'interruption correspond à une espèce d'événement; lorsque l'événement arrive, et que l'interruption est démasquée, l'interruption est traitée par appel à son gestionnaire. Lorsque le gestionnaire termine, la suite du programme "interrompu" est reprise (sauf action de contrôle explicite de la part du handler).

Le plus souvent, un gestionnaire est appelé en "mode protégé" dans lequel toute interruption est masquée; cela implique en particulier qu'il ne peut pas être interrompue par un ^C.

Tout cela est assez expérimental, et quelques fonctions permettent des traitements fins:

  • vm-mask-signal
  • vm-unmask-signal
  • vm-set-granularity
  • vm-set-opsw

Le module interrupt contient un certain nombre de fonctions permettant d'utiliser les éléments décrits par la suite.

Comme chaque interruption présente un cas particulier, on va expliquer au cas par cas, à commencer par les signaux les plus récents.

Le signal 256 : poll-signal

Ce signal a été créé pour permettre une interaction continue avec xforms. Il permet très généralement une interaction continue avec un processus/programme externe à Ravi. Le principe est simple : toutes les K instructions, on appèle le gestionnaire de scrutation, lequel est défini par

(set-poll-handler! th)

th étant une fonction sans arguments. Par exemple,


 (set-poll-handler! (lambda () (display "coucou\n")))
 (set-poll-handler! fl_check_forms)

Le deuxième exemple (simplifié) est significatif: ca permet une opération non-bloquante, ici le maintien en activité d'une interface xforms, pendant l'exécution d'un programme.

L'exécution de th se fait en mode protégé. Cela est nécessaire, mais entraine des conséquences désagréables : si, via l'interface xforms, le handler lance un nouvelle exécution Scheme, on n'a plus le contrôle! C'est un vrai problème, qui a nécessité l'introduction d'une autre interruption:

Le signal 512 : user1-signal, et la fonction vm-set-opsw

(set-user1-handler! th)

met en place un gestionnaire pour cette interruption. Ce qui est original ici, c'est le mécanisme de déclenchement de l'IT. Comme le but est de lancer un traitement depuis une section protégée, on ne peut simplement déclencher un signal!

La fonction (vm-set-opsw signal)positionne le ProgramStatusWord du processus interrompu, et signale une interruption. Dès que le contrôle revient à ce processus, cette interruption se déclenche. Bien entendu, l'exécution du gestionnaire th se fait en mode non-protégé.

D'une facon très générale, la fonction vm-set-opsw permet de contrôler un processus, par exemple depuis une interface graphique; elle permet par exemple de réaliser un bouton "interrupt".

La fonction

(vm-set-granularity K)

permet de modifier la valeur de K dont il a été question plus haut, à savoir le nombre d'instructions entre 2 IT de type poll-signal. La fonction a pour valeur l'ancienne valeur de K.

La fonction

(init-it)

active le mécanisme du poll-signal; par défaut, au départ de Ravi ce signal ne se déclenche pas.

================================================

Les autres signaux.

Le signal 1 : error

Le signal d'erreur est levé par les fonctions C/C++; en particulier, toute fonction "utilisateur" peut provoquer une erreur, et éviter ainsi que l'exécution continue.

A présent, ce signal est traité par une fonction non-exporté de l'interpréteur Scheme, handler0, qui provoque une sortie non-locale. Il y a ici du potentiel de faire plus!

Le signal 4: alarm-signal

en cours d'implémentation

Le signal 8 : break-signal

C'est le ^C bien aimé. Il y a 2 gestionnaires pour ce signal:

  • le gestionnaire standard qui coupe l'exécution en cours. Il s'appele breakhandler et fait partie de l'interpréteur.

  • le module interrupt met en place un gestionnaire qui s'appèle break-handler et qui ouvre un nouveau "shell d'interaction", un nouveau "runlevel"- bref, c'est une boucle read-eval-print classique dont on sort de 2 facons:

    (resume) reprend l'exécution du programme interrompu
    (error) provoque une erreur dans le programme interrompu

=============================================