147 lines
3.6 KiB
C
147 lines
3.6 KiB
C
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#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();
|
|
|
|
}
|
|
}
|
|
|
|
|