Skip to content
Snippets Groups Projects
Commit 6a33b5f4 authored by ismail.abloua's avatar ismail.abloua
Browse files

revert last commit, nb groupe, sem_post avant mutex_unlock, ajout variable...

revert last commit, nb groupe, sem_post avant mutex_unlock, ajout variable wait_get/put sur chaque site
parent f8ae4eb9
Branches
No related tags found
No related merge requests found
/*
Atheeshan VIGNESWARAN, Ismaïl ABLOUA
Group 7
*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
......@@ -13,227 +16,219 @@
#define uspleep(x) usleep(x)
#endif
// Global constants
#define MAX_BIKES_TRUCK 4
// Site structure
// structure site
typedef struct {
int available_bikes;
int waiting_get;
int waiting_put;
sem_t sem_bikes;
sem_t sem_slots;
pthread_mutex_t site_mutex;
int available_bikes;
int wait_put;
int wait_get;
sem_t sem_bikes;
sem_t sem_slots;
pthread_mutex_t site_mutex;
} site_t;
// Global variables
int S = 0; // Number of sites
int H = 0; // Number of habitants
int M = 0; // Number of travels per habitant
int N = 0; // Number of slots per site
// global constants
#define MAX_BIKES_TRUCK 4
// global variables
int S = 0; // nb sites
int H = 0; // nb habitants
int M = 0; // nb travel by habitants
int N = 0; // nb slots per site
site_t* sites;
pthread_mutex_t mutex_finished_habitants;
int finished_habitants = 0;
int truck = 2; // Truck starts with 2 bikes
int depot = 0; // Depot starts empty
int truck = 2;
int depot = 0;
// Habitant routine
void* habitant_routine(void* arg) {
int id = *(int*)arg;
void habitant_routine(void* arg) {
int id_habitant = *(int*)arg;
int current_site = rand() % S;
for (int i = 0; i < M; i++) {
// Take a bike from the current site
for(int i = 0; i < M; i++) {
// init wait get
pthread_mutex_lock(&sites[current_site].site_mutex);
sites[current_site].wait_get++;
pthread_mutex_unlock(&sites[current_site].site_mutex);
// get bike from current site
sem_wait(&sites[current_site].sem_bikes);
pthread_mutex_lock(&sites[current_site].site_mutex);
sites[current_site].available_bikes--;
printf("(GET) person %d starts from terminal %d (%d bykes, %d persons waiting)\n",
id, current_site, sites[current_site].available_bikes, sites[current_site].waiting_get);
pthread_mutex_unlock(&sites[current_site].site_mutex);
sites[current_site].wait_get--;
printf("(GET) Habitant %d taking bike from site %d (%d bikes remaining, %d people waiting)\n", id_habitant, current_site, sites[current_site].available_bikes, sites[current_site].wait_get);
sem_post(&sites[current_site].sem_slots);
pthread_mutex_unlock(&sites[current_site].site_mutex);
// Travel time
usleep(1000 + rand() % 1000);
// Choose a different destination
// travel to destination site
int destination_site;
do {
destination_site = rand() % S;
} while (destination_site == current_site);
do {destination_site = rand() % S;}
while (destination_site == current_site);
current_site = destination_site;
// Arrive at destination and try to return bike
// init wait put
pthread_mutex_lock(&sites[current_site].site_mutex);
sites[current_site].waiting_put++;
printf("(PUT) person %d arrives at terminal %d (%d bykes, %d persons waiting)\n",
id, current_site, sites[current_site].available_bikes, sites[current_site].waiting_put);
sites[current_site].wait_put++;
pthread_mutex_unlock(&sites[current_site].site_mutex);
// return bike to destination site
sem_wait(&sites[current_site].sem_slots);
pthread_mutex_lock(&sites[current_site].site_mutex);
if (sites[current_site].available_bikes >= N) {
printf("person %d STUCK at terminal %d: rack full\n", id, current_site);
} else {
sites[current_site].available_bikes++;
printf("person %d leaves terminal %d by foot\n", id, current_site);
}
sites[current_site].waiting_put--;
pthread_mutex_unlock(&sites[current_site].site_mutex);
sites[current_site].available_bikes++;
sites[current_site].wait_put--;
printf("(PUT) Habitant %d returning bike to site %d (%d bikes remaining, %d people waiting)\n", id_habitant, current_site, sites[current_site].available_bikes, sites[current_site].wait_put);
sem_post(&sites[current_site].sem_bikes);
pthread_mutex_unlock(&sites[current_site].site_mutex);
// Activity time
usleep(1000 + rand() % 1000);
}
// Habitant finished all travels
printf("person %d stops\n", id);
// finished
printf("Habitant %d finished\n", id_habitant);
pthread_mutex_lock(&mutex_finished_habitants);
finished_habitants++;
pthread_mutex_unlock(&mutex_finished_habitants);
return NULL;
}
// Truck routine
void* truck_routine(__attribute__((unused)) void* arg) {
void truck_routine() {
// check if all habitants are finished
while (1) {
pthread_mutex_lock(&mutex_finished_habitants);
if (finished_habitants == H) {
pthread_mutex_unlock(&mutex_finished_habitants);
printf("TRUCK new loop, person's threads finished: %d\n", finished_habitants);
printf("(TRUCK) Truck leaving as all habitants have finished their routine.\n");
break;
}
pthread_mutex_unlock(&mutex_finished_habitants);
// Loop through all sites
for (int i = 0; i < S; i++) {
// refill site routine
for(int i = 0; i < S; i++){
pthread_mutex_lock(&sites[i].site_mutex);
// Try to take bikes if there are too many
while (truck < MAX_BIKES_TRUCK && sites[i].available_bikes > N - 2) {
sem_wait(&sites[i].sem_bikes);
sites[i].available_bikes--;
truck++;
sem_post(&sites[i].sem_slots);
printf("truck removes 1 byke at terminal %d (bykes: %d, waiting people: %d, left: in truck: %d)\n",
i, sites[i].available_bikes, sites[i].waiting_put, truck);
}
// Try to deliver bikes if not enough
while (truck > 0 && sites[i].available_bikes < 2) {
while(truck > 0 && sites[i].available_bikes < 2) {
sem_wait(&sites[i].sem_slots);
truck--;
sites[i].available_bikes++;
sem_post(&sites[i].sem_bikes);
printf("truck adds 1 byke to terminal %d (bykes: %d, waiting people: %d, left: in truck: %d)\n",
i, sites[i].available_bikes, sites[i].waiting_get, truck);
printf("(TRUCK) Truck refilling site %d (%d bikes remaining)\n", i, sites[i].available_bikes);
}
while(truck < MAX_BIKES_TRUCK && sites[i].available_bikes > N-2) {
sem_wait(&sites[i].sem_bikes);
sites[i].available_bikes--;
truck++;
sem_post(&sites[i].sem_slots);
printf("(TRUCK) Truck taking bike from site %d (%d bikes remaining)\n", i, sites[i].available_bikes);
}
pthread_mutex_unlock(&sites[i].site_mutex);
}
// Re-equilibrate truck with depot
while (truck > 2) {
truck--;
depot++;
// refill depot routine
while(truck > 2) {
printf("(DEPOT) Truck returning to depot (%d bikes in truck)\n", truck);
truck--;
depot++;
}
while (truck < 2 && depot > 0) {
depot--;
truck++;
while(truck < 2 && depot > 0) {
printf("(DEPOT) Truck returning to depot (%d bikes in truck)\n", truck);
depot--;
truck++;
}
// Small delay for truck
usleep(100 + rand() % 100);
}
return NULL;
}
// Main function
int main(int argc, char* argv[]) {
if (argc != 5) {
printf("Usage: %s <S> <H> <M> <N>\n", argv[0]);
return EXIT_FAILURE;
}
// Parse arguments
// Read arguments
S = atoi(argv[1]);
H = atoi(argv[2]);
M = atoi(argv[3]);
N = atoi(argv[4]);
if (S <= 2 || H <= 2 || M <= 0 || N <= 4) {
fprintf(stderr, "Invalid parameters: S>2, H>2, M>0, N>4 required.\n");
if(S <= 2 || H <= 2 || M <= 2 || N <= 2) {
perror("Must be: S > 2, H > 2, M > 2, N > 2");
return EXIT_FAILURE;
}
// Initialize random seed
// init random
srand(time(NULL));
// Initialize mutex
// init mutex
pthread_mutex_init(&mutex_finished_habitants, NULL);
// Initialize each site
finished_habitants = 0;
// init sites
sites = malloc(S * sizeof(*sites));
for (int i = 0; i < S; i++) {
sites[i].available_bikes = N - 2;
sites[i].waiting_get = 0;
sites[i].waiting_put = 0;
sem_init(&sites[i].sem_bikes, 0, N - 2);
sites[i].available_bikes = N-2;
sem_init(&sites[i].sem_bikes, 0, N-2);
sem_init(&sites[i].sem_slots, 0, 2);
sites[i].wait_get = sites[i].wait_put = 0;
pthread_mutex_init(&sites[i].site_mutex, NULL);
}
// Initialize threads for each habitant
int* id_habitants = malloc(H * sizeof(int));
pthread_t* threads = malloc(H * sizeof(pthread_t));
for (int i = 0; i < H; i++) {
// init habitants
int* id_habitants = malloc(H * sizeof(*id_habitants));
pthread_t* threads_habitants = malloc(H * sizeof(*threads_habitants));
for(int i = 0; i < H; i++) {
id_habitants[i] = i;
pthread_create(&threads[i], NULL, habitant_routine, &id_habitants[i]);
pthread_create(&threads_habitants[i], NULL, (void*)habitant_routine, &id_habitants[i]);
}
// Initialize truck thread
pthread_t truck_thread;
pthread_create(&truck_thread, NULL, truck_routine, NULL);
// Wait for all threads to finish
for (int i = 0; i < H; i++) {
pthread_join(threads[i], NULL);
// init truck
truck = 2;
depot = 0;
pthread_t thread_truck;
pthread_create(&thread_truck, NULL, (void*)truck_routine, NULL);
// wait for threads to finish
for(int i = 0; i < H; i++) {
pthread_join(threads_habitants[i], NULL);
}
pthread_join(truck_thread, NULL);
pthread_join(thread_truck, NULL);
// Final status
printf("\n***************** CYCLING TERMINATED ***************\n");
for (int i = 0; i < S; i++) {
printf("Terminal %d contains %d bykes\n", i, sites[i].available_bikes);
//print status; all sites bikes, truck bikes, depot bikes
printf("Final status:\n");
for(int i = 0; i < S; i++) {
printf("Site %d: %d bikes\n", i, sites[i].available_bikes);
}
printf("Truck: %d bikes\n", truck);
printf("Depot: %d bikes\n", depot);
//simple math to check if all bikes are accounted for
int total_bikes = S*(N-2) + 2;
int calculated_bikes = 0;
for(int i = 0; i < S; i++) {
calculated_bikes += sites[i].available_bikes;
}
calculated_bikes += truck;
calculated_bikes += depot;
printf("Total bikes: %d\n", total_bikes);
if(calculated_bikes != total_bikes) {
printf("Error: calculated bikes %d != total bikes %d\n", calculated_bikes, total_bikes);
} else {
printf("All bikes accounted for.\n");
}
printf("Truck contains %d bykes\n", truck);
printf("Depot contains %d bykes\n", depot);
int expected_total = S * (N - 2) + 2;
int total = truck + depot;
for (int i = 0; i < S; i++) total += sites[i].available_bikes;
printf("Total number of bykes in town: %d, expected: %d\n", total, expected_total);
if (total == expected_total)
printf("All bykes accounted for.\n");
else
printf("Mismatch in total bykes!\n");
// Cleanup
// free memory
for (int i = 0; i < S; i++) {
sem_destroy(&sites[i].sem_bikes);
sem_destroy(&sites[i].sem_slots);
pthread_mutex_destroy(&sites[i].site_mutex);
}
free(sites);
free(id_habitants);
free(threads);
free(threads_habitants);
pthread_mutex_destroy(&mutex_finished_habitants);
pthread_mutex_destroy(&mutex_finished_habitants);
return EXIT_SUCCESS;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment