Extension d'un noyau de processus légers
Etape 2 - Comptes a rebours
1. Que veut-on fournir
On souhaite enrichir le noyau en ajoutant des fonctions de base de
gestion du temps. Plus précisément, on veut réaliser
:
-
une horloge, qui donne la date depuis le lancement du systeme selon une
base de temps donnée (tick)
-
des compteurs à rebours (c'est a dire des réveils) qui, une
fois chargés avec une certaine valeur, se décrémentent
automatiquement à chaque tick horloge. Lorsqu'un compteur à
rebours a pour valeur 0, alors il exécute une action donnée.
Le principe est d'utiliser un dispositif assimilé à un quartz,
pouvant engendrer périodiquement une interruption (tick horloge).
2. Interface à réaliser
Les interfaces qui devront être fournies sont les suivantes. Ces
interfaces sont bien entendu données à titre indicatif.
Interface du module Quartz
Interface du module TimeService
/* Initialize the module */
void initTimeService();
/* Initialize the initial date */
void initDate (int initialDate);
/* return the current date */
int getDate();
/* return the initial date */
int getInitialDate();
/* Attach a handler to a given counter */
/* the handler is supposed to receive an int as a parameter */
void attachHdlerToCounter (
int counter,
void (* handler) (int));
/* starts a counter*/
void startCountDown (
int counter,
int value);
/* stops a counter */
/* return the current counter's value */
int stopCountDown (
int counter);
3. Controle des compteurs à rebours
Les compteurs à rebours ont un fonctionnement qui respecte un automate
d'état. Il est tres important de tenir compte de cette contrainte
dans le code source des fonctions fournies par le module TimeService, et
donc de vérifier que la pré-condition d'exécution
associée à toute fonction est bien respectée.
L' automate possede deux états dénommés COUNT (compteur
actif) et NO_COUNT (compteur inactif). Le comportement de cet automate
est défini comme suit.
Lancement :
Traitant : vide
Décompte : 0
Etat : NO_COUNT
NO_COUNT :
<AttachHandlerToCounter(c, h)>
Traitant : h
Etat : NO_COUNT
<StartCountDown(c, v)>
Décompte : v avec v > 0
Etat : COUNT
<autre>
Erreur
COUNT:
<StopCountDown>
Etat : NO_COUNT
<Tick>
Décompte -=1
Si décompte == 0 alors exécuter Traitant
Etat : NO_COUNT
<autre>
Erreur
4. Principes de mise en oeuvre
Sont ci-apres brievement décrits les principes de mise en oeuvre
des modules Quartz et TimeService.
4.1 Dates
On accumule dans une variable Date les ticks qui se produisent. La
variable Date est initialisée avec une valeur initiale qui représente
la valeur de date au lancement du systeme.
4.2 Compteur à rebours
A chaque tick, tout compteur est décrémenté ;
s'il devient nul, le handler associé est executé. La période
de décompte doit être grande par rapport à la durée
d'exécution de la fonction associée au quartz. Dans l'autre
cas, le processeur peut soit ne pas suivre le rythme, soit passer la majeure
partie de son temps dans cette fonction.
Pour ces deux fonctionnalités, on a besoin d'effectuer un traitement
particulier a chaque tick horloge (incrémentation de la date, décrémentation
des compteurs, etc). Le quartz sera simulé en utilisant le
Timer virtuel d'Unix (qu'utilise la version initiale du noyau pour gérer
le quantum de temps-partagé).
Pour comprendre les principes d'utilisation du timer virtuel d'Unix,
on pourra regarder la maniere dont est géré le temps partagé
dans la version initiale du noyau fourni.
Etant donné que le timer virtuel d'Unix est maintenant utilisé
pour gérer la date et les comptes à rebours, il ne peut plus
servir a gérer le temps partagé comme dans la version initiale
du noyau. Le temps partagé doit alors être pris en charge
par un compteur à rebours particulier.
Contraintes relatives à la synchronisation
On prendra soin de rendre les fonctions atomiques des lors que celles-ci
manipulent des structures de données critiques du noyau.
5. Travail demandé
Il est demandé de :
-
Réaliser le module TimeService
-
Tester le module, en réalisant des jeux de tests mettant en jeu
des exécutions concurrentes de toutes les fonctions réalisées.