diff --git a/G17_bykes/G17_Bykes.md b/G17_bykes/G17_Bykes.md new file mode 100644 index 0000000000000000000000000000000000000000..ed839ae4f32a9965ff3c769503b6214db2256843 --- /dev/null +++ b/G17_bykes/G17_Bykes.md @@ -0,0 +1,98 @@ +# G17 - TP Bykes +### Greub Remi + +## Status du projet +Le projet dans son état est complet et fonctionnel avec quelques bugs a relever. + +**Lancement du programme** +- via le makefile avec la cible `run` permettant de lancer le programme avec les arguments : S = 10, H = 100 , M = 10, N = 10 (modifiable avec la cible run ainsi) +``` +make run ARGS="arg1 arg2 arg3 arg4" +``` + +- le lancement du programme se fait autrement via `./bykes arg1 arg2 arg3 arg4` + - arg1 -> nombre de sites (terminals) + - arg2 -> nombre de personnes a simuler (chacun dans un thread !) + - arg3 -> nombre de trajets par personnes + - arg4 -> nombre de bornes a vélos/bikes par sites/terminals + +le programme est fonctionnel avec les arguments `10 100 10 10`, mais il peut se bloquer si l'on augmente le nombre de threads (notamment au dessus de 10000 threads avec par exemple les arguments ` ./bykes 100 10000 100 5000` ce qui devrait donné à la fin 499802 velos au total à la fin.) + +## Fonctionnement de l'algorithme +l'algorithme est séparé en 3 librairies `civilian.h` (contenant l'algorithme des personnes), `Truck.h` (algo de la camionette) et enfin `city.h` qui est la structure principale avec les variables partagées dont les différents sites/terminals. + +**city.h** +city contient les variables globales du programme : +``` +#define USLEEP 1 //activate usleep() = 1 or no = 0 + +struct terminal{ + int nb_bikesParked; //number of bikes parked in terminal + int nb_P_waiting; //number of persons waiting in terminal + sem_t *sem_FreeSlot; //semaphore of the free parking slots + sem_t *sem_BikeFree; //semaphore of the free bike + pthread_mutex_t *mutex; //mutex -> one for each terminal +}; +struct city{ + int npersons; //nb of persons in the city + int nSlots; //nb of slots for each terminal + int nTerminal; //nb of terminals in the city + int personsFinished; //nb of persons that finished + pthread_barrier_t b; //barrier to wait for every person + struct terminal *terminals; //all the terminals in the city +``` + +- d'abord le define USLEEP permettant d'activer les attentes usleep ou non +- la structure `city` qui contient toutes les variables partagée entre les threads, notamment personsFinished, et les terminals (les sites) +- chaque site contient un semaphore qui incrémente le BikeFree si qqun pose un vélo, puis décrémente le FreeSlots car une place de park sera prise. + - il contient également un mutex par terminal qui sera partagé aussi lorsque l'on accède aux variables partagées nb_bikesParked correspondant aux velos garés sur un terminal. + +**civilian.h** + **Truck.h** +civilian.h contient une structure `person` qui contient l'essentiel de valeurs pour compter, mais aussi **afficher** les resultats sur le terminal. +``` +struct person{ + int num_thread; + int nb_travels; + int max_travels; + int i_terminals; + int nbTerminals; + int nslots; +}; +``` +Avec la structure city passée en variable globale dans la structure dans `civilian.c`. + +Truck.h, das le principe fonctionne pareil, mais avec city passé directement en pointeur dans sa structure. +``` +struct Truck{ + int num_thread; + int n_bike; + int i_terminals; + int nbterminals; + int nslots; + int nbpersons; + struct city *city; +}; +``` + +L'algorithme en lui même reprends le principe de producer consumer vu en cours : +- 2 types de sémaphores (1: velo de libre, 2: place de park de libre) +Les deux sont mis à jours ainsi : +1. qqun veut **prendre** un velo (est d'abord considéré en attente incrémenté dans des mutex), il va donc lancer un sem_wait en attente qu'un **velo** sois libre, pour ensuite le prendre et envoyer un sem_post indiquant qu'une **place** est libres +``` +sem_wait(city_->terminals[pers->i_terminals].sem_BikeFree); +pthread_mutex_lock(city_->terminals[pers->i_terminals].mutex); +... //critical section +pthread_mutex_unlock(city_->terminals[pers->i_terminals].mutex); +sem_post(city_->terminals[pers->i_terminals].sem_FreeSlot); +``` +2. la personne fait son voyage jusqu'à j (j!=i) et se mets à nouveau en attente pour cette fois **poser** son velo avec sem_wait -> **place** de libre. au quel cas, il fait comme plus haut mais en inverse. +``` +sem_wait(city_->terminals[j].sem_FreeSlot); +pthread_mutex_lock(city_->terminals[j].mutex); +... //critical section +pthread_mutex_unlock(city_->terminals[j].mutex); +sem_post(city_->terminals[j].sem_BikeFree); +``` +3. autrement, c'est le camion qui va de la même manière s'occuper de placer ou de prendre un velo comme indiqué sur le tp. + +Ce qui conclu ce TP. merci ! \ No newline at end of file diff --git a/G17_bykes/civilian.c b/G17_bykes/civilian.c index 0f1a6b60a4ce35bf1b023f12743b56f88ae14aca..934ee8a14613415e72918d84c64c2cb5f9177764 100644 --- a/G17_bykes/civilian.c +++ b/G17_bykes/civilian.c @@ -45,9 +45,6 @@ void *Persons(void *arg){ pthread_mutex_lock(city_->terminals[pers->i_terminals].mutex); city_->terminals[pers->i_terminals].nb_P_waiting -= 1; city_->terminals[pers->i_terminals].nb_bikesParked -= 1; //critical section - //if(pers->i_terminals==4){ - //printf("person %d leaves terminal %d by bike\n", pers->num_thread, pers->i_terminals); - //} pthread_mutex_unlock(city_->terminals[pers->i_terminals].mutex); sem_post(city_->terminals[pers->i_terminals].sem_FreeSlot); //if(pers->i_terminals==4){ @@ -101,9 +98,9 @@ void *Persons(void *arg){ pers->nb_travels += 1; } printf("person %d stops\n", pers->num_thread); - pthread_mutex_lock(city_->terminals[pers->i_terminals].mutex); + //pthread_mutex_lock(city_->terminals[pers->i_terminals].mutex); city_->personsFinished += 1; - pthread_mutex_unlock(city_->terminals[pers->i_terminals].mutex); + //pthread_mutex_unlock(city_->terminals[pers->i_terminals].mutex); pthread_barrier_wait(&city_->b); return NULL;