0

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);
    }
Enot
  • 790
  • 2
  • 15
  • 34
  • You could use a semaphore if you push "signals" on a stack (FIFO)... Check out `sem_open()` first. – Alexis Wilke Sep 08 '14 at 23:38
  • Also in pthread land, you have conditions (pthread_cond_...) which will give you a signal you can sleep on. Probably better than semaphores if you do not have to count anything. But signals are really bad because they are pre-emptive. – Alexis Wilke Sep 08 '14 at 23:54
  • possible duplicate of [POSIX threads and signals](http://stackoverflow.com/questions/2575106/posix-threads-and-signals), which asks, "How do I tell another thread that a signal has arrived?" – pilcrow Sep 12 '14 at 14:49

0 Answers0