Département INFormatique 
  CSC4508/M2 : Concepts des systèmes d'exploitation et mise en œuvre sous Unix


    Évaluation



Institut National des Télécommunications
Télécom INT 2è année

TP Noté CSC4508/M2 du 07/06/06

(Corrigés)

Modalités

Durée : 3 heures

Les trois questions sont indépendantes les unes des autres.

Le barême est donné à titre indicatif des poids entre les différentes questions. Seront notés :
  • La clarté du code,
  • Le fait que le code compile (sans warning),
  • Le fait que le code répond correctement à la question posée,
  • Le fait que le retour de chaque appel système, s'il y en a un, est testé et géré (traitement d'erreur),
  • Le fait que les ressources système réservées pendant l'exécution du programme sont libérées à la fin de l'exécution.
La «livraison» de votre travail en fin de TP noté se fera par remise de votre copie à l'enseignant et par envoi d'un mail à Michel.Simatic@int-evry.fr (sujet «CSC4508/M2:TP noté») avec en pièce jointe le fichier d'extension tgz constitué de la manière suivante :
cd votreRepertoireDeTravailPourCS22M1
tar cvfz $USER.tgz TPNote2006

Préparation

cd votreRepertoireDeTravailPourCS22M1
cp ~simatic/CS22M1/tPNote2006.tgz .
tar xvfz tPNote2006.tgz
cd TPNote2006

Question 1 : Questions de cours (5 points)

Pour chacune des questions ci-dessous, répondez sur votre copie ou bien dans le fichier Q1/reponse1.txt (dans ce dernier cas, indiquez sur votre copie "Réponse dans Q1/reponse1.txt" ).

Question 1.1 : À propos des threads

On considère le code suivant :
#include <stdio.h>
#include <stdlib.h>

#include <pthread.h>

#define NBAFFICHAGE 5

void ajoute(char *val)
{
static char cur;

if (val != NULL)
cur = *val;
else
cur = cur + 1;

printf("cur = %c\n", cur);
}


void *pthread_func(void *arg)
{
int i;
char *val = (char *)arg;

ajoute(val);

sleep(2);

for (i = 0; i < NBAFFICHAGE; i++)
ajoute(NULL);

pthread_exit(NULL);
}

int main(int argc, char **argv)
{
pthread_t thread1, thread2;

char val1 = 'a';
char val2 = 'A';

if (pthread_create(&thread1, NULL, pthread_func, &val1))
{
perror("pthread_create");
exit(EXIT_FAILURE);
}

if (pthread_create(&thread2, NULL, pthread_func, &val2))
{
perror("pthread_create");
exit(EXIT_FAILURE);
}

pthread_join(thread1, NULL);
pthread_join(thread2, NULL);

return EXIT_SUCCESS;
}

À un moment donné, combien y-a-t-il au maximum dans la mémoire du processus d'occurrences de:

  • val1
  • val2
  • i
  • cur
  • val
---beginCorr
Barême : 0,3 point par nombre correct d'occurrences ==> 1,5 point maxi
  • val1: 1
  • val2: 1
  • i: 2 (nombre de threads appelant thread_func)
  • cur: 1 (variable statique)
  • val: 2 (nombre de threads appelant thread_func)
---endCorr

Question 1.2 : Ordonnancement

Un(e) de vos collègues vient de lancer le programme suivant :
/*******************************/
/* Essai de sched_setscheduler */
/*******************************/

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>

#define FATAL(msg) {\
char m[128]; \
sprintf(m, "%s in %s:%d:%s", msg, __FILE__, __LINE__, __func__); \
perror(m); \
abort(); \
}

/**********************************************************************/
/* Code execute par le processus enfant */
/**********************************************************************/
void codeEnfant()
{
struct sched_param sp;

sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (sched_setscheduler(0,SCHED_FIFO,&sp) < 0) {
FATAL("sched_setscheduler");
}

while(1){
}
}

/**********************************************************************/
/* Programme principal */
/**********************************************************************/
int main(int argc, char* argv[])
{
int status;

switch (fork()) {
case -1:
FATAL("fork");
break;
case 0:
codeEnfant();
break;
default:
wait(&status);
}

return EXIT_SUCCESS;
}
Que conseillez-vous pour arrêter son programme ? Justifiez votre réponse.
Qu'auriez-vous répondu si votre collègue avait utilisé SCHED_RR à la place de SCHED_FIFO ?
---beginCorr
Barême : 1,5 point réparti en : 0,5 point pour la manière d'arrêter le programme, 0,5 point pour la justification et 0,5 pour l'explication par rapport à SCHED_RR.

Il faut arrêter la machine (en coupant son alimentation électrique).
En effet, ce programme forke un enfant qui prend une priorité statique maximale. Donc, quand cet enfant prend la main, il ne la lâche plus (vu qu'ordonnancement SCHED_FIFO et que priorité maximale : aucun processus ne peut préempter cet enfant). Donc, on n'a plus aucun moyen d'arrêter ce programme.

Si utilisation de SCHED_RR, on ne peut plus être aussi catégorique. En effet, tout dépend de la présence ou non d'un processus de priorité statique 99 ayant les fonctionnalités suivantes : il est à l'écoute d'une socket ; sur réception d'un message sur cette socket, il fait kill sur un processus qu'on lui a indiqué. Dans ce cas, comme le processus lancé par le collègue a un ordonnancement SCHED_RR, il peut laisser la main à cet autre processus au bout de ce quantum de temps. Donc le processus peut être arrêté s'il y a cet autre processus. S'il n'y pas cet autre processus, on est dans la même situation que précédemment.
---endCorr

Question 1.3 : Mémoire

Le système d'exploitation MS-DOS a été conçu en 1981 de sorte qu'un programme s'exécutant sur ce système ne pouvait accéder qu'à 640 Ko de mémoire vive. Or, à partir de 1988, les ordinateurs sous MS-DOS disposant d'au moins 1 Mo de mémoire vive devenaient communs.
Pour tirer parti de cette mémoire vive supplémentaire, des compilateurs ont alors proposé le mécanisme appelé "mécanisme de recouvrement" (overlay) :
  • Le programmeur pouvait spécifier que des sections de son code devaient être rangées dans des fichiers appelés "fichiers de recouvrement" (ou fichiers d'overlay).
  • Ainsi un programme exécutable était constitué par :
    • Un fichier exécutable contenant le main du programme.
    • Un ou plusieurs fichiers de recouvrement, chargés dans la mémoire au delà des 640 Ko au moment de l'exécution.
  • La zone de 640 Ko contenait une zone appelée "zone de recouvrement". Pour être utilisé, un fichier de recouvrement devait être transféré dans cette zone de recouvrement. Le programmeur souhaitant appeler une fonction située dans un fichier de recouvrement devait au préalable invoquer une primitive permettant le transfert du fichier de recouvrement dans la zone de recouvrement. L'appel de la fonction pouvait ensuite se faire normalement.
    NB : si le programmeur avait ensuite besoin d'invoquer une fonction présente dans un autre fichier de recouvrement, il devait préalablement demander le transfert de cet autre fichier qui recouvrait (remplaçait) alors le premier fichier dans la zone de recouvrement.
  • Voici un exemple de main d'un programme qui utilisait 3 fonctions a et b stockées dans le fichier fichierRecouvrementAB et 2 fonctions y et z stockées dans le fichier fichierRecouvrementYZ :
    int main(){
    chargerFichierRecouvrement(fichierRecouvrementAB);
    a(); /* NB : a() appelle b(), ce qui ne pose aucun problème   */
    /* puisque b() est présente dans la zone de recouvrement */
    chargerFichierRecouvrement(fichierRecouvrementYZ); /* NB : ce fichier recouvre le fichier */
    /* fichierRecouvrementAB : a() et b() */
    /* ne sont donc plus accessibles */
    y();
    z();
    chargerFichierRecouvrement(fichierRecouvrementAB);
    a();
    return EXIT_SUCCESS;
    }
Présentez au moins un avantage et au moins deux inconvénients du mécanisme de recouvrement par rapport à un mécanisme de mémoire virtuelle.
---beginCorr
Barême : 1 point pour l'avantage et 0,5 point par inconvénient (avec un total de 2 points maximum).

Avantages
  • Quand le fichier de recouvrement est chargé dans la zone de recouvrement, l'accès à des fonctions stockées dans ce fichier ne coûte qu'un accès mémoire (alors qu'avec de la mémoire virtuelle, si on n'a pas de TLB ou de cache, on a systématiquement 2 accès).
  • Ce mécanisme de recouvrement ne nécessite pas de gestion spéciale au niveau du processeur. En revanche, la mémoire virtuelle n'est efficace que parce que le processeur offre des fonctionnalités pour la gérer.
Inconvénients
  • Une fonction présente dans un fichier de recouvrement ne peut pas appeler une fonction présente dans un autre fichier de recouvrement.
  • Le programmeur doit être conscient du fichier de recouvrement où est stocké chaque fonction. Cela lui rajoute du travail et diminue sa productivité.
  • On ne peut mettre que du code dans un fichier de recouvrement. Or, ce qui consomme de la mémoire dans un programme correspond en général à ses données. Le mécanisme de recouvrement ne répondra donc pas au besoin de tous les programmes.
  • Ce mécanisme ne peut pas être accéléré à l'aide d'instructions spéciales dans le processeur.
  • temps de chargement du fichier de recouvrement dans la zone de recouvrement
  • Extensibilité de ce mécanisme, les 640 Ko étant fixés.
---endCorr

Question 2 : Il était une fois... (7 points)

Il était une fois une jeune et jolie jeune fille qui s'appelait Blanche-Neige. Tous les matins, les chauds rayons du soleil venait la tirer de son doux et beau sommeil. Pleine d'énergie, elle réveillait les sept nains (avec qui elle vivait) afin qu'ils ne soient pas en retard pour leur travail à la mine.
Une fois habillés, puis arrivés devant la mine, les sept nains devaient éventuellement attendre que les trois ours (qui travaillaient parfois à la mine pendant que les nains n'y étaient pas) en soient sortis (les ours et les nains n'arrivaient pas à cohabiter dans la mine : les ours estimaient que la barbe des nains grattait ; quant aux nains, ils trouvaient que les ours ne savaient pas siffler en travaillant). Une fois les ours sortis (pour rejoindre la tendre Bouton d'Or, mais cela est une autre histoire), les nains entraient dans la mine pour commencer leur travail qu'ils entrecoupaient de pauses régulières au cours desquelles ils se réconfortaient à l'aide d'un verre d'alcool du pays préparé par la Grand-mère du Petit Chaperon rouge. Ils trouvaient ces verres sur un plateau (situé à l'entrée de la mine), les buvaient (cul sec !) et les jetaient par dessus leur épaule (ces nains étaient d'origine russe). Ce plateau (qui pouvait contenir au plus quatre verres pleins) était rempli par 8 adorables petites mésanges qui faisaient constamment l'aller-retour Maison de Mère-Grand/Mine avec un verre rempli (ces mésanges attendant qu'une place soit libérée sur le plateau si jamais le plateau contenait quatre verres pleins).
Le soir venu, les nains quittaient la mine (permettant ainsi aux ours de rentrer dans la mine s'ils avaient décidé de venir y travailler) et rentraient à la maison. Là, sans se préoccuper que le soleil soit couché ou non, Blanche-Neige leur faisait "Bisou Bonne Nuit" pour qu'ils s'endorment. Elle allait ensuite se coucher en attendant une nouvelle journée pleine d'aussi merveilleuses aventures...

Cette histoire, vous l'avez raconté des centaines de fois à l'enfant dont vous êtes le ou la baby-sitter et... vous craquez ! Aussi, vous avez décidé de réfléchir à un algorithme qui servirait de base à un programme racontant automatiquement cette histoire.

Vous envisagez les tâches suivantes :
  • Une tâche Soleil racontant l'histoire du point de vue du soleil. Elle exécute l'algorithme suivant :
    faire
       Ecrire "Je me lève"
       dormir(12 heures)
       Ecrire "Je me couche"
       dormir(12 heures)
    tant que VRAI

  • Une tâche BlancheNeige racontant l'histoire du point de vue de Blanche-Neige. Elle exécute l'algorithme suivant :
    faire
       Ecrire "Le soleil me reveille"
       Ecrire "Je réveille les nains"
       Ecrire "Je vis ma vie sans les nains"
       Ecrire "Je fais Bisou Bonne Nuit à chaque nain"
       Ecrire "Je dors"
    tant que VRAI

  • 7 tâches Nain (une pour chacun des nains) racontant l'histoire du point de vue de chaque nain. Elles exécutent l'algorithme suivant :
    faire
       Ecrire "Blanche-Neige me reveille"
       Ecrire "Je vais à la mine"
       Ecrire "J'attends de pouvoir entrer dans la mine"
       Ecrire "J'entre dans la mine"
       faire
          Ecrire "Je travaille"
          dormir(nombreDeMinutesAleatoire)
          Ecrire "Je prends ma pause"
          Ecrire "Je prends un verre plein"
          Ecrire "Je bois cul sec !"
       tant que continuerTravail()
       Ecrire "Je quitte la mine"
       Ecrire "Je rentre à la maison"
       Ecrire "Blanche-Neige me fait Bisou Bonne Nuit"
       Ecrire "Je m'endors"
     tant que VRAI

  • 3 tâches Ours (une pour pour chacun des ours) racontant l'histoire du point de vue de chaque ours. Elles exécutent l'algorithme suivant :
     faire
        Ecrire "Je vis une autre histoire avec Bouton d'Or"
        dormir(nombreDeMinutesAleatoire)
        si oursDecideDAllerTravaillerALaMine() == VRAI alors
          
    Ecrire "Je vais à la mine"
           Ecrire "J'attends de pouvoir entrer dans la mine"
           Ecrire "J'entre dans la mine et je travaille"
           dormir(nombreDeMinutesAleatoire)
           Ecrire "Je quitte la mine"
        finsi

     tant que VRAI

  • 8 tâches Mesange (une pour chacune des mésanges) racontant l'histoire du point de vue de chaque mésange. Elles exécutent l'algorithme suivant :
     faire
        Ecrire "Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau"
        Ecrire "Je dépose le verre sur le plateau"
     tant que VRAI
NB : pour les questions 2.1 et 2.2, vous pouvez répondre sur votre copie ou bien dans le fichier Q2/reponse2.txt. Dans ce dernier cas, indiquez sur votre copie "Réponses dans Q2/reponse2.txt".

Question 2.1 : Identification des paradigmes (2 points)

Indiquez les différents types de problème de synchronisation auxquels vous allez être confrontés pour implémenter ce programme (exclusion mutuelle, cohorte, producteur/consommateur...) en précisant, pour chaque problème, ses acteurs (par exemple, si vous trouvez qu'il y a un paradigme de lecteurs/rédacteur dans lequel intervient le "soleil", vous devez préciser si le "soleil" est lecteur ou rédacteur).
Pour chacune des questions ci-dessous, répondez sur votre copie ou bien dans le fichier Q2/reponse.txt (dans ce dernier cas, indiquez sur votre copie "Réponse dans Q2/reponse.txt" ).
---beginCorr
Barême : 0,4 point par paradigme détecté.
  • Paradigme de type signal
    • Soleil ("signaleur")/Blanche-Neige("signalé")
    • Blanche-Neige ("signaleur")/Chacun des nains ("signalé") au moment du réveil
    • Blanche-Neige ("signaleur")/Chacun des nains ("signalé") au moment du Bisou Bonne Nuit
  • Paradigme de type Producteur/Consommateur
    • Mésanges ("producteur")/Nains ("consommateur"), le tampon étant représenté par le plateau
  • Paradigme de type Lecteurs/Rédacteurs (ou on pourrait dire LecteursDeCatégorie1/LecteursDeCatégorie2, les 2 catégories ne pouvant pas se mélanger)
    • Nains ("LecteursDeCatégorie1")/Ours ("LecteursDeCatégorie2")
---endCorr

Question 2.2 : Conception à l'aide de sémaphores (5 points)

À l'aide de sémaphores IPC (munis de leurs opérations P() et V()) et de variables que vous déclarerez de manière globale (i.e. ils seront accessibles à partir de n'importe quelle procédure/fonction de votre programme) et initialiserez, complétez les algorithmes envisagés pour que le programme raconte correctement l'histoire.
---beginCorr
Barême :
  • Toutes les variables sont là : 0,5 (- 0,1 par variable manquante)
  • Toutes les variables sont correctement initialisées : 0,5 (-0,1 par variable incorrectement initialisée)
  • 1 point pour paradigme LecteursDeCatégorie1/LecteursDeCatégorie2 correctement implémenté
  • 0,75 point pour chacun des 4 autres paradigmes correctement implémenté.
Variables
=========
// Variables associées aux paradigmes de type Signal
Sémaphore topSoleil initialisé à 0
Sémaphore topReveilNain initialisé à 0
Sémaphore topBisouNain initialisé à 0
// Variables associées au paradigme de type Producteur/Consommateur
Sémaphore infoPrete initialisé à 0
Sémaphore placeDispo initialisé à 4
Sémaphore mutexNain initialisé à 1
Sémaphore mutexMesange initialisé à 1
Entier iDepot initialisé à 0
Entier iExtrait initialisé à 0
plateau Tableau[1..4] d'Entier = {0, 0, 0, 0}
// Variable associées au paradigme de type LecteursDeCatégorie1/LecteursDeCatégorie2
Sémaphore fifo initialisé à 1
Sémaphore mutexG initialisé à 1
Sémaphore mutexNain initialisé à 1
Sémaphore mutexOurs initialisé à 1
Entier nbNainDansMine initialisé à 0
Entier nbOursDansMine initialisé à 0

Tache Soleil
============
faire
Ecrire "Je me lève"
V(topSoleil)
dormir(12 heures)
Ecrire "Je me couche"
dormir(12 heures)
tant que VRAI

Tache BlancheNeige
==================
faire
P(topSoleil)
Ecrire "Le soleil me reveille"
Ecrire "Je réveille les nains"
pour i=1:Entier à 7 faire
V(topReveilNain)
fpour i
Ecrire "Je vis ma vie sans les nains"
Ecrire "Je fais Bisou Bonne Nuit à chaque nain"
pour i=1:Entier à 7 faire
V(topBisouNain)
fpour i
Ecrire "Je dors"
tant que VRAI

Tache Nain
==========
faire
P(topReveilNain)
Ecrire "Blanche-Neige me reveille"
Ecrire "Je vais à la mine"
Ecrire "J'attends de pouvoir entrer dans la mine"
P(fifo)
P(mutexNain)
nbNainDansMine = nbNainDansMine + 1
si nbNainDansMine == 1 alors
P(mutexG)
finsi
V(mutexNain)
V(fifo)
Ecrire "J'entre dans la mine"
faire
Ecrire "Je travaille"
dormir(nombreDeMinutesAleatoire)
Ecrire "Je prends ma pause"
P(infoPrete)
P(mutexNain)
Ecrire "Je prends un verre plein"
Ecrire "Je bois cul sec !"
tampon[iExtrait] = 0
iExtrait = (iExtrait + 1) modulo 4
V(mutexNain)
V(placeDispo)
tant que continuerTravail()
Ecrire "Je quitte la mine"
P(mutexNain)
nbNainDansMine = nbNainDansMine - 1
 si nbNainDansMine == 0 alors
V(mutexG)
finsi
V(mutexNain)
Ecrire "Je rentre à la maison"
P(topBisouNain)
Ecrire "Blanche-Neige me fait Bisou Bonne Nuit"
Ecrire "Je m'endors"
tant que VRAI

Tache Ours
==========
faire
Ecrire "Je vis une autre histoire avec Bouton d'Or"
dormir(nombreDeMinutesAleatoire)
si oursDecideDAllerTravaillerALaMine() == VRAI alors
Ecrire "Je vais à la mine"
Ecrire "J'attends de pouvoir entrer dans la mine"
P(fifo)
P(mutexOurs)
nbOursDansMine = nbOursDansMine + 1
si nbOursDansMine == 1 alors
P(mutexG)
finsi
V(mutexOurs)
V(fifo)
 Ecrire "J'entre dans la mine et je travaille"
dormir(nombreDeMinutesAleatoire)
Ecrire "Je quitte la mine"
P(mutexOurs)
nbOursDansMine = nbOursDansMine - 1
 si nbOursDansMine == 0 alors
V(mutexG)
finsi
V(mutexOurs)
finsi
tant que VRAI

Tache Mesange
=============
faire
Ecrire "Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau"
P(placeDispo)
P(mutexMesange)
Ecrire "Je dépose le verre sur le plateau"
tampon[iDepot] = 1
iDepot = (iDepot + 1) modulo 4
V(mutexMesange)
V(infoPrete)
tant que VRAI
---endCorr

Question 3 : Nains, mésanges et code (8 points)

Vous décidez d'implémenter une version simplifiée des algorithmes de la question 2. Les tâches suivantes sont envisagées :
  • 7 tâches Nain (une pour chacun des nains) racontant l'histoire (simplifiée) du point de vue de chaque nain. Elles exécutent l'algorithme suivant :
    faire
       Ecrire "Nain <numéroNain> : Je travaille"
       dormir(1 seconde)
       Ecrire "Nain <numéroNain> : Je prends ma pause"
       Ecrire "Nain <numéroNain> : Je prends un verre plein sur le plateau"
       Ecrire "Nain <numéroNain> : Je bois cul sec !"
     tant que VRAI

  • 8 tâches Mesange (une pour chacune des mésanges) racontant l'histoire (simplifiée) du point de vue de chaque mésange. Elles exécutent l'algorithme suivant :
     faire
        Ecrire "Mésange <numéroMésange> : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau"
        Ecrire "Mésange <numéroMésange> : Je dépose le verre sur le plateau"
     tant que VRAI

Question 3.1 : Conception (2 points)

Décrire dans Q3/reponse31.txt les algorithmes envisagés dans le cas de l'utilisation de threads, avec des mutex et des conditions (le plateau sera représenté par un tableau d'entier de 4 cases : une case à 0 signifie que cette partie du plateau est vide tandis qu'une case à 1 signifie que cette partie du plateau contient un verre plein.
NB : Si vous ne voyez pas comment écrire ces algorithmes (et que vous souhaitez, malgré tout, répondre à la question 3.2), vous avez la possibilité de faire "appel à un cabinet de consulting" en demandant une indication à l'enseignant qui notera qu'il vous a aidé : donc, le(s) point(s) de barême associé(s) à cet(/ces) algorithmes ne vous sera(/seront) pas comptabilisé(s).
---beginCorr
Barême :
  • 0,5 point pour l'explication du paradigme (NB : on comptabilise ce 0,5 si présentation des algos de producteur/consommateur sans les mentionner explicitement (vu que ça a déjà été mentionné à la question précédente)
  • 0,5 pour la définition et l'initialisation des variables (-0,1 pour chaque variable manquante ou mal initialisée
  • 0,5 pour chaque algo
C'est un producteur/consommateur avec 8 producteurs (les mésanges), 7 consommateurs (les nains) et un tampon de 4 cases.
Variables
=========
mutex mutexDepot
mutex mutexRetrait
condition condDepot
condition condRetrait
Entier placeDispo initialisé à 4
Entier infoPrete initialisé à 0
Entier iDepot initialisé à 0
Entier iExtrait initilisé à 0
plateau Tableau[1..4] d'Entier = {0, 0, 0, 0}

Tache Nain
==========
faire
Ecrire "Nain <numéroNain> : Je travaille"
dormir(1 seconde)
Ecrire "Nain <numéroNain> : Je prends ma pause"
// On tente de prendre le verre
lock(mutexRetrait)
tant que infoPrete == 0 faire
wait(condRetrait, mutexRetrait)
fait
infoPrete = infoPrete - 1
plateau[iExtrait] = 0
iExtrait = (iExtrait + 1) modulo 4
unlock(mutexRetrait)
lock(mutexDepot)
placeDispo = placeDispo + 1
unlock(mutexDepot)
signal(condDepot)
// On a reussi : on peut donc continuer
Ecrire "Nain <numéroNain> : Je prends un verre plein sur le plateau"
Ecrire "Nain <numéroNain> : Je bois cul sec !"
tant que VRAI

Tache Mesange
============
faire
Ecrire "Mésange <numéroMésange> : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau"
// On tente de déposer le verre
lock(mutexDepot)
tant que placeDispo == 0 faire
wait(condDepot, mutexDepot)
fait
placeDispo = placeDispo - 1
plateau[iDepot] = 1
iDepot = (iDepot + 1) modulo 4
unlock(mutexDepot)
lock(mutexRetrait)
infoPrete = infoPrete + 1
unlock(mutexRetrait)
signal(condRetrait)
// On a reussi : on peut donc continuer
Ecrire "Mésange <numéroMésange> : Je dépose le verre sur le plateau"
tant que VRAI
---endCorr

Question 3.2 : Implémentation avec des threads (6 points)

Implémenter (avec des threads, des conditions et des mutex) la conception envisagée à la question 3.1 en modifiant le fichier Q3/conteDeFeeOuCauchemar.c
NB : <numéroNain> sera remplacé par un numéro entre 1 et 7 tandis que <numéroMésange> sera remplacé par un numéro entre 1 et 8
---beginCorr
Barême (à revoir une fois que le code aura été écrit) :
  • 3 points pour la mise en oeuvre du Producteur/consommateur :
    • 1 pour la création/initialisation des threads (passage correct de l'indice pour que chaque thread ait reçu un numéro en paramètre).
    • 1 point pour les 2 conditions
    • 1 point pour les 2 mutex
  • 1 point pour la gestion des différentes variables
  • 1 point pour le fonctionnement global
  • 0,5 points pour la propreté (commentaires, indentation...)
  • 0,5 points pour le traitement des erreurs
Voir conteDeFeeOuCauchemar.corrige.c
Voici un exemple d'exécution :
Nain 1 : Je travaille
Nain 2 : Je travaille
Nain 3 : Je travaille
Nain 4 : Je travaille
Nain 5 : Je travaille
Nain 6 : Je travaille
Nain 7 : Je travaille
Mésange 1 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 1 : Je dépose le verre sur le plateau
Mésange 1 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 1 : Je dépose le verre sur le plateau
Mésange 1 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 1 : Je dépose le verre sur le plateau
Mésange 1 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 1 : Je dépose le verre sur le plateau
Mésange 1 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 2 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 3 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 4 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 5 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 6 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 7 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 8 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Nain 2 : Je prends ma pause
Nain 2 : Je prends un verre plein sur le plateau
Nain 2 : Je bois cul sec !
Nain 2 : Je travaille
Nain 3 : Je prends ma pause
Nain 3 : Je prends un verre plein sur le plateau
Nain 3 : Je bois cul sec !
Nain 3 : Je travaille
Nain 4 : Je prends ma pause
Nain 4 : Je prends un verre plein sur le plateau
Nain 4 : Je bois cul sec !
Nain 4 : Je travaille
Nain 5 : Je prends ma pause
Nain 5 : Je prends un verre plein sur le plateau
Nain 5 : Je bois cul sec !
Nain 5 : Je travaille
Nain 6 : Je prends ma pause
Nain 7 : Je prends ma pause
Nain 1 : Je prends ma pause
Mésange 1 : Je dépose le verre sur le plateau
Mésange 1 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 2 : Je dépose le verre sur le plateau
Mésange 2 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Mésange 3 : Je dépose le verre sur le plateau
Mésange 3 : Je prends un verre plein chez Mère-Grand, je vais à la mine et j'attends de pouvoir le déposer sur le plateau
Nain 1 : Je prends un verre plein sur le plateau
Nain 1 : Je bois cul sec !
Nain 1 : Je travaille
...
---endCorr



Page mise à jour le 7 juin 2006