Chapitre 3 : Les mécanismes de base


La gestion de l'unité centrale

Exemple 1 - La gestion de l'unité centrale

Enoncé
On considère le cas d'une unité centrale illustrée par le schéma suivant :

Cette unité centrale possède :

Sur le schéma, nous distinguons aussi deux zones localisées dans la mémoire centrale :

Comme nous l'avons déjà dit plus haut, tous les sous programmes de traitement d'interruption commencent par la sauvegarde du contexte du processus courant et se terminent par la restauration du contexte du processus chargé. Nous proposons donc d'écrire les fonctions permettant d'assurer la gestion correcte de cette unité centrale :

Solution :

UC_SAUVEGARDER :
Cette fonction sera appelée au début de chaque sous-programme système ; son rôle est de sauvegarder, d'une part, les registres de travail de l'unité centrale qui correspondent au contexte «unité centrale» du processus interrompu et de changer, d'autre part, la pile pointée par SP pour passer à la pile système. Le traitement proprement dit du sous - programme système peut se faire alors en utilisant cette dernière pile. D'où l'algorithme suivant :

UC_SAUVEGARDER( )
{
	Sauvegarder les registres de travail dans la pile du processus courant ;
	Sauvegarder l'adresse de la pile du processus courant ;
	Changer de pile : passer à la pile système ;
}


UC_SAUVEGARDER( )
{
	/*Sauvegarder les registres de travail dans la pile du processus courant*/
	empiler(R0) ;
	empiler(R1) ;
	empiler(R2) ;
	empiler(R3) ;
	empiler(R4) ;
	empiler(R5) ;

	/*Sauvegarder l'adresse de la pile du processus courant*/
	ad_pile_courante = SP ;

	/*Changer de pile : passer à la pile système*/
	SP = ad_pile_système ;
}

Cette solution est fausse. Pouvez - vous déceler l'erreur ?

Deuxième tentative :

UC_SAUVEGARDER( )
{
	/*Récupérer l'adresse de retour de la pile courante* /
	ad_retour = depiler() ;

	/*Sauvegarder les registres de travail dans la pile du processus courant*/
	empiler(R0) ;
	empiler(R1) ;
	empiler(R2) ;
	empiler(R3) ;
	empiler(R4) ;
	empiler(R5) ;

	/*Sauvegarder l'adresse de la pile du processus courant*/
	ad_pile_courante = SP ;

	/*Changer de pile : passer à la pile système*/
	SP = ad_pile_système ;

	/*Placer l'adresse de retour sur le sommet de la nouvelle pile*/
	empiler(ad_retour) ;
}


UC_RESTAURER :
Cette fonction sera appelée à la fin de chaque sous-programme système ; son rôle est de restaurer le contexte «unité centrale» du processus choisi A la fin du sous-programme système, l'unité centrale exécutera le processus restauré. Nous avons ici le même problème rencontré dans UC_SAUVEGARDER (à cause du changement de pile devant être effectué dans UC_RESTAURER) et par conséquent, nous devons effectuer les mêmes traitements à l'entrée et à la sortie de cette fonction. L'algorithme de cette fonction est donc :

UC_RESTAURER( )
{
	/*Récupérer l'adresse de retour de la pile courante* /
	ad_retour = depiler() ;

	/*Changer de pile : passer à la pile du processus à restaurer*/
	SP = ad_pile_courante ;

	/*Restaurer les registres de travail à partir de la pile du processus à restaurer */
	R5 = dépiler() ;
	R4 = dépiler() ;
	R3 = dépiler() ;
	R2 = dépiler() ;
	R1 = dépiler() ;
	R0 = dépiler() ;

	/*Placer l'adresse de retour sur le sommet de la nouvelle pile*/
	empiler(ad_retour) ;
}


UC_VIDER :
Le rôle de cette fonction est de «vider» l'unité centrale du processus courant devant être suspendu. Elle doit donc sauvegarder l'adresse de sa pile dans le champ prévu pour cela dans le descripteur du processus. En effet, la pile du processus a, peut être, évolué depuis son dernier chargement, et par conséquent la valeur de ce champ peut ne plus être à jour.

UC_VIDER(int	i)
{
	/*Sauvegarder l'adresse de la pile dans le descripteur de ce même processus*/
	desc[I].ad_pile = ad_pile_courante ;
}


UC_CHARGER :
Le rôle de cette fonction est de «charger» l'unité centrale par un nouveau processus qui va prendre le contrôle de l'unité central. Elle doit donc utiliser la valeur du champ «adresse pile» se trouvant dans le descripteur du processus.

UC_CHAGER(int	i)
{
	/*Récupérer l'adresse de la pile à partir du descripteur du processus*/
	ad_pile_courante = desc[I].ad_pile ;
}