I'm designing a program that consists in three threads simulating a principle of Consumer/Producer that are ControlEntrada
and ControlSalida
respectively, two of them initialize timers that generate two signals respectively and in an infinite loop waits for the signal and after capture it, it has to send to a last thread responsible to monitor and capture these signals, depending of the signal, it'll do one task or another, I think I have the main purpose of the program done but I don't know every time the timer expires and the signal is captured in sigwait, how to send to Monitorizar
thread for capture there, any ideas? This is my code:
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define NUM_THREADS 3
#define SIG_1 SIGUSR1
#define SIG_2 SIGUSR2
pthread_t hebras[NUM_THREADS];
int aforo=0;
static void error(int errnum, const char* msg)
{
char buf[127];
const char* sep = (msg != NULL ? ": " : "");
msg = (msg != NULL ? msg : "");
strerror_r(errnum, buf, sizeof(buf));
fprintf(stderr, "%s%s%s\n", msg, sep, buf);
exit(EXIT_FAILURE);
}
void *ControlEntrada(void * arg){
printf("Creando la hebra entrada.\n");
//int signum;
sigset_t * set = (sigset_t *) arg;
timer_t timer;
struct itimerspec required;
//struct itimerspec old;
struct timespec first;
struct timespec period;
struct sigevent sig;
sig.sigev_notify = SIGEV_SIGNAL;
sig.sigev_signo = SIG_1;
sig.sigev_value.sival_ptr = &timer;
if(timer_create(CLOCK_MONOTONIC, &sig, &timer)!=0){
error(errno,"error_timer_create para entrada");
}
if(clock_gettime(CLOCK_MONOTONIC, &first)!=0){
error(errno,"error_clock_gettime para entrada");
}
first.tv_sec = 0;
period.tv_sec = 1;
required.it_value = first;
required.it_interval = period;
if(sigemptyset(set)!=0){
error(errno,"error_sigemptyset para entrada");
}
if(sigaddset(set, SIG_1)!=0){
error(errno,"error_sigaddset para entrada");
}
if(pthread_sigmask(SIG_BLOCK, set, NULL)!=0){
error(errno,"error_sigprocmask para entrada");
}
if(timer_settime(timer, 0, &required, NULL)!=0){
error(errno,"error_timer_settime para entrada");
}
printf("Creado timer para la entrada.\n");
while(1){
sigwait(set, &signum);
if(signum==SIG_1){
// How to send signal to 'Monitorizar' thread?
}
}
return 0;
}
void *ControlSalida(void * arg){
printf("Hebra salida.\n");
sigset_t * set = (sigset_t *) arg;
timer_t timer;
struct itimerspec required;
//struct itimerspec old;
struct timespec first, period;
struct sigevent sig;
//sigset_t set;
int signum;
sig.sigev_notify = SIGEV_SIGNAL;
sig.sigev_signo = SIG_2;
sig.sigev_value.sival_ptr = timer;
if(clock_gettime(CLOCK_MONOTONIC, &first)!=0){
error(errno,"error_clock_gettime para salida");
}
first.tv_sec = 0;
period.tv_sec = 2;
required.it_value = first;
required.it_interval = period;
if(timer_create(CLOCK_MONOTONIC, &sig, &timer)!=0){
error(errno,"error_timer_create para salida");
}
if(sigemptyset(set)!=0){
error(errno,"error_sigemptyset para salida");
}
if(sigaddset(set, SIG_2)!=0){
error(errno,"error_sigaddset para salida");
}
if(pthread_sigmask(SIG_BLOCK, set, NULL)!=0){
error(errno,"error_sigprocmask para salida");
}
if(timer_settime(timer, 0, &required, NULL)!=0){
error(errno,"error_timer_settime para salida");
}
printf("Creado timer para la salida.\n");
while(1){
sigwait(set, &signum);
if(signum==SIG_2){
// How to send to 'Monitorizar' thread?
}
}
return 0;
}
void * Monitorizar(void * arg){
printf("Entrando en monitorizar\n");
int sig, err;
sigset_t * set = (sigset_t *) arg;
while(1){
// espera la señal
err=sigwait(set, &sig);
if(err!=EINTR){
error(err,"error_sigwait");
}
else{
if(sig==SIG_1){
// incrementamos el aforo de entrada
aforo++;
printf("Entrando gente... Aforo: %d\n",aforo);
}
else if(sig==SIG_2){
// decrementamos el aforo de salida
aforo--;
printf("Saliendo gente... Aforo: %d\n",aforo);
}
}
}
}
int main(){
sigset_t set;
pthread_attr_t attr;
int err;
pthread_attr_init(&attr);
printf("Creando en main la 3º hebra.\n");
if((err=pthread_create(&hebras[2], &attr, Monitorizar, &set))!=0){
error(err, "pthread_create");
}
//pthread_join(hebras[2],NULL);
printf("Creando en main la 1º hebra.\n");
if((err=pthread_create(&hebras[0], &attr, ControlEntrada, &set))!=0){
error(err, "pthread_create");
}
printf("Creando en main la 2º hebra.\n");
/*if((err=pthread_create(&hebras[1], &attr, ControlSalida, &set))!=0){
error(err, "pthread_create");
}*/
//pthread_join(hebras[0],NULL);
//pthread_join(hebras[1],NULL);
//return 0;
pthread_exit(NULL);
}