Add documentation, signal handling, initial supervisor and semaphor functions

This commit is contained in:
Ivaylo Ivanov 2019-01-12 23:00:50 +01:00
parent 0c024698e3
commit 4d9c62cb84
5 changed files with 208 additions and 13 deletions

View File

@ -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(&regex, "^[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);
}

View File

@ -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");

View File

@ -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");

View File

@ -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;

View File

@ -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);
}