Previous Up Next

6  Synchronisation entre contextes

On introduit un mécanisme de synchronisation entre contextes à l’aide de sémaphores. Un sémaphore est une structure de données composée

Le compteur peut prendre des valeurs entières positives, négatives, ou nulles. Lors de la création d’un sémaphore, le compteur est initialisé à une valeur donnée positive ou nulle ; la file d’attente est vide.

Un sémaphore est manipulé par les deux actions atomiques suivantes :

Deux utilisations sont faites des sémaphores :

Bien souvent on peut assimiler la valeur positive du compteur au nombre de contextes pouvant acquérir librement la ressource ; et assimiler la valeur négative du compteur au nombre de contextes bloqués en attente d’utilisation de la ressource. Un exemple classique est donné dans l’encart.

Le classique producteur consommateur

Une solution du problème du producteur consommateur au moyen de sémaphores est donnée ici. Les deux utilisations types des sémaphores sont illustrées.

#define N 100                         /* nombre de places dans le tampon */

struct sem_s mutex, vide, plein;

sem_init(&mutex, 1);                /* controle d'acces au tampon */
sem_init(&vide, N);                 /* nb de places libres */
sem_init(&plein, 0);                /* nb de places occupees */

void producteur (void)
{
  objet_t objet ;

  while (1) {
    produire_objet(&objet);           /* produire l'objet suivant */
    sem_down(&vide);                  /* dec. nb places libres */
    sem_down(&mutex);                 /* entree en section critique */
    mettre_objet(objet);              /* mettre l'objet dans le tampon */
    sem_up(&mutex);                   /* sortie de section critique */
    sem_up(&plein);                   /* inc. nb place occupees */
  }
}

void consommateur (void)
{
  objet_t objet ;

  while (1) {
    sem_down(&plein);                 /* dec. nb emplacements occupes */
    sem_down(&mutex);                 /* entree section critique */
    retirer_objet (&objet);           /* retire un objet du tampon */
    sem_up(&mutex);                   /* sortie de la section critique */
    sem_up(&vide);                    /* inc. nb emplacements libres */
    utiliser_objet(objet);            /* utiliser l'objet */
  }
}
  

Persuadez-vous qu’il n’est pas possible pour le producteur (resp. le consommateur) de prendre le sémaphore mutex avant le sémaphore plein (resp. vide).

Testez votre implantation des sémaphores sur un exemple comme celui-ci.

Ajoutez une boucle de temporisation dans le producteur que le changement de contexte puisse avoir lieu avant que le tampon ne soit plein.

Essayez d’inverser les accès aux sémaphores mutex et plein/vide; que constatez-vous ? Votre implémentation peut-elle détecter de tels comportements ?


Exercice 11
  
  1. En remarquant qu’un contexte donnée ne peut être bloqué que dans une unique file d’attente d’un sémaphore, étendez la structure de données associée à un contexte pour gérer les files d’attente des sémaphores.
  2. Donnez la déclaration de la structure de donnée associée à un sémaphore.
  3. Proposez une implantation de la primitive
    void sem_init(struct sem_s *sem, unsigned int val);
    

Exercice 12
   Proposez une implantation des deux primitives
void sem_down(struct sem_s *sem);
void sem_up(struct sem_s *sem);

Previous Up Next