diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..15309787ada476c0907431c9af91acf70a3c95bd --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..a2c02db40ee2de14191962dea6ca10e823c0cc93 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "stdlib.h": "c", + "threads.h": "c", + "unistd.h": "c" + } +} \ No newline at end of file diff --git a/G17_bykes/.vscode/settings.json b/G17_bykes/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..5a51a28efb30dd3f77571eb8dcfac4718a8b4d89 --- /dev/null +++ b/G17_bykes/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "threads.h": "c" + } +} \ No newline at end of file diff --git a/G17_bykes/Makefile b/G17_bykes/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a12c3ef709e7e6ae77a4b17a9350827397a2acdc --- /dev/null +++ b/G17_bykes/Makefile @@ -0,0 +1,14 @@ +CC:=gcc +CFLAGS:=-Wall -Wextra -pedantic -g -fsanitize=address,undefined -fsanitize-recover=address +LDFLAGS:=-lpthread -lm +EXEC:=bykes +ARGS:=10 100 10 10 + +$(EXEC): main.c + $(CC) $(CFLAGS) $^ -o $(EXEC) $(LDFLAGS) + +clean: + rm -rf *.o $(EXEC) + +run: $(EXEC) + ./$< $(ARGS) diff --git a/G17_bykes/bykes b/G17_bykes/bykes new file mode 100755 index 0000000000000000000000000000000000000000..1fafd7cc7285dadb5a8a7f53b320f9d91b29224a Binary files /dev/null and b/G17_bykes/bykes differ diff --git a/G17_bykes/main.c b/G17_bykes/main.c new file mode 100644 index 0000000000000000000000000000000000000000..72610caf0d9895c3c307a139440ab0e7417e4fdf --- /dev/null +++ b/G17_bykes/main.c @@ -0,0 +1,329 @@ +#include <stdio.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <time.h> +#include <semaphore.h> + +#define CAMION_CAPACITE_MAX 4 +#define CAMION_CAPACITE_TYP 2 +#define SITE_CAPACITE_MIN 2 + +//#define NUM_THREAD 5 + +#define DEPOT 0 + +sem_t *sem_BorneFree; +sem_t *sem_BikeFree; +pthread_mutex_t *mutex; +pthread_barrier_t b; + +bool end = false; + +struct habitant{ + int num_thread; + int nb_trajet; + int max_trajets; + int i_site; + int nbSites; + int nbornes; +}; + +struct camionette{ + int num_thread; + int n_Velo; + int i_site; + int nbSites; + int nbornes; +}; + +struct site{ + int nb_bikesParked; + int nb_P_waiting; +}; + +int rand_Dc(); +int rand_D(); +//void habitants_PassiveMode(void *arg); +void *Camion(void *arg); +void *habitants(void *arg); +struct site *sites; //this table is the size of the number of sites, each sites has NParkinglot and each numbers represents a free parkinglot + + +int main(int argc, char **argv){ + if (argc < 5 || argc > 5){ + perror("erreur d'arguments d'entrée\n"); + return EXIT_FAILURE; + } + int nbSites = atoi(argv[1]); //S 10 + int nbHabs = atoi(argv[2]); //H 100 + int nbTrajets = atoi(argv[3]); //M 10 + int nbBorne = atoi(argv[4]); //N 10 + srand(0); + + + pthread_t *threadHabs = malloc(sizeof(pthread_t)*nbHabs); + pthread_t *threadCam = malloc(sizeof(pthread_t)); + sites = calloc(nbSites, sizeof(struct site)); + struct habitant *habs = calloc(nbHabs, sizeof(struct habitant)); + struct camionette *camion = malloc(sizeof(struct camionette)); + + for(int j = 0; j<nbSites; j++){ + sites[j].nb_bikesParked = nbBorne-2; + sites[j].nb_P_waiting = 0; + } + sites[0].nb_bikesParked = 0; //depot avec 0 velos au depart + + camion->i_site = 0; + camion->n_Velo = CAMION_CAPACITE_TYP; + camion->nbornes = nbBorne; + camion->num_thread = nbHabs; + camion->nbSites = nbSites; + + + sem_BikeFree = malloc(sizeof(sem_t)*nbSites); + sem_BorneFree = malloc(sizeof(sem_t)*nbSites); + //mutex = malloc(sizeof(pthread_mutex_t)*(nbHabs+1)); + mutex = malloc(sizeof(pthread_mutex_t)*nbSites); + + for(int x =0; x<nbSites; x++){ + sem_init(&sem_BikeFree[x], 0, 8); + sem_init(&sem_BorneFree[x], 0, 2); + pthread_mutex_init(&mutex[x], NULL); //mutex du camion + } + + pthread_barrier_init(&b, NULL, nbHabs); + + if(pthread_create(threadCam, NULL, Camion, (void*)camion)!=0){ + perror("thread creation error"); + return EXIT_FAILURE; + } + for(int i=0; i<nbHabs; i++){ + habs[i].max_trajets = nbTrajets; + habs[i].nbornes = nbBorne; + habs[i].nbSites = nbSites; + habs[i].num_thread = i; + habs[i].nb_trajet = 0; + habs[i].i_site = (rand()%(habs[i].nbSites - 1))+1; + pthread_mutex_init(&mutex[i], NULL); //mutex par habitants + if(pthread_create(&threadHabs[i], NULL, habitants, (void*)&habs[i])!=0){ + perror("thread creation error"); + return EXIT_FAILURE; + } + } + + //pthread_barrier_wait(&b); + if(pthread_join(*threadCam, NULL)){ // va retourner un truc après + perror("thread join error"); + return EXIT_FAILURE; + } + //thread join + for(int i=0; i<nbHabs; i++){ + if(pthread_join(threadHabs[i], NULL)){ //va retourner un truc après + perror("thread join error"); + return EXIT_FAILURE; + } + } + + //free the memory + for(int i=0; i<nbSites; i++){ + sem_destroy(&sem_BikeFree[i]); + sem_destroy(&sem_BorneFree[i]); + } + for(int i=0; i<nbHabs+1; i++){ + pthread_mutex_destroy(&mutex[i]); + } + pthread_barrier_destroy(&b); + free(threadHabs); + free(threadCam); + free(sem_BikeFree); + free(sem_BorneFree); + free(mutex); + int sum=0; + for(int i=0; i<nbSites; i++){ + sum+=sites[i].nb_bikesParked; + } + printf("nb de velos en fin de programme %d\n", sum); + + free(habs); + free(camion); + free(sites); + + //srand(time(NULL)); + //nb sites, nb habs, nb de voyaegs par habitants, nb de bornes par sites + return EXIT_SUCCESS; +} + +void *habitants(void *arg){ + struct habitant *hab = (struct habitant*)arg; + int j=0; + int val; + // inside a Mtrajets loop for each habitants + while(hab->nb_trajet < hab->max_trajets){ + //waits for a bike in site i + //if(hab->i_site==4){ + pthread_mutex_lock(&mutex[hab->i_site]); + printf("(GET) person %d starts from terminal %d (%d bykes, %d persons waiting, semVal : %d)\n", hab->num_thread, hab->i_site, sites[hab->i_site].nb_bikesParked, sites[j].nb_P_waiting, val);//sites[hab->i_site].nb_P_waiting); + pthread_mutex_unlock(&mutex[hab->i_site]); + //} + + sem_getvalue(&sem_BorneFree[hab->i_site],&val); + if(sites[hab->i_site].nb_bikesParked<=0){// && hab->i_site == 4){ + printf("person %d is STUCK at terminal %d: rack empty with : %d bikes\n", hab->num_thread, hab->i_site, sites[hab->i_site].nb_bikesParked); + } + + pthread_mutex_lock(&mutex[hab->i_site]); + sites[hab->i_site].nb_P_waiting += 1; + pthread_mutex_unlock(&mutex[hab->i_site]); + + + sem_wait(&sem_BikeFree[hab->i_site]); + pthread_mutex_lock(&mutex[hab->i_site]); + sites[hab->i_site].nb_P_waiting -= 1; + sites[hab->i_site].nb_bikesParked -= 1; //critical section + //if(hab->i_site==4){ + //printf("person %d leaves terminal %d by bike\n", hab->num_thread, hab->i_site); + //} + pthread_mutex_unlock(&mutex[hab->i_site]); + sem_post(&sem_BorneFree[hab->i_site]); + //if(hab->i_site==4){ + printf("person %d leaves terminal %d by bike\n", hab->num_thread, hab->i_site); + //} + + + //go to place j = rand()%nsites and j != i + do{ + j = (rand()%(hab->nbSites - 1))+1; + }while(j==hab->i_site); + usleep(rand_D()); + + + //waits for a parkinglot to be freed and deposit his bycycle + //if(j==4){ + pthread_mutex_lock(&mutex[j]); + printf("(PUT) person %d arrives at terminal %d (%d bykes, %d persons waiting, semVal : %d)\n", hab->num_thread, j, sites[j].nb_bikesParked, sites[j].nb_P_waiting, val);//sites[j].nb_P_waiting); + pthread_mutex_unlock(&mutex[j]); + //} + + sem_getvalue(&sem_BikeFree[j],&val); + if(sites[j].nb_bikesParked>=hab->nbornes){//} && j == 4){ + printf("person %d is STUCK at terminal %d: rack full : %d bikes\n", hab->num_thread, j, sites[j].nb_bikesParked); + } + + pthread_mutex_lock(&mutex[j]); + sites[j].nb_P_waiting += 1; + pthread_mutex_unlock(&mutex[j]); + + + sem_wait(&sem_BorneFree[j]); + pthread_mutex_lock(&mutex[j]); + //deposit his bycycle + sites[j].nb_P_waiting -= 1; + sites[j].nb_bikesParked += 1; //critical section + pthread_mutex_unlock(&mutex[j]); + sem_post(&sem_BikeFree[j]); + //if(j==4){ + printf("person %d leaves terminal %d by foot\n", hab->num_thread, j); + //} + + //does whatever he has to do for a D delay time (waits for rand() 1000->1999us) + usleep(rand_D()); + //changes his position from site i = j (j is the new site) + hab->i_site = j; + hab->nb_trajet += 1; + } + //printf("machin bidule finished : %d, tot_trajets = %d\n", hab->num_thread, hab->nb_trajet); + + pthread_barrier_wait(&b); + //printf("machin bidule a passé la barriere !!!! : %d, tot_trajets = %d\n", hab->num_thread, hab->nb_trajet); + + pthread_mutex_lock(&mutex[hab->i_site]); + end = true; + pthread_mutex_unlock(&mutex[hab->i_site]); + return NULL; +} + +void *Camion(void *arg){ + struct camionette *camion = (struct camionette*)arg; + int tmp_nbBikes; + + while(!end){ + //1 : for each sites from 1 to S (0 is the depot) + for(int i=1; i<camion->nbSites; i++){ + //spreads the bikes evenly + //too many bikes in this site + tmp_nbBikes = camion->n_Velo; + if(sites[i].nb_bikesParked > (camion->nbornes-2) && camion->n_Velo < CAMION_CAPACITE_MAX){ + while(sites[i].nb_bikesParked > (camion->nbornes-2) && camion->n_Velo < CAMION_CAPACITE_MAX){ + sem_wait(&sem_BikeFree[i]); + pthread_mutex_lock(&mutex[i]); + camion->n_Velo += 1; + sites[i].nb_bikesParked -= 1; + pthread_mutex_unlock(&mutex[i]); + sem_post(&sem_BorneFree[i]); + } + + pthread_mutex_lock(&mutex[i]); + printf("truck removes %d bikes at terminal %d (%d bikes, %d persons waiting, %d left in truck)\n", camion->n_Velo-tmp_nbBikes, i, sites[i].nb_bikesParked, sites[i].nb_P_waiting, camion->n_Velo); + pthread_mutex_unlock(&mutex[i]); + } + // not enough bikes in this site + // until he gets at least 2 bikes (or the camion is empty) + else if(sites[i].nb_bikesParked < SITE_CAPACITE_MIN && camion->n_Velo > 0){ + tmp_nbBikes = camion->n_Velo; + while(sites[i].nb_bikesParked < SITE_CAPACITE_MIN && camion->n_Velo > 0){ + sem_wait(&sem_BorneFree[i]); + pthread_mutex_lock(&mutex[i]); + camion->n_Velo -= 1; + sites[i].nb_bikesParked += 1; + pthread_mutex_unlock(&mutex[i]); + sem_post(&sem_BikeFree[i]); + } + + pthread_mutex_lock(&mutex[i]); + printf("truck adds %d bikes at terminal %d (%d bikes, %d persons waiting, %d left in truck)\n", tmp_nbBikes-camion->n_Velo, i, sites[i].nb_bikesParked, sites[i].nb_P_waiting, camion->n_Velo); + pthread_mutex_unlock(&mutex[i]); + } + } + //2: goes to the depot to rebalance the truck's content to 2 bycycles + tmp_nbBikes = camion->n_Velo; + if(camion->n_Velo < CAMION_CAPACITE_TYP){ + if(sites[DEPOT].nb_bikesParked > 0){ + while(camion->n_Velo < CAMION_CAPACITE_TYP && sites[DEPOT].nb_bikesParked > 0){ + camion->n_Velo += 1; + pthread_mutex_lock(&mutex[DEPOT]); + sites[DEPOT].nb_bikesParked -= 1; + pthread_mutex_unlock(&mutex[DEPOT]); + } + pthread_mutex_lock(&mutex[DEPOT]); + printf("(DEPOT) truck gets %d bikes at terminal %d (%d bikes, %d persons waiting, %d left in truck)\n", camion->n_Velo-tmp_nbBikes, DEPOT, sites[DEPOT].nb_bikesParked, sites[DEPOT].nb_P_waiting, camion->n_Velo); + pthread_mutex_unlock(&mutex[DEPOT]); + } + } + else if (camion->n_Velo > CAMION_CAPACITE_TYP){ + while(camion->n_Velo > CAMION_CAPACITE_TYP){ + camion->n_Velo -= 1; + pthread_mutex_lock(&mutex[DEPOT]); + sites[DEPOT].nb_bikesParked += 1; + pthread_mutex_unlock(&mutex[DEPOT]); + } + pthread_mutex_lock(&mutex[DEPOT]); + printf("(DEPOT) truck deposit %d bikes at terminal %d (%d bikes, %d persons waiting, %d left in truck)\n", tmp_nbBikes-camion->n_Velo, DEPOT, sites[DEPOT].nb_bikesParked, sites[DEPOT].nb_P_waiting, camion->n_Velo); + pthread_mutex_unlock(&mutex[DEPOT]); + } + //3: pause betweem 100us up to 199us + usleep(rand_Dc()); + } + printf("end camion\n"); + return NULL; +} + +int rand_D(){ + return (rand()%999)+1000; +} + +int rand_Dc(){ + return (rand()%99)+100; +} \ No newline at end of file