#include #include #include #include #include #define SIGRT_READY (SIGRTMIN +3) #define SIGRT_START (SIGRTMIN +2) #define SIGRT_CHILD (SIGRTMIN +1) #define SIGRT_FINAL (SIGRTMIN +0) #define __START__ 0 #define PREPARING 1 #define EXPECTING 2 #define RECIEVING 3 #define OPERATING 4 #define __FINAL__ 5 sigset_t mask ; volatile sig_atomic_t state = __START__ ; union sigval envelope; struct sigaction descriptor; volatile sig_atomic_t state_child1 = __START__ ; volatile sig_atomic_t state_child2 = __START__ ; volatile sig_atomic_t recieved_sigrts = 0 ; pid_t child1,child2; void handleStart(int signum, siginfo_t *info, void *unused) { printf("recieved start\n"); state = OPERATING; sigaddset(& mask , SIGRT_START ); sigprocmask(SIG_SETMASK, &mask , NULL); } void handleReady(int signum, siginfo_t *info, void *unused) { printf("recieved ready\n"); if (info->si_pid == child1) state_child1 = EXPECTING; if (info->si_pid == child2) state_child2 = EXPECTING; } void handleChild(int signum, siginfo_t *info, void *unused) { printf("recieved %d\n",info->si_value.sival_int); recieved_sigrts++; } void handleFinal(int signum, siginfo_t *info, void *unused) { printf("recieved final\n"); state = __FINAL__ ; sigaddset(& mask , SIGRT_FINAL ); sigprocmask(SIG_SETMASK, &mask, NULL); } void parentBehavior(){ sigdelset(&mask,SIGRT_READY); sigprocmask(SIG_SETMASK, &mask, NULL); printf("parent expecting\n"); while (state_child1 != EXPECTING || state_child2 != EXPECTING) pause(); state = RECIEVING; sigaddset(&mask,SIGRT_READY); sigdelset(&mask,SIGRT_CHILD); sigprocmask(SIG_SETMASK, &mask, NULL); sigqueue(child1, SIGRT_START, envelope); sigqueue(child2, SIGRT_START, envelope); printf("parent recieving\n"); while (recieved_sigrts < 20) pause(); printf("parent recieved 20 sig\n"); state = __FINAL__; sigaddset(&mask,SIGRT_CHILD); sigprocmask(SIG_SETMASK, &mask, NULL); sigqueue(child1, SIGRT_FINAL, envelope); sigqueue(child2, SIGRT_FINAL, envelope); exit(EXIT_SUCCESS); } void childBehavior(pid_t parent, useconds_t delay){ srand(getpid() * time(0)); sigqueue(parent, SIGRT_READY, envelope); state = EXPECTING; printf("child expecting\n"); sigdelset(&mask, SIGRT_START); sigprocmask(SIG_SETMASK, &mask, NULL); while (state == EXPECTING) pause(); sigdelset(&mask, SIGRT_FINAL); sigprocmask(SIG_SETMASK, &mask, NULL); printf("child operating\n"); while (state == OPERATING) { envelope.sival_int = rand() % 100; sigqueue(parent, SIGRT_CHILD, envelope); struct timespec request = {0, delay}, remaining; clock_nanosleep(CLOCK_MONOTONIC, 0,&request, &remaining); } exit(EXIT_SUCCESS); } int main (int argc, char *argv[]){ printf("lauching\n"); sigfillset(&mask); sigprocmask(SIG_SETMASK , &mask, NULL); descriptor.sa_flags = SA_SIGINFO; descriptor.sa_sigaction = handleStart; sigaction(SIGRT_START, &descriptor, NULL); descriptor.sa_sigaction = handleFinal; sigaction(SIGRT_FINAL, &descriptor, NULL); descriptor.sa_sigaction = handleReady; sigaction(SIGRT_READY, &descriptor, NULL); descriptor.sa_sigaction = handleChild; sigaction(SIGRT_CHILD, &descriptor, NULL); child1 = fork(); if (child1 == 0) childBehavior(getppid(), 2e5); else { child2 = fork(); if (child2 == 0) childBehavior(getppid(),3e5); else parentBehavior(); } }