97 lines
3.5 KiB
C
97 lines
3.5 KiB
C
/**
|
|
* @file supervisor.c
|
|
* @author Ivaylo Ivanov 11777707
|
|
* @date 11.01.2018
|
|
*
|
|
* @brief Supervisor program module.
|
|
*
|
|
* The supervisor sets up the shared memory and the semaphores and initializes the circular buffer required
|
|
* for the communication with the generators. It then waits for the generators to write solutions to the
|
|
* circular buffer.
|
|
* The supervisor program takes no arguments.
|
|
* Once initialization is complete, the supervisor reads the solutions from the circular buffer and remembers the best solution so far, i.e. the solution with the least edges. Every time a better solution than the
|
|
* previous best solution is found, the supervisor writes the new solution to standard output. If a generator
|
|
* writes a solution with 0 edges to the circular buffer, then the graph is acyclic and the supervisor terminates. Otherwise the supervisor keeps reading results from the circular buffer until it receives a SIGINT
|
|
* or a SIGTERM signal.
|
|
* Before terminating, the supervisor notifies all generators that they should terminate as well. This can
|
|
* be done by setting a variable in the shared memory, which is checked by the generator processes before
|
|
* writing to the buffer. The supervisor then unlinks all shared resources and exits.
|
|
*
|
|
* SYNOPSIS
|
|
* supervisor
|
|
*
|
|
**/
|
|
#include "shared/shm.c"
|
|
#include "shared/sem.c"
|
|
#include "shared/structs.c"
|
|
|
|
void clean_up(void);
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if(argc > 1) {
|
|
fprintf(stderr, "ERROR: Command takes no arguments");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if(atexit(clean_up) != 0) {
|
|
fprintf(stderr, "ERROR: Cannot set exit function\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
process_signal();
|
|
|
|
/// Open shared memory objects
|
|
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, 0);
|
|
use_sem = open_sem(USE_SEM_NAME, 0, 0);
|
|
mutex = open_sem(MUTEX_NAME, 1, 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!");
|
|
circ_buffer -> finished = true;
|
|
signal_handler(SIGINT);
|
|
} 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");
|
|
}
|
|
}
|
|
exit(EXIT_SUCCESS);
|
|
}
|