diff --git a/OSs/lab4/part-1/Makefile b/OSs/lab4/part-1/Makefile new file mode 100644 index 0000000..da8fa15 --- /dev/null +++ b/OSs/lab4/part-1/Makefile @@ -0,0 +1,12 @@ +targets = main +all: $(targets) + +main: main.o + $(CC) -o $@ $^ $(CFLAGS) + +%.o: %.c + $(CC) -c $^ -o $@ $(CFLAGS) + +clean: + rm -f $(targets) + rm -f *.o diff --git a/OSs/lab4/part-1/main b/OSs/lab4/part-1/main new file mode 100755 index 0000000..0a5b58f Binary files /dev/null and b/OSs/lab4/part-1/main differ diff --git a/OSs/lab4/part-1/main.c b/OSs/lab4/part-1/main.c new file mode 100644 index 0000000..1f01b24 --- /dev/null +++ b/OSs/lab4/part-1/main.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum events{ + EVENT_VICTIM_THREAD_READY, + EVENT_PRINT_BUFFER_UPDATED, + EVENTS_NR +}; + +enum threads_roles { + ROLE_VICTIM, + ROLE_KILLER, + ROLE_PRINTER, + ROLES_NR +}; + +#define ERR_PTR(ret) ((void*)(long)ret) +#define PRINTER_TIMEOUT_SECS 2 + +#define PRINT_BUFF_SIZE 256 +static sem_t sems[EVENTS_NR]; +static pthread_t threads[ROLES_NR]; +static char print_buffer[PRINT_BUFF_SIZE]; +static volatile bool run = true; + +void sig_handler(int signal) +{ + snprintf(print_buffer, PRINT_BUFF_SIZE, "signal %d recieved", signal); + pthread_exit(ERR_PTR(sem_post(&sems[EVENT_PRINT_BUFFER_UPDATED]))); +} + +void *killer_thread(void* _) +{ + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss, SIGUSR1); + if (pthread_sigmask(SIG_BLOCK, &ss, NULL)) + pthread_exit(ERR_PTR(-EFAULT)); + int ret = sem_wait(&sems[EVENT_VICTIM_THREAD_READY]); + if (ret) pthread_exit(ERR_PTR(ret)); + pthread_exit(ERR_PTR(pthread_kill(threads[ROLE_VICTIM], SIGUSR1))); +} + +void *victim_thread(void* _) +{ + int ret = sem_post(&sems[EVENT_VICTIM_THREAD_READY]); + if (ret) pthread_exit(ERR_PTR(ret)); + volatile int x = 0; // for compiler not to optimize infinite loop + while (run) { + x++; + } + pthread_exit(NULL); +} + +void *printer_thread(void* _) +{ + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss, SIGUSR1); + if (pthread_sigmask(SIG_BLOCK, &ss, NULL)) pthread_exit(ERR_PTR(-EFAULT)); + while (run) { + struct timespec ts = {0}; + int ret = timespec_get(&ts, TIME_UTC); + if (ret != TIME_UTC) pthread_exit(ERR_PTR(-EFAULT)); + ts.tv_sec += PRINTER_TIMEOUT_SECS; + if (sem_timedwait(&sems[EVENT_PRINT_BUFFER_UPDATED], &ts)) + pthread_exit(ERR_PTR(-EFAULT)); + puts(print_buffer); + memset(print_buffer, 0, PRINT_BUFF_SIZE); + } + pthread_exit(NULL); +} + +#define DO_OR_FAIL(cond) if (cond) return EXIT_FAILURE + +int main() +{ + struct sigaction sa = { + .sa_handler = sig_handler, + }; + DO_OR_FAIL(sigaction(SIGUSR1, &sa, NULL)); + DO_OR_FAIL(sem_init(&sems[EVENT_VICTIM_THREAD_READY], 0, 0)); + DO_OR_FAIL(sem_init(&sems[EVENT_PRINT_BUFFER_UPDATED], 0, 0)); + DO_OR_FAIL(pthread_create(&threads[ROLE_KILLER], NULL, killer_thread, NULL)); + DO_OR_FAIL(pthread_create(&threads[ROLE_PRINTER], NULL, printer_thread, NULL)); + DO_OR_FAIL(pthread_create(&threads[ROLE_VICTIM], NULL, victim_thread, NULL)); + + for (size_t i = 0; i < ROLES_NR; i++) { + DO_OR_FAIL(pthread_join(threads[i], NULL)); + } + return EXIT_SUCCESS; +} diff --git a/OSs/lab4/part-1/main.o b/OSs/lab4/part-1/main.o new file mode 100644 index 0000000..e93bcf4 Binary files /dev/null and b/OSs/lab4/part-1/main.o differ