• Aucun résultat trouvé

Composants d’exécution

La bibliothèque KORTEXfournit des composants permettant la virtualisation et la gestion le pro-

cesseur. Ces composants peuvent être utilisés par les systèmes nécessitant l’exécution de plusieurs fils d’exécution. De nombreux autres composants requièrent la présence de fils d’exécution. C’est par exemple le cas pour la pile de protocole que nous verrons à la section 5.5. Ces composants sont im- plantés selon le modèle de ressources vu à la section 3.2.4 qui lui-même est issu de ReTINA [ReTINA 1999].

5.4.1 Fils d’exécution & ordonnancement

Les composants d’ordonnancement permettent les opérations usuelles sur les fils d’exécutions ; création, destruction, mais aussi la possibilité d’attendre sur une condition et d’en être informé. Les fils d’exécution ne sont que des registres du processeur et ne fournissent pas par exemple de pile d’exécution, c’est à l’utilisateur de la définir si elle est requise par son langage de programmation. Si les fils d’exécution ne s’exécutent pas dans le même espace d’adressage, l’ordonnanceur effectue aussi les opérations requises par les changements d’espaces d’adressage.

Fils d’exécution

L’interfaceThreaddonnée à la figure 5.9 représente l’abstraction d’un fil d’exécution. Cette in- terface offre deux méthodes qui permettent de manipuler un fil d’exécution. Tout d’abord, la méthode

5.4. Composants d’exécution 97 initial du fil d’exécution. Ce contexte correspond à celui vu à la section 5.1. Ce contexte est initialisé avec la valeur initiale des registres, par exemple le pointeur d’instruction contient l’adresse de la mé- thode ou débute le fil d’exécution, et les registres r3 à r13 contiennent les arguments. Deuxièmement, la méthodectxrécupère durant l’exécution le contexte associé au fil d’exécution.

interface Thread extends AbstractResource { void run(Context ctx);

Context ctx(); }

FIGURE5.9 – Interface d’un fil d’exécution

L’implantation de cette interface dépend de l’ordonnanceur. Il n’y a pas de code de composant autonome pour les fils d’exécution. Le code de composant des fils d’exécution est intégré aux ordon- nanceurs qui sont présentés à la section ci-dessous.

Ordonnanceurs

L’interfaceScheduler donnée à la figure 5.10 est utilisée pour l’ordonnanceur qui réalise la gestion du processeur. Elle crée desThread, c’est donc une usine qui étendResourceFactory. La méthodenewThread est utilisée pour créer de nouveaux fils d’exécution. Elle prend en argu- ment l’espace d’adressage dans lequel va s’exécuter le nouveau fil d’exécution. Elle prend aussi la priorité du fil d’exécution. En fonction de l’implantation, cet argument peut ne pas être utilisé. La méthodedestroyThreadpermet la destruction du fil d’exécution donné en paramètre. Les mé- thodesgetThreadetgetSpacepermettent respectivement d’obtenir le fil d’exécution et l’espace d’adressage courant.

Le reste des méthodes de l’interfaceSchedulerréalise la synchronisation des fils d’exécution. La méthodeyield permet au fil d’exécution courant de libérer le processeur et déclencher sa ré- allocation à un autre fil d’exécution. La méthodewaitendort le fil d’exécution sur le verrou lock. Le fil d’exécution sera réveillé lors d’un appel par un autre fil d’exécution de la méthodenotifysur le même verrou lock. La méthodewaittoest similaire à la précédente, mais l’attente est limitée à un délai en milliseconde fixée par timeout.

Actuellement, un ordonnanceur coopératif et deux ordonnanceurs préemptifs sont implantés dans KORTEX. Le composant nommécooperative implantant l’ordonnanceur coopératif est basique et utilise le co-routinage5. Un changement de contexte est effectué uniquement lors d’un appel à

yieldpar le composant actif. Les composants implantant des ordonnanceurs préemptifs allouent le processeur aux fils d’exécution selon un quantum de temps fixé à 100 Hz. Pour un composant nomméroundrobin, l’allocation est circulaire, pour l’autre nommépriorityelle est basée sur la priorité des fils d’exécution. Pour de plus amples informations sur les politiques d’allocations du processeur, on consultera [Silberschatz et Galvin 1998].

5

Le co-routinage consiste à utiliser les procéduressetjmpetlongjmpoffertes par la librairie C. L’ordonnancement applicatif utilisant le co-routinage offre théoriquement de meilleures performances pour la gestion des fils d’exécution que pour un ordonnancement système. Mais cette implantation pose deux problèmes ; cela n’exploite pas les architectures multiprocesseurs, lorsqu’un fil d’exécution appelle le noyau il bloque tout le processus.

interface Scheduler extends ResourceFactory {

Thread newThread(Space space, int prio);

void destroyThread(Thread thread); Thread getThread();

Space getSpace();

void yield();

void wait(Lock lock);

int waitto(Lock lock, int timeout);

void notify(Lock lock); }

FIGURE5.10 – Interface d’un ordonnanceur

Les ordonnanceurs sont implantés en utilisant l’interfaceTrap des exceptions du POWERPC, voir la section 5.2.1. Les ordonnanceurs préemptifs sont implantés simplement en installant un traitant d’exception temporelle, en fait un decrémenteur sur le POWERPC. À chaque exception temporelle, l’utilisation de la méthode SetContext met en place le contexte minimum du fil d’exécution à activer qui sera restauré à la fin du traitant.

5.4.2 Processus

Le concept de processus identifie toutes les ressources utilisées par une application ; espaces d’adressage, fils d’exécution, les fichiers ouverts, etc. Actuellement, KORTEXn’implante pas de com- posant offrant le concept de processus. Seule la notion de fils d’exécution s’exécutant dans un espace d’adressage existe.

Chargeur d’application

Le seul composant relatif à la gestion des processus offert par KORTEX est un chargeur d’ap-

plication. Ce composant lance une nouvelle application à partir d’un fichier contenant un exécutable au format ELF [TIS 1993]. Ce composant requiert la mémoire paginée pour pouvoir mettre en place l’espace d’adressage de l’application. Ce composant requiert aussi un ordonnanceur permettant de lancer le fil d’exécution initial de l’application.