Add documentation, signal handling, initial supervisor and semaphor functions
This commit is contained in:
parent
0c024698e3
commit
4d9c62cb84
@ -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);
|
||||
}
|
||||
|
@ -7,16 +7,25 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h> ///< 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");
|
||||
|
@ -11,8 +11,16 @@
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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");
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <stdbool.h> ///< For boolean constants
|
||||
#include <signal.h>
|
||||
|
||||
#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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user