diff --git a/bykes_V1/.vscode/settings.json b/bykes_V1/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..5a51a28efb30dd3f77571eb8dcfac4718a8b4d89 --- /dev/null +++ b/bykes_V1/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "threads.h": "c" + } +} \ No newline at end of file diff --git a/bykes_V1/Makefile b/bykes_V1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a12c3ef709e7e6ae77a4b17a9350827397a2acdc --- /dev/null +++ b/bykes_V1/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/bykes_V1/bykes b/bykes_V1/bykes new file mode 100755 index 0000000000000000000000000000000000000000..9f035935639bf51f30aa1418f357398ca1239910 Binary files /dev/null and b/bykes_V1/bykes differ diff --git a/bykes_V1/main.c b/bykes_V1/main.c new file mode 100644 index 0000000000000000000000000000000000000000..359d1c6b791e3642962b6bc03bd7e5ed887e32c1 --- /dev/null +++ b/bykes_V1/main.c @@ -0,0 +1,334 @@ +#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 TRUCK_CAPACITE_MAX 4 +#define TRUCK_CAPACITE_TYP 2 +#define CITY_CAPACITY_MIN 2 + +#define DEPOT 0 + +#define USLEEP 1 + +sem_t *sem_FreeSlot; +sem_t *sem_BikeFree; +pthread_mutex_t *mutex; +pthread_barrier_t b; + +int personsFinished=0; + +struct person{ + int num_thread; + int nb_travels; + int max_travels; + int i_terminals; + int nbterminals; + int nslots; +}; + +struct Truck{ + int num_thread; + int n_bike; + int i_terminals; + int nbterminals; + int nslots; + int nbpersons; +}; + +struct city{ + int nb_bikesParked; + int nb_P_waiting; +}; + +int rand_Dc(); +int rand_D(); +//void persons_PassiveMode(void *arg); +void *trucks(void *arg); +void *Persons(void *arg); +struct city *terminals; //this table is the size of the number of terminals, each terminals 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 nbterminals = atoi(argv[1]); //S 10 + int nbpersons = atoi(argv[2]); //H 100 + int nbtravels = atoi(argv[3]); //M 10 + int nbslots = atoi(argv[4]); //N 10 + nbterminals += 1; + srand(0); + + + pthread_t *threadpersons = malloc(sizeof(pthread_t)*nbpersons); + pthread_t *threadTruck = malloc(sizeof(pthread_t)); + terminals = calloc(nbterminals, sizeof(struct city)); + struct person *persons = calloc(nbpersons, sizeof(struct person)); + struct Truck *truck = malloc(sizeof(struct Truck)); + + for(int j = 0; j<nbterminals; j++){ + terminals[j].nb_bikesParked = nbslots-2; + terminals[j].nb_P_waiting = 0; + } + terminals[DEPOT].nb_bikesParked = 0; + + truck->i_terminals = 0; + truck->n_bike = TRUCK_CAPACITE_TYP; + truck->nslots = nbslots; + truck->num_thread = nbpersons; + truck->nbterminals = nbterminals; + truck->nbpersons = nbpersons; + + sem_BikeFree = malloc(sizeof(sem_t)*nbterminals); + sem_FreeSlot = malloc(sizeof(sem_t)*nbterminals); + mutex = malloc(sizeof(pthread_mutex_t)*nbterminals); + + for(int x =0; x<nbterminals; x++){ + sem_init(&sem_BikeFree[x], 0, nbslots-2);//8); + sem_init(&sem_FreeSlot[x], 0, nbslots-(nbslots-2));//2); + pthread_mutex_init(&mutex[x], NULL); //mutex du truck + } + + pthread_barrier_init(&b, NULL, nbpersons); + + if(pthread_create(threadTruck, NULL, trucks, (void*)truck)!=0){ + perror("thread creation error"); + return EXIT_FAILURE; + } + for(int i=0; i<nbpersons; i++){ + persons[i].max_travels = nbtravels; + persons[i].nslots = nbslots; + persons[i].nbterminals = nbterminals; + persons[i].num_thread = i; + persons[i].nb_travels = 0; + persons[i].i_terminals = (rand()%(persons[i].nbterminals - 1))+1; + if(pthread_create(&threadpersons[i], NULL, Persons, (void*)&persons[i])!=0){ + perror("thread creation error"); + return EXIT_FAILURE; + } + } + + //pthread_barrier_wait(&b); + if(pthread_join(*threadTruck, NULL)){ + perror("thread join error"); + return EXIT_FAILURE; + } + //thread join + for(int i=0; i<nbpersons; i++){ + if(pthread_join(threadpersons[i], NULL)){ + perror("thread join error"); + return EXIT_FAILURE; + } + } + + + printf("***************** CYCLING TERMINATED ***************\n"); + int sum=0; + for(int i=1; i<nbterminals; i++){ + printf("Terminal %d contains %d bikes\n", i, terminals[i].nb_bikesParked); + sum+=terminals[i].nb_bikesParked; + } + printf("total number of bikes in town: %d, in depot: %d, in truck: %d, total: %d\n", sum, terminals[DEPOT].nb_bikesParked, truck->n_bike, truck->n_bike+terminals[DEPOT].nb_bikesParked+sum); + + + //free the memory + for(int i=0; i<nbterminals; i++){ + sem_destroy(&sem_BikeFree[i]); + sem_destroy(&sem_FreeSlot[i]); + pthread_mutex_destroy(&mutex[i]); + } + pthread_barrier_destroy(&b); + free(threadpersons); + free(threadTruck); + free(sem_BikeFree); + free(sem_FreeSlot); + free(mutex); + free(persons); + free(truck); + free(terminals); + return EXIT_SUCCESS; +} + +void *Persons(void *arg){ + struct person *hab = (struct person*)arg; + int j=0; + int val; + // inside a Mtravels loop for each persons + while(hab->nb_travels < hab->max_travels){ + //waits for a bike in terminals i + //if(hab->i_terminals==4){ + sem_getvalue(&sem_FreeSlot[hab->i_terminals],&val); + pthread_mutex_lock(&mutex[hab->i_terminals]); + printf("(GET) person %d starts from terminal %d (%d bykes, %d persons waiting, semslotsFree_val : %d)\n", hab->num_thread, hab->i_terminals, terminals[hab->i_terminals].nb_bikesParked, terminals[hab->i_terminals].nb_P_waiting, val);//terminals[hab->i_terminals].nb_P_waiting); + pthread_mutex_unlock(&mutex[hab->i_terminals]); + //} + + if(terminals[hab->i_terminals].nb_bikesParked<=0){// && hab->i_terminals == 4){ + printf("person %d is STUCK at terminal %d: rack empty : %d bikes\n", hab->num_thread, hab->i_terminals, terminals[hab->i_terminals].nb_bikesParked); + } + + pthread_mutex_lock(&mutex[hab->i_terminals]); + terminals[hab->i_terminals].nb_P_waiting += 1; + pthread_mutex_unlock(&mutex[hab->i_terminals]); + + + sem_wait(&sem_BikeFree[hab->i_terminals]); + pthread_mutex_lock(&mutex[hab->i_terminals]); + terminals[hab->i_terminals].nb_P_waiting -= 1; + terminals[hab->i_terminals].nb_bikesParked -= 1; //critical section + //if(hab->i_terminals==4){ + //printf("person %d leaves terminal %d by bike\n", hab->num_thread, hab->i_terminals); + //} + pthread_mutex_unlock(&mutex[hab->i_terminals]); + sem_post(&sem_FreeSlot[hab->i_terminals]); + //if(hab->i_terminals==4){ + printf("person %d leaves terminal %d by bike\n", hab->num_thread, hab->i_terminals); + //} + + + //go to place j = rand()%nterminals and j != i + do{ + j = (rand()%(hab->nbterminals - 1))+1; + }while(j==hab->i_terminals); +#if USLEEP + usleep(rand_D()); +#endif + + //waits for a parkinglot to be freed and deposit his bycycle + //if(j==4){ + sem_getvalue(&sem_BikeFree[j],&val); + pthread_mutex_lock(&mutex[j]); + printf("(PUT) person %d arrives at terminal %d (%d bykes, %d persons waiting, semBikeFree_val : %d)\n", hab->num_thread, j, terminals[j].nb_bikesParked, terminals[j].nb_P_waiting, val);//terminals[j].nb_P_waiting); + pthread_mutex_unlock(&mutex[j]); + //} + + + if(terminals[j].nb_bikesParked>=hab->nslots){//} && j == 4){ + printf("person %d is STUCK at terminal %d: rack full : %d bikes\n", hab->num_thread, j, terminals[j].nb_bikesParked); + } + + pthread_mutex_lock(&mutex[j]); + terminals[j].nb_P_waiting += 1; + pthread_mutex_unlock(&mutex[j]); + + + sem_wait(&sem_FreeSlot[j]); + pthread_mutex_lock(&mutex[j]); + //deposit his bycycle + terminals[j].nb_P_waiting -= 1; + terminals[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) +#if USLEEP + usleep(rand_D()); +#endif + //changes his position from terminals i = j (j is the new terminals) + hab->i_terminals = j; + hab->nb_travels += 1; + } + printf("person %d stops\n", hab->num_thread); + pthread_mutex_lock(&mutex[hab->i_terminals]); + personsFinished += 1; + pthread_mutex_unlock(&mutex[hab->i_terminals]); + pthread_barrier_wait(&b); + //printf("machin bidule a passé la barriere !!!! : %d, tot_travels = %d\n", hab->num_thread, hab->nb_travels); + + return NULL; +} + +void *trucks(void *arg){ + struct Truck *truck = (struct Truck*)arg; + int tmp_nbBikes; + + while(personsFinished < truck->nbpersons){ + //1 : for each terminals from 1 to S (0 is the depot) + for(int i=1; i<truck->nbterminals; i++){ + //spreads the bikes evenly + //too many bikes in this terminals + tmp_nbBikes = truck->n_bike; + if(terminals[i].nb_bikesParked > (truck->nslots-2) && truck->n_bike < TRUCK_CAPACITE_MAX){ + while(terminals[i].nb_bikesParked > (truck->nslots-2) && truck->n_bike < TRUCK_CAPACITE_MAX){ + sem_wait(&sem_BikeFree[i]); + pthread_mutex_lock(&mutex[i]); + truck->n_bike += 1; + terminals[i].nb_bikesParked -= 1; + pthread_mutex_unlock(&mutex[i]); + sem_post(&sem_FreeSlot[i]); + } + + pthread_mutex_lock(&mutex[i]); + printf("truck removes %d bikes at terminal %d (%d bikes, %d persons waiting, %d left in truck)\n", truck->n_bike-tmp_nbBikes, i, terminals[i].nb_bikesParked, terminals[i].nb_P_waiting, truck->n_bike); + pthread_mutex_unlock(&mutex[i]); + } + // not enough bikes in this terminals + // until he gets at least 2 bikes (or the truck is empty) + else if(terminals[i].nb_bikesParked < CITY_CAPACITY_MIN && truck->n_bike > 0){ + tmp_nbBikes = truck->n_bike; + while(terminals[i].nb_bikesParked < CITY_CAPACITY_MIN && truck->n_bike > 0){ + sem_wait(&sem_FreeSlot[i]); + pthread_mutex_lock(&mutex[i]); + truck->n_bike -= 1; + terminals[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-truck->n_bike, i, terminals[i].nb_bikesParked, terminals[i].nb_P_waiting, truck->n_bike); + pthread_mutex_unlock(&mutex[i]); + } + } + //2: goes to the depot to rebalance the truck's content to 2 bycycles + tmp_nbBikes = truck->n_bike; + if(truck->n_bike < TRUCK_CAPACITE_TYP){ + if(terminals[DEPOT].nb_bikesParked > 0){ + while(truck->n_bike < TRUCK_CAPACITE_TYP && terminals[DEPOT].nb_bikesParked > 0){ + truck->n_bike += 1; + pthread_mutex_lock(&mutex[DEPOT]); + terminals[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", truck->n_bike-tmp_nbBikes, DEPOT, terminals[DEPOT].nb_bikesParked, terminals[DEPOT].nb_P_waiting, truck->n_bike); + pthread_mutex_unlock(&mutex[DEPOT]); + } + } + else if (truck->n_bike > TRUCK_CAPACITE_TYP){ + while(truck->n_bike > TRUCK_CAPACITE_TYP){ + truck->n_bike -= 1; + pthread_mutex_lock(&mutex[DEPOT]); + terminals[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-truck->n_bike, DEPOT, terminals[DEPOT].nb_bikesParked, terminals[DEPOT].nb_P_waiting, truck->n_bike); + pthread_mutex_unlock(&mutex[DEPOT]); + } + //3: pause betweem 100us up to 199us +#if USLEEP + usleep(rand_Dc()); +#endif + //printf("TRUCK new loop, person's threads finished: %d\n", personsFinished); + } + printf("TRUCK end loop\n"); + return NULL; +} + +int rand_D(){ + return (rand()%999)+1000; +} + +int rand_Dc(){ + return (rand()%99)+100; +} \ No newline at end of file