supervisor.c 4.01 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/**
 * @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"
25 26
#include "shared/sem.c"
#include "shared/structs.c"
27

28 29
void clean_up(void);

30 31 32 33 34 35
int main(int argc, char *argv[]) {
    if(argc > 1) {
        fprintf(stderr, "ERROR: Command takes no arguments");
        exit(EXIT_FAILURE);
    }

36 37 38 39 40
    if(atexit(clean_up) != 0) {
        fprintf(stderr, "ERROR: Cannot set exit function\n");
        exit(EXIT_FAILURE);
    }

41 42
    process_signal();

43
    /// Open shared memory objects
44
    buffer_shmfd = create_shmfd(BUFF_SHM_NAME);
45
    truncate_shm(buffer_shmfd, BUFF_SIZE);
46
    circ_buffer = (buffer_t *)open_shm(buffer_shmfd, sizeof(buffer_t));
47

48 49
    /// Open semaphores
    free_sem = open_sem(FREE_SEM_NAME, BUFF_SIZE);
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    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;
        }
69

70 71 72 73 74 75 76 77 78 79 80
        /// 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!");
81
            signal_handler(SIGINT);
82 83 84 85 86 87 88 89 90 91 92
        } 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");
        }
    }
93 94 95
    exit(EXIT_SUCCESS);
}

96

97 98 99 100 101 102 103 104 105
/**
 * @brief Function to that cleans up the resources
 * @details The function closes and destroys all semaphores,
 *          closes and destroys all shared memory objects and
 *          closes the file descriptors
 * @param none
 * @return none
 **/
void clean_up(void) {
106 107
    /// Close and destory semaphores
    close_sem(free_sem);
108
    close_sem(use_sem);
109 110 111
    close_sem(mutex);

    destroy_sem(FREE_SEM_NAME);
112
    destroy_sem(USE_SEM_NAME);
113 114 115 116
    destroy_sem(MUTEX_NAME);

    /// Close and destroy shared memory objects
    close_shm(circ_buffer, sizeof(buffer_t));
117
    destroy_shm(BUFF_SHM_NAME, buffer_shmfd);
118
}