Previous Up Next

5  Ordonnancement sur interruptions

L’ordonnancement développé jusque ici est un ordonnancement avec partage volontaire du processeur. Un contexte passe la main par un appel explicite à yield(). Nous allons maintenant développer un ordonnancement préemptif avec partage involontaire du processeur : l’ordonnanceur va être capable d’interrompre le contexte en cours d’exécution et de changer de contexte. Cet ordonnancement est basé sur la génération d’interruptions. Une interruption déclenche l’exécution d’une fonction associée à l’interruption (un gestionnaire d’interruptions ou handler). Le matériel sur lequel nous travaillons permet de définir la fonction handler() qui sera associée à l’interruption TIMER_IRQ

IRQVECTOR[TIMER_IRQ] = handler

Cette interruption est remontée périodiquement du matériel.

La primitive init_hardware() permet d’initialiser le matériel ; elle doit être invoquée pour démarrer la simulation du matériel, et donc la génération des interruptions.

Les deux primitives irq_disable() et irq_enable() devront être définies. Elles permettrons de délimiter des zones de code devant être exécutées de manière non interruptible.

On trouvera plus de détails sur le simulateur de matériel que nous utiliserons, et en particulier un exemple d’utilisation du gestionnaire d’interruptions périodiques à www.lifl.fr/~marquet/ens/hw/.

La nouvelle interface que va fournir notre ordonnanceur est la suivante :

int create_ctx(int stack_size, func_t f, void *args);
void start_sched(); 

La fonction start_sched() va installer les gestionnaires d’interruptions et initialiser le matériel. Elle se contente d’un appel à init_hardware() et de l’initialisation du tableau IRQVECTOR.

Notre ordonnanceur est maintenant préemptif, il reste à isoler les sections critiques de code ne pouvant être interrompues par un gestionnaire d’interruptions.


Exercice 10
   Ajoutez les appels nécessaires à irq_disable() et irq_enable() dans le code de l’ordonnanceur.

Previous Up Next