aboutsummaryrefslogtreecommitdiff
path: root/semestr-5/so/lista2/so21_lista_2/cycle.c
diff options
context:
space:
mode:
Diffstat (limited to 'semestr-5/so/lista2/so21_lista_2/cycle.c')
-rw-r--r--semestr-5/so/lista2/so21_lista_2/cycle.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/semestr-5/so/lista2/so21_lista_2/cycle.c b/semestr-5/so/lista2/so21_lista_2/cycle.c
new file mode 100644
index 0000000..7daf754
--- /dev/null
+++ b/semestr-5/so/lista2/so21_lista_2/cycle.c
@@ -0,0 +1,57 @@
+#include "csapp.h"
+
+static void signal_handler(int signum, siginfo_t *info, void *data) {
+ if (signum == SIGINT) {
+ safe_printf("(%d) Screw you guys... I'm going home!\n", getpid());
+ _exit(0);
+ }
+}
+
+static void play(pid_t next, const sigset_t *set) {
+ for (;;) {
+ printf("(%d) Waiting for a ball!\n", getpid());
+ /* TODO: Something is missing here! */
+ sigset_t mask;
+ sigfillset(&mask);
+ sigdelset(&mask, SIGUSR1);
+ sigdelset(&mask, SIGINT);
+ Sigsuspend(&mask);
+ usleep((300 + random() % 400) * 1000);
+ Kill(next, SIGUSR1);
+ printf("(%d) Passing ball to (%d)!\n", getpid(), next);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ if (argc != 2)
+ app_error("Usage: %s [CHILDREN]", argv[0]);
+
+ int children = atoi(argv[1]);
+
+ if (children < 4 || children > 20)
+ app_error("Give number of children in range from 4 to 20!");
+
+ /* Register signal handler for SIGUSR1 */
+ struct sigaction action = {.sa_sigaction = signal_handler};
+ Sigaction(SIGINT, &action, NULL);
+ Sigaction(SIGUSR1, &action, NULL);
+
+ /* TODO: Start all processes and make them wait for the ball! */
+ sigset_t mask;
+ sigfillset(&mask);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ pid_t prev_pid = getpid();
+
+ for (int i = 1; i <= children; i++) {
+ int pid = Fork();
+ if (pid == 0) {
+ play(prev_pid, NULL);
+ }
+ prev_pid = pid;
+ }
+
+ Kill(prev_pid, SIGUSR1);
+ play(prev_pid, NULL);
+ return EXIT_SUCCESS;
+}