setupPulseAndTimer()

Updated: April 19, 2023

In setupPulseAndTimer() you see the code where we define the type of timer and notification scheme. When we talked about the timer function calls in the text above, I said that the timer could deliver a signal, a pulse, or cause a thread to be created. That decision is made here (in setupPulseAndTimer()).

Notice that we used the macro SIGEV_PULSE_INIT(). By using this macro, we're effectively assigning the value SIGEV_PULSE to the sigev_notify member. (Had we used one of the SIGEV_SIGNAL*_INIT() macros instead, it would have delivered the specified signal.) Notice also that, for the pulse, we set the connection back to ourselves via the ConnectAttach() call, and give it a code that uniquely identifies it (we choose the manifest constant CODE_TIMER, something that we defined). The final parameter in the event structure initialization is the priority of the pulse; we choose SIGEV_PULSE_PRIO_INHERIT (the constant -1). This tells the kernel to set the priority of the receiving thread to the priority the process was launched at.

Near the bottom of this function, we call timer_create() to create a timer object within the kernel, and then we fill it in with data saying that it should go off in one second (the it_value member) and that it should reload with one-second repeats (the it_interval member). Note that the timer is activated only when we call timer_settime(), not when we create it.

Note: The SIGEV_PULSE notification scheme is a QNX Neutrino extension; POSIX has no concept of pulses.
/*
 *  setupPulseAndTimer
 *
 *  This routine is responsible for setting up a pulse so it
 *  sends a message with code MT_TIMER.  It then sets up a
 *  periodic timer that fires once per second.
*/

void
setupPulseAndTimer (void)
{
    timer_t             timerid;    // timer ID for timer
    struct sigevent     event;      // event to deliver
    struct itimerspec   timer;      // the timer data structure
    int                 coid;       // connection back to ourselves

    // create a connection back to ourselves
    coid = ConnectAttach (0, 0, chid, 0, 0);
    if (coid == -1) {
        fprintf (stderr, "%s:  couldn't ConnectAttach to self!\n",
                 progname);
        perror (NULL);
        exit (EXIT_FAILURE);
    }

    // set up the kind of event that we want to deliver -- a pulse
    SIGEV_PULSE_INIT (&event, coid,
                      SIGEV_PULSE_PRIO_INHERIT, CODE_TIMER, 0);

    // create the timer, binding it to the event
    if (timer_create (CLOCK_REALTIME, &event, &timerid) == -1) {
        fprintf (stderr, "%s:  couldn't create a timer, errno %d\n", 
                 progname, errno);
        perror (NULL);
        exit (EXIT_FAILURE);
    }

    // setup the timer (1s delay, 1s reload)
    timer.it_value.tv_sec = 1;
    timer.it_value.tv_nsec = 0;
    timer.it_interval.tv_sec = 1;
    timer.it_interval.tv_nsec = 0;

    // and start it!
    timer_settime (timerid, 0, &timer, NULL);
}