Skip to content
Snippets Groups Projects
Commit 7141ac60 authored by Lou Davila's avatar Lou Davila
Browse files

Lou Final version code+doc

parent d82ec91d
Branches main
No related tags found
No related merge requests found
TP3 : Gestion d’un parc de vélos
Nom : El Ajeri Nom : Davila Prado
Prénom : Khalil Mokhtar Prénom : Lou
Groupe : 14
--------------------------------------------------
Statut du projet
--------------------------------------------------
Projet fonctionnel.
- Le programme gère correctement la concurrence entre threads à l’aide de mutex et sémaphores.
- Tous les trajets sont effectués sans blocage (tests répétés).
- Le nombre total de vélos reste constant à la fin de la simulation : S * (N - 2) + 2.
- Chaque site possède entre 0 et N vélos à la fin.
- Les affichages reflètent bien les prises, dépôts, attentes et les actions du camion.
- La logique du dépôt et du rééquilibrage est bien gérée.
- Les délais usleep ont été désactivés pour les tests de performance/stabilité.
- On a eu un bug avec un grand nombre d'habitants donc à cause de la concurrence au niveau de la gestion des vélos
qu'on a pu régler par la suite.
--------------------------------------------------
Algorithme de gestion des habitants
--------------------------------------------------
Chaque habitant est un thread. Il effectue M trajets :
1. Il attend passivement qu’un vélo soit disponible sur son site actuel (sémaphore velos), en incrémentant personnes_attente.
2. Une fois le vélo obtenu, il décrémente le compteur local velos_dispo du site, puis libère une borne (bornes).
3. Il choisit un autre site (aléatoirement) et attend passivement qu’une borne soit libre (sémaphore bornes) pour y déposer le vélo.
4. Il incrémente alors velos_dispo de ce site, poste sur le sémaphore velos, et libère ainsi le vélo pour un autre utilisateur.
Toutes les modifications des variables critiques (velos_dispo, personnes_attente) sont protégées par un mutex par site.
Un mutex global (mutex_trajets) est utilisé pour suivre le nombre total de trajets réalisés par tous les habitants.
--------------------------------------------------
Gestion de la concurrence
--------------------------------------------------
- Les accès partagés (velos_dispo, bornes, velos, personnes_attente, variables utilisées dans les printf) sont protégés par des mutex individuels.
- Les accès globaux (trajets_effectues, velos_depot) sont protégés par des mutex globaux.
- Les sémaphores assurent des attentes passives :
- velos pour prendre un vélo.
- bornes pour déposer un vélo.
- Les sections critiques sont réduites au strict minimum.
- Chaque affichage est fait après la section critique pour limiter la contention.
--------------------------------------------------
Fonctions codées:
--------------------------------------------------
void *habitant(void *arg)
---------------------------------
Cette fonction représente le comportement d’un habitant modélisé par un thread.
- Chaque habitant commence à un site choisi aléatoirement.
- Il effectue TRAJETS fois la séquence de prise et dépôt de vélo entre deux sites différents.
- Il utilise les sémaphores pour attendre passivement la disponibilité d’un vélo ou d’une borne.
- Les compteurs internes (velos_dispo, personnes_attente) sont mis à jour dans des sections critiques protégées par mutex.
- Le compteur global trajets_effectues est également protégé par un mutex.
- À chaque dépôt de vélo, le site actuel est mis à jour.
- Les affichages indiquent les actions de l’habitant et les situations d’attente.
void *gestion_camion(void *arg)
---------------------------------
Cette fonction modélise la camionnette de maintenance qui équilibre les vélos entre les sites.
- Elle tourne tant que tous les trajets ne sont pas effectués (condition vérifiée avec mutex_trajets).
- Pour chaque site :
a. Si trop de vélos : enlève jusqu’à CAMION_CAPACITE - velos_camion vélos pour atteindre N - 2.
b. Si trop peu de vélos : ajoute jusqu’à 2 vélos selon disponibilité du camion et bornes.
- Après la boucle des sites :
a. Dépôt des vélos excédentaires si velos_camion > 2.
b. Recharge depuis le dépôt si velos_camion < 2.
- L’accès au dépôt est protégé par mutex_velos_depot.
- Le comportement respecte la capacité max du camion (4 vélos).
int main(int argc, char *argv[])
---------------------------------
Fonction principale qui :
- Récupère les paramètres SITES, HABITANTS, TRAJETS et BORNES depuis la ligne de commande.
- Initialise les sémaphores et mutex de chaque site.
- Lance les threads pour chaque habitant et un thread pour le camion.
- Attend la fin de tous les threads avec pthread_join.
- Affiche les vélos par site et la vérification du total global à la fin de l’exécution.
- Détruit les sémaphores et mutex à la fin.
--------------------------------------------------
Bugs résiduels
--------------------------------------------------
Lorsqu'un trop grand nombre d'habitants est spécifié au lancement du programme, le programme finit par se bloquer après un certain temps d'exécution.
Nous pensons que ceci est dû à un trop grand nombre de threads concurrents crées par rapport à la capacité de la machine.
Il faudrait probablement limiter le nombre de threads créés simultanement pour éviter ce genre de problème.
--------------------------------------------------
Conclusion
--------------------------------------------------
Le programme respecte toutes les exigences du TP : cohérence des vélos, absence de blocage, affichages pertinents, gestion propre de la concurrence.
\ No newline at end of file
No preview for this file type
/*Authors: Lou Davila Prado, Khalil El Ajeri
Groupe: 14*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
......@@ -14,7 +17,7 @@ typedef struct
int velos_dispo;
int personnes_attente;
pthread_mutex_t mutex;
} Site;
}Site;
int SITES,HABITANTS,TRAJETS,BORNES;
Site *sites;
......@@ -36,38 +39,46 @@ void *habitant(void *arg)
{
site_suivant = rand()%SITES;
}
while (site_suivant == site_actuel);
while (site_actuel == site_suivant);
pthread_mutex_lock(&sites[site_actuel].mutex);
sites[site_actuel].personnes_attente++;
int velos = sites[site_actuel].velos_dispo;
int attente = sites[site_actuel].personnes_attente;
pthread_mutex_unlock(&sites[site_actuel].mutex);
printf("(GET) Habitant %d attend un vélo au site %d\n",habitant_id,site_actuel);
printf("(GET) Habitant %d attend un vélo au site %d (%d vélos, %d personnes en attente)\n", habitant_id, site_actuel, velos, attente);
sem_wait(&sites[site_actuel].velos);
pthread_mutex_lock(&sites[site_actuel].mutex);
sites[site_actuel].velos_dispo--;
sites[site_actuel].personnes_attente--;
velos = sites[site_actuel].velos_dispo;
attente = sites[site_actuel].personnes_attente;
pthread_mutex_unlock(&sites[site_actuel].mutex);
printf("(GET) Habitant %d prend un vélo au site %d\n",habitant_id,site_actuel);
printf("(GET) Habitant %d prend un vélo au site %d (%d vélos, %d personnes en attente)\n", habitant_id, site_actuel, velos, attente);
sem_post(&sites[site_actuel].bornes);
//usleep((rand()%1000+1000));
pthread_mutex_lock(&sites[site_suivant].mutex);
sites[site_suivant].personnes_attente++;
velos = sites[site_suivant].velos_dispo;
attente = sites[site_suivant].personnes_attente;
pthread_mutex_unlock(&sites[site_suivant].mutex);
printf("(PUT) Habitant %d attend d'avoir accès à une borne du site %d\n",habitant_id,site_suivant);
printf("(PUT) Habitant %d attend d'avoir accès à une borne du site %d (%d vélos, %d personnes en attente)\n", habitant_id, site_suivant, velos, attente);
sem_wait(&sites[site_suivant].bornes);
pthread_mutex_lock(&sites[site_suivant].mutex);
sites[site_suivant].velos_dispo++;
sites[site_suivant].personnes_attente--;
velos = sites[site_suivant].velos_dispo;
attente = sites[site_suivant].personnes_attente;
pthread_mutex_unlock(&sites[site_suivant].mutex);
sem_post(&sites[site_suivant].velos);
printf("(PUT) Habitant %d dépose un vélo au site %d\n",habitant_id,site_suivant);
printf("(PUT) Habitant %d dépose un vélo au site %d (%d vélos, %d personnes en attente)\n", habitant_id, site_suivant, velos, attente);
//usleep((rand()%1000+1000));
site_actuel = site_suivant;
......@@ -96,6 +107,8 @@ void *gestion_camion(void *arg)
for (int i = 0; i < SITES; i++)
{
pthread_mutex_lock(&sites[i].mutex);
int velos = sites[i].velos_dispo;
int attente = sites[i].personnes_attente;
if (CAMION_CAPACITE > velos_camion && sites[i].velos_dispo > BORNES-2)
{
......@@ -110,15 +123,23 @@ void *gestion_camion(void *arg)
aRetirer = sites[i].velos_dispo-1;
}
pthread_mutex_unlock(&sites[i].mutex);
for (int j = 0; j < aRetirer; j++)
{
sem_wait(&sites[i].velos);
pthread_mutex_lock(&sites[i].mutex);
sites[i].velos_dispo--;
velos = sites[i].velos_dispo;
attente = sites[i].personnes_attente;
pthread_mutex_unlock(&sites[i].mutex);
velos_camion++;
sem_post(&sites[i].bornes);
}
printf("Camion prend des vélos au site %d (Vélos dans camion: %d)\n",i,velos_camion);
printf("Camion prend %d vélos au site %d (%d vélos, %d personnes en attente) (Vélos dans le camion: %d)\n", aRetirer, i, velos, attente, velos_camion);
}
else if (sites[i].velos_dispo < 2 && velos_camion > 0)
{
......@@ -134,18 +155,29 @@ void *gestion_camion(void *arg)
aAjouter = spotsDisponibles;
}
pthread_mutex_unlock(&sites[i].mutex);
for (int j = 0; j < aAjouter; j++)
{
sem_wait(&sites[i].bornes);
pthread_mutex_lock(&sites[i].mutex);
sites[i].velos_dispo++;
velos = sites[i].velos_dispo;
attente = sites[i].personnes_attente;
pthread_mutex_unlock(&sites[i].mutex);
velos_camion--;
sem_post(&sites[i].velos);
}
printf("Camion dépose des vélos au site %d (Vélos dans camion: %d)\n",i,velos_camion);
printf("Camion dépose %d vélos au site %d (%d vélos, %d personnes en attente) (Vélos dans le camion: %d)\n", aAjouter, i, velos, attente, velos_camion);
}
else
{
pthread_mutex_unlock(&sites[i].mutex);
}
pthread_mutex_unlock(&sites[i].mutex);
//usleep((rand()%100+100));
}
......@@ -154,7 +186,7 @@ void *gestion_camion(void *arg)
{
velos_depot+= (velos_camion-2);
velos_camion = 2;
printf("Camion vide les vélos au dépôt (Vélos en dépôt: %d)\n",velos_depot);
printf("Camion vide les vélos au dépôt (Vélos en dépôt: %d)\n", velos_depot);
}
else if (velos_depot > 0 && velos_camion < 2)
{
......@@ -165,11 +197,11 @@ void *gestion_camion(void *arg)
}
velos_depot-= requis;
velos_camion+= requis;
printf("Camion prend des vélos du dépôt (Vélos en dépôt: %d)\n",velos_depot);
printf("Camion prend des vélos au dépôt (Vélos en dépôt: %d)\n", velos_depot);
}
pthread_mutex_unlock(&mutex_velos_depot);
printf("Camion fait un tour, vélos restants: %d, vélos en dépôt: %d\n",velos_camion,velos_depot);
printf("Camion fait un tour, Vélos restants: %d, vélos en dépôt: %d\n", velos_camion, velos_depot);
//usleep((rand()%100+100));
}
return NULL;
......@@ -179,23 +211,31 @@ int main(int argc, char *argv[])
{
if (argc != 5)
{
fprintf(stderr, "Usage: %s <SITES> <HABITANTS> <TRAJETS> <BORNES>\n",argv[0]);
fprintf(stderr, "Usage: %s <SITES> <HABITANTS> <TRAJETS> <BORNES>\n", argv[0]);
return 1;
}
SITES = atoi(argv[1]);
HABITANTS = atoi(argv[2]);
TRAJETS = atoi(argv[3]);
BORNES = atoi(argv[4]);
if (SITES <= 2 || HABITANTS <= 2 || TRAJETS <= 0 || BORNES <= 4)
{
printf("Les contraintes suivantes doivent être respectées:\n");
printf("SITES > 2, HABITANTS > 2, TRAJETS > 0, BORNES > 4\n");
exit(EXIT_FAILURE);
}
srand(time(NULL));
sites = malloc(SITES * sizeof(Site));
pthread_t habitants[HABITANTS],camion;
pthread_t habitants[HABITANTS], camion;
for (int i = 0; i < SITES; i++)
{
sem_init(&sites[i].velos,0,BORNES-2);
sem_init(&sites[i].bornes,0,2);
sem_init(&sites[i].velos, 0, BORNES-2);
sem_init(&sites[i].bornes, 0, 2);
pthread_mutex_init(&sites[i].mutex, NULL);
sites[i].velos_dispo = BORNES-2;
sites[i].personnes_attente = 0;
......@@ -204,24 +244,24 @@ int main(int argc, char *argv[])
{
int *habitant_id = malloc(sizeof(int));
*habitant_id = i;
pthread_create(&habitants[i],NULL,habitant,habitant_id);
pthread_create(&habitants[i], NULL, habitant, habitant_id);
}
pthread_create(&camion,NULL,gestion_camion,NULL);
pthread_create(&camion, NULL, gestion_camion, NULL);
for (int i = 0; i < HABITANTS; i++)
{
pthread_join(habitants[i],NULL);
pthread_join(habitants[i], NULL);
}
pthread_join(camion,NULL);
pthread_join(camion, NULL);
int total_velos = velos_depot;
for (int i = 0; i < SITES; i++)
{
total_velos+= sites[i].velos_dispo;
printf("Site %d contains %d bykes\n",i,sites[i].velos_dispo);
total_velos += sites[i].velos_dispo;
printf("Site %d contient %d vélos\n", i, sites[i].velos_dispo);
}
total_velos+= 2;
printf("Nombre total de vélos à la fin : %d (doit être %d)\n",total_velos,SITES*(BORNES-2)+2);
total_velos += 2;
printf("Nombre total de vélos à la fin : %d (doit être %d)\n", total_velos, SITES*(BORNES-2)+2);
printf("Simulation terminée.\n");
for (int i = 0; i < SITES; i++)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment