From 4d9c62cb844df3f8dbd4e15457e9d8eeeaf0477e Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sat, 12 Jan 2019 23:00:50 +0100 Subject: [PATCH] Add documentation, signal handling, initial supervisor and semaphor functions --- fb_arc_set/generator.c | 7 ++++ fb_arc_set/shared/sem.c | 74 ++++++++++++++++++++++++++++++++++++- fb_arc_set/shared/shm.c | 47 ++++++++++++++++++++++- fb_arc_set/shared/structs.c | 38 +++++++++++++++++-- fb_arc_set/supervisor.c | 55 ++++++++++++++++++++++++--- 5 files changed, 208 insertions(+), 13 deletions(-) diff --git a/fb_arc_set/generator.c b/fb_arc_set/generator.c index b6f5315..7fa2766 100644 --- a/fb_arc_set/generator.c +++ b/fb_arc_set/generator.c @@ -38,6 +38,8 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } + process_signal(); + /// Create a regex to check the input against regex_t regex; if(regcomp(®ex, "^[0-9]*-[0-9]*$", REG_EXTENDED|REG_NOSUB)) { @@ -66,5 +68,10 @@ int main(int argc, char *argv[]) { } } + int buffer_shmfd = create_shmfd(BUFF_SHM_NAME); + circ_buffer = (buffer_t *)open_shm(buffer_shmfd, sizeof(buffer_t)); + + int wr_pos = 0; + exit(EXIT_SUCCESS); } diff --git a/fb_arc_set/shared/sem.c b/fb_arc_set/shared/sem.c index f421865..9ed79cc 100644 --- a/fb_arc_set/shared/sem.c +++ b/fb_arc_set/shared/sem.c @@ -7,16 +7,25 @@ #include #endif +#include #include ///< For semaphores #define FREE_SEM_NAME "/11777707_free" -#define USED_SEM_NAME "/11777707_used" +#define USE_SEM_NAME "/11777707_used" #define MUTEX_NAME "/11777707_mutex" static sem_t *free_sem; -static sem_t *used_sem; +static sem_t *use_sem; static sem_t *mutex; +/** + * @brief Function that executes sem_open(3) and does error handling. + * @details The function executes sem_open(3), giving it a semaphor name and size as parameters, + * and handles the errors if any. The same behaviour as sem_open(3) should be expected. + * Returns a new semaphore + * @param sem_name, sem_size + * @return res + **/ sem_t * open_sem(char *sem_name, size_t sem_size) { sem_t *res = sem_open(sem_name, O_CREAT | O_EXCL, 0600, sem_size); if(res == SEM_FAILED) { @@ -26,6 +35,60 @@ sem_t * open_sem(char *sem_name, size_t sem_size) { return res; } +/** + * @brief Function that executes sem_getvalue(3) and does error handling. + * @details The function executes sem_getvalue(3), giving it a semaphor and size as parameters, + * and handles the errors if any. The same behaviour as sem_getvalue(3) should be expected. + * Writes the value of a semaphore to a chosen pointer + * @param sem, rem + * @return none + **/ +void getval_sem(sem_t *sem, int *res) { + if(sem_getvalue(sem, res) == -1) { + fprintf(stderr, "ERROR: Failed getting semaphore value\n"); + exit(EXIT_FAILURE); + } +} + +/** + * @brief Function that executes sem_wait(3) and does error handling. + * @details The function executes sem_wait(3), giving it a semaphor as a parameter, + * and handles the errors if any. The same behaviour as sem_wait(3) should be expected. + * If the process was terminated, the function exits + * @param sem + * @return none + **/ +void wait_sem(sem_t *sem) { + if(sem_wait(sem) == -1) { + if(errno == EINTR) { + return; + } + fprintf(stderr, "ERROR: Failed locking semaphore\n"); + exit(EXIT_FAILURE); + } +} + +/** + * @brief Function that executes sem_post(3) and does error handling. + * @details The function executes sem_post(3), giving it a semaphor as a parameter, + * and handles the errors if any. The same behaviour as sem_post(3) should be expected. + * @param sem + * @return none + **/ +void post_sem(sem_t *sem) { + if(sem_post(sem) == -1) { + fprintf(stderr, "ERROR: Failed unlocking semaphore\n"); + exit(EXIT_FAILURE); + } +} + +/** + * @brief Function that executes sem_close(3) and does error handling. + * @details The function executes sem_close(3), giving it a semaphor as a parameter, + * and handles the errors if any. The same behaviour as sem_close(3) should be expected. + * @param sem + * @return none + **/ void close_sem(sem_t *sem) { if(sem_close(sem) < 0) { fprintf(stderr, "ERROR: Failed closing semaphore\n"); @@ -33,6 +96,13 @@ void close_sem(sem_t *sem) { } } +/** + * @brief Function that executes sem_unlink(3) and does error handling. + * @details The function executes sem_unlink(3), giving it a semaphor name as a parameter, + * and handles the errors if any. The same behaviour as sem_unlink(3) should be expected. + * @param sem_name + * @return none + **/ void destroy_sem(char *sem_name) { if(sem_unlink(sem_name) < 0) { fprintf(stderr, "ERROR: Failed closing semaphore\n"); diff --git a/fb_arc_set/shared/shm.c b/fb_arc_set/shared/shm.c index fe16f55..93e0c5d 100644 --- a/fb_arc_set/shared/shm.c +++ b/fb_arc_set/shared/shm.c @@ -11,8 +11,16 @@ #include #include -#define BUFFER_SHM_NAME "/11777707_buff" +#define BUFF_SHM_NAME "/11777707_buff" +/** + * @brief Function that executes shm_open(3) and does error handling. + * @details The function executes shm_open(3), giving it a name as a param, + * and handles the errors if any. The same behaviour as shm_open(3) should be expected. + * Returns a shared memory object file descriptor + * @param shm_name + * @return shmfd + **/ int create_shmfd(char *shm_name) { int shmfd = shm_open(shm_name, O_RDWR | O_CREAT, 0600); if(shmfd == -1) { @@ -22,6 +30,13 @@ int create_shmfd(char *shm_name) { return shmfd; } +/** + * @brief Function that executes ftruncate(2) and does error handling. + * @details The function executes ftruncate(2), giving it a file descriptor and size as parameters, + * and handles the errors if any. The same behaviour as ftruncate(2) should be expected. + * @param shmfd, shm_size + * @return none + **/ void truncate_shm(int shmfd, size_t shm_size) { if(ftruncate(shmfd, shm_size) < 0) { fprintf(stderr, "ERROR: Failed truncating shared memory object\n"); @@ -29,6 +44,14 @@ void truncate_shm(int shmfd, size_t shm_size) { } } +/** + * @brief Function that executes mmap(2) and does error handling. + * @details The function executes mmap(2), giving it a file descriptor and size as parameters, + * and handles the errors if any. The same behaviour as mmap(2) should be expected. + * Returns a mapped shared memory object + * @param shmfd, shm_size + * @return shm + **/ void* open_shm(int shmfd, size_t shm_size) { void* shm; shm = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); @@ -41,10 +64,24 @@ void* open_shm(int shmfd, size_t shm_size) { return shm; } +/** + * @brief Function to write a value to shared memory object + * @details The functions copies the value of a string with a specified size to a shared memory object + * @param shm, message, message_size + * @return none + **/ void write_to_shm(void* shm, char *message, size_t message_size) { memcpy(shm, message, message_size); } +/** + * @brief Function that executes munmap(2) and does error handling. + * @details The function executes munmap(2), giving it a shared memory object and size as parameters, + * and handles the errors if any. The same behaviour as munmap(2) should be expected. + * Returns a mapped shared memory object + * @param shmfd, shm_size + * @return none + **/ void close_shm(void* shm, size_t shm_size) { if (munmap(shm, shm_size) == -1) { fprintf(stderr, "ERROR: Failed unmapping shared memory object\n"); @@ -52,6 +89,14 @@ void close_shm(void* shm, size_t shm_size) { } } +/** + * @brief Function that executes shm_unlink(3) and close(2) and does error handling. + * @details The function executes shm_unlink(3) and close(2), giving them a shared memory object name + * and a file descriptor respectively, and handles the errors if any. + * The same behaviour as shm_unlink(3) and close(2) should be expected. + * @param shm_name, shmfd + * @return none + **/ void destroy_shm(char *shm_name, int shmfd) { if (shm_unlink(shm_name) == -1) { fprintf(stderr, "ERROR: Failed unlinking shared memory object\n"); diff --git a/fb_arc_set/shared/structs.c b/fb_arc_set/shared/structs.c index a0b201b..39f6bd5 100644 --- a/fb_arc_set/shared/structs.c +++ b/fb_arc_set/shared/structs.c @@ -1,4 +1,5 @@ #include ///< For boolean constants +#include #define BUFF_SIZE 8 #define SET_MAX_SIZE 8 @@ -9,15 +10,44 @@ typedef struct edge { } edge_t; /// Struct for the feedback arc set -typedef struct fb_set { +typedef struct fb_arc_set { bool valid; + int edge_num; edge_t edges[SET_MAX_SIZE]; -} fb_set_t; +} fb_arc_set_t; /// Struct for the circular buffer typedef struct buffer { - bool terminate; - fb_set_t sets[BUFF_SIZE]; + bool finished; + short best_arc_len; + fb_arc_set_t sets[BUFF_SIZE]; } buffer_t; +static bool terminate = false; + +/** + * @brief Function to execute when the program gets a signal + * @details flips the terminate variable to true + * @param none + * @return none + **/ +static void signal_handler() { + terminate = true; +} + +/** + * @brief Function to process the signals passed by the user + * @details creates a new sigaction structure + * and changes the behaviour of the SIGINT and SIGTERM signals + * @param none + * @return none + **/ +static void process_signal(void){ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); +} + static buffer_t *circ_buffer; diff --git a/fb_arc_set/supervisor.c b/fb_arc_set/supervisor.c index 20ec17c..7f7cb98 100644 --- a/fb_arc_set/supervisor.c +++ b/fb_arc_set/supervisor.c @@ -31,27 +31,70 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } + process_signal(); + /// Open shared memory objects - int buffer_shmfd = create_shmfd(BUFFER_SHM_NAME); + int buffer_shmfd = create_shmfd(BUFF_SHM_NAME); truncate_shm(buffer_shmfd, BUFF_SIZE); circ_buffer = (buffer_t *)open_shm(buffer_shmfd, sizeof(buffer_t)); /// Open semaphores free_sem = open_sem(FREE_SEM_NAME, BUFF_SIZE); - used_sem = open_sem(USED_SEM_NAME, 0); - mutex = open_sem(MUTEX_NAME, 1); + use_sem = open_sem(USE_SEM_NAME, 0); + int free_space = 0; + int use_space = 0; + int r_pos = 0; ///< Position of the circular buffer to read from + circ_buffer->best_arc_len = __INT8_MAX__; + + fb_arc_set_t fb_arc; + while(terminate == false) { + /// Get the values of the semaphores + getval_sem(free_sem, &free_space); + getval_sem(use_sem, &use_space); + + wait_sem(use_sem); + + /// Loop until we find a place that has been written to + while(circ_buffer->sets[r_pos].valid == false) { + r_pos = (r_pos + 1) % BUFF_SIZE; + } + + /// Get the valid set and save it + fb_arc = circ_buffer->sets[r_pos]; + circ_buffer->sets[r_pos].valid = false; + + post_sem(free_sem); ///< Free the semaphore + + r_pos = (r_pos + 1) % BUFF_SIZE; ///< Increase read position + + if(fb_arc.edge_num == 0) { + /// If the graph is acyclic, set the terminate flag + puts("The graph is acyclic!"); + signal_handler(); + } else if(fb_arc.edge_num < circ_buffer->best_arc_len) { + /// Save ther best feedback arc length and print a solution + circ_buffer->best_arc_len = fb_arc.edge_num; + printf("Solution with %d edges: ", circ_buffer->best_arc_len); + + for(int i=0; i < fb_arc.edge_num; i++) { + printf("%d-%d ", fb_arc.edges[i].u, fb_arc.edges[i].v); + } + printf("\n"); + } + } /// Close and destory semaphores close_sem(free_sem); - close_sem(used_sem); + close_sem(use_sem); close_sem(mutex); destroy_sem(FREE_SEM_NAME); - destroy_sem(USED_SEM_NAME); + destroy_sem(USE_SEM_NAME); destroy_sem(MUTEX_NAME); /// Close and destroy shared memory objects close_shm(circ_buffer, sizeof(buffer_t)); - destroy_shm(BUFFER_SHM_NAME, buffer_shmfd); + destroy_shm(BUFF_SHM_NAME, buffer_shmfd); + exit(EXIT_SUCCESS); }