Vous êtes sur la page 1sur 3

TP3 : Le probl`me des philosophes e

RS : Rseaux et Syst`mes e e
Deuxi`me anne e e Cinq philosophes, runis pour philosopher, ont au moment du repas un probl`me pratique ` rsoudre. e e a e En eet, le repas est compos de spaghettis qui, selon la coutume de ces philosophes, se mangent avec e deux fourchettes. Or, la table nest dresse quavec une seule fourchette par couvert. Les philosophes e dcident dadopter le rituel suivant : e Chaque philosophe prend une place ` table. a Chaque philosophe qui mange utilise la fourchette ` sa droite et celle ` sa gauche (pas celle den a a face). ` A tout instant, chaque philosophe est dans lun des tats suivants : e il mange avec deux fourchettes ; il a faim, et attend la fourchette de droite, celle de gauche ou les deux ; il pense, et nutilise pas de fourchette. Initialement, tous les philosophes pensent. Un philosophe qui mange sarrte en un temps born. e e Lobjectif du TP est dexprimenter diverses solutions ` ce probl`me. Copiez les chiers de /home/ e a e depot/2A/RS/philosophes dans un rpertoire chez vous. philosophes.c et philosophes.h constituent e un simulateur de philosophes. Pour pouvoir lutiliser, il nest pas ncessaire de modier les e ` chiers philosophes.[ch]. A la place, il faut ajouter (dans un chier spar) trois fonctions manquantes e e spciant le comportement des philosophes : e e initialize data() : Une fonction ralisant toutes les initialisations de globales dont vous avez besoin. Elle reoit en argument le nombre de philosophes assis autour de la table. c pickup() : Ce que fait un philosophe qui a faim pour prendre ses fourchettes. Elle reoit en argument c le numro du philosophe qui lappelle, ainsi que le compte de philosophes autour de la table. e putdown() : Ce que fait un philosophe rassasi pour reposer ses fourchettes. Ses arguments sont e similaires ` pickup. a Une fois que le comportement des philosophes est spcis, il devient possible de compiler le sie e mulateur : gcc -pthread philosophes.c mon philosophe.c -lm -o mon philosophe . Le programme gnr e ee attend deux arguments obligatoires plus un optionnel : le nombre de philosophes assis autour de la table, le nombre maximal quun philosophe passe ` dormir et le temps de simulation souhait (la simulation est a e innie si on ne spcie pas de dure maximale). ./mon philosophe 5 1 20 simule 5 philosophes pouvant e e ` dormir au plus 1 seconde ` chaque fois, et termine la simulation apr`s 20 secondes. A intervalles rguliers, a e e des lignes rsument le temps que chaque philosophe a pass bloqu. e e e 10.0 Total blocktime : 13 : 2.9 3.1 3.6 2.6 3.9 (2 CS violations) Apr`s 10 secondes, les philosophes ont attendu 13 secondes au total. Le premier a attendu 2.9 secondes, e le second 3.1, et ainsi de suite. En plus de tenir ces chronomtrages ` jour, le simulateur vrie quaucun e a e philosophe ne mange en mme temps que lun de ses voisins, car cela voudrait dire que la fourchette e place entre les deux est utilise par deux personnes en mme temps. Dans lexemple ci-dessus, un tel e e e vnement est arriv deux fois (le simulateur indique deux violations de section critique). e e e Lobjectif est dobtenir une solution sans violation de section critique, sans interblocage, ecace (le temps total dattente est minimal) et quitable (lattente est bien rpartie entre les processus). Pour que e e ces grandeurs soient reprsentatives, il convient de laisser tourner la simulation au moins cent fois plus e que le temps de sommeil maximal. Le rpertoire des sources contient galement une biblioth`que dinterposition permettant de dtecter e e e e les interblocages dans un programme pthread sans devoir modier ce dernier. Voir lannexe ` ce sujet ` a a la n de lnonc. e e Exercice 1. Le chier philo null.c contient une implmentation vide du philosophe : chacun commence e a ` manger sans vrier si les couverts sont disponibles ou non. Compilez le programme, et excutez le. e e Constatez que le nombre de violations de section critique augmente avec le temps. gcc -pthread philosophes.c philo null.c -lm -o philo null Exercice 2. Le chier philo naive.c contient limplmentation na e ve, consistant ` prendre la foura chette ` sa droite puis la fourchette ` sa gauche en vriant leur disponibilit avec un mutex. Compilez le a a e e programme, et excutez le. Contrairement ` ce quon attend, ce programme nentre pas en interblocage e a (si cela ne vous tonne pas, relisez le TD correspondant). e

TP3 : Le probl`me des philosophes e Ceci est d au fait quil faut quun philosophe soit interrompu entre le moment o` il prend sa fourchette u u de gauche et la ligne suivant, o` il prend sa fourchette de droite pour provoquer un interblocage. Ajoutez u un sleep(1) entre les deux lignes, et remarquez la dirence. e e e Exercice 3. Ecrivez une version philo ordo vitant linterblocage en ordonnant les requtes. On peut par exemple verrouiller min(id, (id + 1)%count) en premier et max(id, (id + 1)%count) ensuite. Cela revient ` dire que tous les philosophes sont droitiers, sauf le dernier qui est gaucher. a Exercice 4. Ecrivez une version philo parite dans laquelle les philosophes dont lidentiant est pair sont droitiers (ils prennent leur fourchette droite en premier) tandis que les philosophes impaires sont gauchers. Question 1. Linterblocage est-il possible ? Pourquoi ? Question 2. Comparez lquit de cette version par rapport ` la solution de lexercice prcdent. e e a e e Exercice 5. Ecrivez une version philo global vitant linterblocage en ralisant des rservations globales e e e (ne pas prendre la moindre fourchette si on nest pas sr de pouvoir avoir les deux). On introduit une u variable dtat pour chaque philosophe c[i] qui vaut 0 si le philosophe i pense, 1 si il veut manger et 2 e si il mange. Le tableau c doit tre partag par tous les processus de faon ` ce que chacun puisse tester e e c a ltat de ses voisins. Le tableau doit naturellement tre protg par mutex. e e e e Un philosophe ayant faim consulte le tableau pour savoir sil peut manger. Si oui, il modie le tableau (pour bloquer ses voisins) ; si non, il sendort sur une smaphore prive pour que ses voisins le rveillent e e e quand ils ont ni. Question 1. Isolez les fonctions pickup() et putdown() dans le code suivant, et traduisez les en C dans Ne modiez pas philosophe.c philo global. fonction test(k) : si c[k] = 1 et c[k+1] != 2 et c[k-1] !=2 alors c[k] :=2 V(sempriv[k]) /* on libere le philosophe de son attente */ fonction philosopher(i) : penser() P(mutex) ; /* pour proteger le tableau c */ c[i] := 1 ; /* i a faim puisquil a fini de penser */ test(i) ; /* il regarde si il peut manger ; si oui, V(sempriv[i]) est fait */ V(mutex) ; /* pour que les voisins puissent rendre les fourchettes sils les avaient*/ P(sempriv[i]) ; /* Si le V est fait, a continue et il mange. c Sinon il attend quun voisin le rveille en librant les fourchettes */ e e manger() P(mutex) ; /* on va dire a tout le monde que lon a fini de manger */ c[i] := 0 ; /* on pose les couverts */ test(i-1) ; /* on regarde si les voisins peuvent manger maintenant que lon */ test(i+1) ; /* a pos les couverts et on fait leur V(sempriv[i]) si oui */ e V(mutex) ; Question 2. Modiez lalgorithme pour utiliser une variable de condition ` la place de la smaphore. a e Exercice 6. (solution du ma de table). tre Nous allons maintenant appliquer la troisi`me mthode du cours pour viter les interblocages en e e e modiant lalgorithme. Le principe est de ne pas prendre sa premi`re fourchette sil sagit de la derni`re e e pose sur la table. Cela simplmente simplement avec une smaphore initialise ` count 1 et prise (une e e e e a seule fois) par chaque philosophe avant de manger. Question 1. Implmentez cette approche dans philo maitre. e Exercice 7. Tous les algorithmes prcdents prsentent un risque de famine. Si le hasard veut que les e e e philosophes 0 et 2 mangent, puis 1 et 3, puis 0 et 2, et ainsi de suite, il est possible que 4 ne parvienne

TP3 : Le probl`me des philosophes e

jamais ` manger (si limplmentation des mutex ne garantie pas que les threads obtiennent le verrou dans a e lordre o` ils lont demand ce nest pas impos par le standard). u e e Pour corriger ce probl`me, il faut sassurer nous mme que les philosophes sont servis dans lordre. e e Quand lun dentre-eux appelle pickup(), sil a dj` quelquun dans la queue, le philosophe sy ajoute. ea Si la queue est vide, il tente de prendre ses fourchettes. Sil russi, il mange et il est plac dans la queue e e sinon. Lorsque lon pose les fourchettes, on regarde si cela lib`re le premier de la le. e e Question 1. Appliquez cette approche dans philo fifo. Remarquez que cette approche am`ne des temps de blocage bien plus long puisque certains philosophes sont bloqus dans la le dattente alors que e leurs fourchettes sont libres. Exercice 8. Saurez-vous proposer une solution garantie sans famine mais ecace ?

Dtection dinterblocages par biblioth`que dinterposition e e


Dans les sources fournis sur /home/depot/2A/RS/, vous trouverez un chier pthread interposer.c. Il sagit du source dun petit outil que vous pouvez utiliser pour dtecter de faon relativement sre les e c u interblocages dans vos programmes pthreads. Son principe gnral est dintercepter tous les appels aux fonctions pthread mutex lock et consoeurs, e e et dajouter des vrications pour voir si un cycle de dpendances se cre entre les threads en attente de e e e verrous possds par dautres. e e En ce qui concerne la dtection de deadlock, on construit une structure partage (donc elle mme e e e protge par mutex) indiquant quelle ressource est possde par quel thread, et quel thread est en attente e e e e de quelle ressource. Il ne reste plus qu` la parcourir parfois pour chercher un cycle. Notons que ce nest a pas infaillible car linterposeur change le comportement de lapplication observe, puisquon ajoute des e barri`res de synchronisation pour ne pas avoir de comptition sur notre structure partage. Votre code e e e peut donc entrer en interblocage sans linterposeur, et fonctionner tr`s bien avec (ou le contraire). e En ce qui concerne linterception elle-mme, on compile le code comme une biblioth`que partage e e e (pthread interposer.so, voir lentte du source sur comment faire), et on demande au chargeur dynae mique dutiliser prfrentiellement notre code plutt que le code syst`me. Il sut de dnir une variable ee o e e denvironnement LD PRELOAD contenant le chemin des biblioth`ques ` interposer de la sorte. e a Notre biblioth`que contient par exemple une fonction nomme pthread mutex lock. Donc, quand le e e programme excut avec le mcanisme dinterposition en place voudra appeler une fonction de ce nom, e e e cest notre version qui sera invoque et non celle de la biblioth`que pthread du syst`me (le contenu de e e e LD PRELOAD prend le pas sur LD LIBRARY PATH et sur les indications de chargement dynamique prsentes dans lexcutable). e e Notre objectif nest pas de rimplmenter compl`tement cette fonction, mais simplement dajouter du e e e code avant et apr`s lappel ` la vraie fonction. Il faut donc que notre version puisse appeler la version e a syst`me apr`s avoir vri quil ny a pas de deadlock. Oui, mais comment appeler une fonction du mme e e e e e nom que la fonction courante, mais venant dune autre biblioth`que ? e On utilise les fonctionnalits du chargeur dynamique linux pour rcuprer un pointeur sur la fonction. e e e Par exemple, le code suivant initialise le pointeur sur fonction mutex lock pour quil pointe sur le prochain symbole pthread mutex lock dni dans les biblioth`ques dynamiques actuellement charges. Ensuite, e e e mutex lock est utilisable comme une fonction normale, et appelle la fonction du syst`me... e
1 2

mutex_lock = (int(*)(pthread_mutex_t*)) dlsym(RTLD_NEXT, "pthread_mutex_lock"); mutex_lock(&the_mutex); $ LD_PRELOAD=./pthread_interposer.so [...] DEADLOCK DETECTED: - Thread 3 waits for lock 0, owned - Thread 1 waits for lock 1, owned - Thread 2 waits for lock 2, owned ./philo_naive 3 1 20 by thread 1. by thread 2. by thread 3.

1 2 3 4 5 6

Ce mcanisme dinterposition de biblioth`ques partages permet de raliser des tours de passe-passe e e e e en syst`me, et nous le mettons par exemple souvent en uvre pour automatiser la correction de projets e de programmation. Il existe un mcanisme quivalent sous Mac OS X (avec une syntaxe compl`tement dirente), mais e e e e Windows ne permet malheureusement pas de dnir une interposition pour un processus donn. Si on e e donne un interposeur, tous les programmes du syst`me lutilisent, ce qui peut poser probl`me si lintere e poseur est un peu ( (agressif) ). 3