From c85abfa7c3764406a2beae9d4fbb15a91331a0ae Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Wed, 4 Sep 2024 12:30:00 +0200 Subject: [PATCH] Synchronized Process Manager exercise --- synchronize_chp5/pid_manager.c | 98 ++++++++++++++++++++++++++++++++++ synchronize_chp5/pid_manager.h | 16 ++++++ 2 files changed, 114 insertions(+) create mode 100644 synchronize_chp5/pid_manager.c create mode 100644 synchronize_chp5/pid_manager.h diff --git a/synchronize_chp5/pid_manager.c b/synchronize_chp5/pid_manager.c new file mode 100644 index 0000000..e365672 --- /dev/null +++ b/synchronize_chp5/pid_manager.c @@ -0,0 +1,98 @@ +#include "pid_manager.h" +#include +#include +#include +#include +#include +#include + +#define MIN_PID 300 +#define MAX_PID 5000 +#define SIZE (MAX_PID - MIN_PID + 1) + +typedef struct __PID_REGISTRY__ { + bool *pids; + pthread_mutex_t mtx; +} pid_registry_t; + +void *runner(void *param); + +pid_registry_t registry; + +int allocate_map(void) { + registry.pids = (bool *)calloc(SIZE, sizeof(bool)); + if (pthread_mutex_init(®istry.mtx, NULL) != 0) { + perror("Cannot create mutex\n"); + return -1; + } + return 1; +} + +int deallocate_map(void) { + if (registry.pids == NULL) { + perror("Cannot deallocate unallocated struct\n"); + return 1; + } + free(registry.pids); + registry.pids = NULL; + + return pthread_mutex_destroy(®istry.mtx); +} + +int allocate_pid(void) { + int pid = -1; + for (int i = 0; i < SIZE && pid == -1; i++) { + pthread_mutex_lock(®istry.mtx); + if (!registry.pids[i]) { + registry.pids[i] = true; + pid = i + MIN_PID; + } + pthread_mutex_unlock(®istry.mtx); + } + return pid; +} + +void release_pid(int pid) { + if (pid >= MIN_PID && pid <= MAX_PID) { + pthread_mutex_lock(®istry.mtx); + registry.pids[pid - MIN_PID] = false; + pthread_mutex_unlock(®istry.mtx); + } +} + +void *runner(void *param) { + const pid_t self = gettid(); + const int pid = allocate_pid(); + printf("Run thread %d handle PID %d.\n", self, pid); + sleep(rand() % 31); + release_pid(pid); + printf("Thread %d ended\n", self); + pthread_exit(0); +} + +int main(void) { + const int thread_count = 100; + pthread_t threads[thread_count]; + + if (!allocate_map()) { + perror("Failed to allocate PID Manager\n"); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < thread_count; i++) { + printf("Created thread %d\n", i); + pthread_create(&threads[i], NULL, runner, NULL); + } + + for (int i = 0; i < thread_count; i++) { + printf("Waiting thread %d\n", i); + pthread_join(threads[i], NULL); + } + + if (!deallocate_map()) { + perror("Failed to deallocate PID Manager\n"); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/synchronize_chp5/pid_manager.h b/synchronize_chp5/pid_manager.h new file mode 100644 index 0000000..e116507 --- /dev/null +++ b/synchronize_chp5/pid_manager.h @@ -0,0 +1,16 @@ +#if !defined(__PID_MANGER_H__) +#define __PID_MANGER_H__ +#define _GNU_SOURCE + +// Crea e inizializza una struttura per rappresentare i pid; +// restituisce -1 in caso di insuccesso e 1 in caso di successo. +int allocate_map(void); + +// Alloca e restituisce un pid, restituisce -1 se non รจ possibile +// assegnare un PID (tutti i pid sono in uso). +int allocate_pid(void); + +// Rilascia un pid +void release_pid(int pid); + +#endif