timer_create()

Updated: May 06, 2022

Create a timer

Synopsis:

#include <signal.h>
#include <time.h>

int timer_create( clockid_t clock_id,
                  struct sigevent * evp,
                  timer_t * timerid );

Arguments:

clock_id
The clock source that you want to use; one of:
  • CLOCK_REALTIME — the standard POSIX-defined clock. Timers based on this clock wake up the processor if it's in a power-saving mode.
  • CLOCK_SOFTTIME — (a QNX Neutrino extension) this clock is active only when the processor isn't in a power-saving mode. For example, an application using a CLOCK_SOFTTIME timer to sleep wouldn't wake up the processor when the application was due to wake up. This will allow the processor to enter a power-saving mode.

    While the processor isn't in a power-saving mode, CLOCK_SOFTTIME behaves the same as CLOCK_REALTIME.

  • CLOCK_MONOTONIC — this clock always increases at a constant rate and can't be adjusted.
  • (QNX Neutrino 7.0.1 or later) CLOCK_THREAD_CPUTIME_ID or a thread CPU-time clock ID returned by pthread_getcpuclockid() or ClockId(). The timeout that you set for this type of timer represents the thread's execution time. CLOCK_THREAD_CPUTIME_ID is a special clock ID that refers to the calling thread. See Monitoring execution times in the “Understanding the Microkernel's Concept of Time” chapter of the QNX Neutrino Programmer's Guide.
    Note: You can have only one timer at a time associated with a thread. You can't currently create a timer for a process CPU-time clock.

For more information about the different clocks, see Other clock sources in the Clocks, Timers, and Getting a Kick Every So Often of Getting Started with QNX Neutrino.

evp
NULL, or a pointer to a sigevent structure containing the event that you want to deliver when the timer fires.
timerid
A pointer to a timer_t object where the function stores the ID of the new timer.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The timer_create() function creates a per-process timer using the specified clock source, clock_id, as the timing base.

Note:
  • This function fails if the clock ID corresponds to the CPU-time clock of a process or thread different from the process or thread invoking the function.
  • In order to create a timer that sends a pulse to a process belonging to a different user, your process must have the PROCMGR_AID_CONNECTION ability enabled. For more information, see procmgr_ability().
  • At most 50 timer events are generated per clock tick, to limit the consumption of system resources. If the system has a large number of timers set to expire in the same clock period, then at most 50 of the timer events will actually trigger on time; the rest will be handled on the next clock tick (subject to the same limitation of at most 50 timer events).

You can use the time ID that the function stores in timerid in subsequent calls to timer_gettime(), timer_settime(), and timer_delete().

The timer is created in the disabled state, and isn't enabled until you call timer_settime().

We recommend the following event types:

If the evp argument is NULL, a SIGALRM signal is sent to your process when the timer expires. To specify a handler for this signal, call sigaction().

Returns:

0
Success. The timerid argument is set to the timer's ID.
-1
An error occurred (errno is set).

Errors:

EAGAIN
One of the following occurred:
  • All timers are in use. You'll have to wait for a process to release one.
  • (QNX Neutrino 7.0.1 or later) There's already a timer associated with the given thread CPU-time clock.
EINVAL
One of the following occurred:
  • The clock_id isn't one of the valid CLOCK_* constants.
  • (QNX Neutrino 7.0.1 or later) You tried to create a timer for a process CPU-time clock.
EPERM
The calling process doesn't have the required permission; see procmgr_ability().

Examples:

/*
 * Demonstrate how to set up a timer that, on expiry, 
 * sends us a pulse.  This example sets the first 
 * expiry to 1.5 seconds and the repetition interval 
 * to 1.5 seconds.
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>

#define MY_PULSE_CODE   _PULSE_CODE_MINAVAIL

typedef union {
        struct _pulse   pulse;
        /* your other message structures would go 
           here too */
} my_message_t;

int main()
{
   struct sigevent         event;
   struct itimerspec       itime;
   timer_t                 timer_id;
   int                     chid;
   int                     rcvid;
   my_message_t            msg;
   struct sched_param      scheduling_params;
   int prio;

   chid = ChannelCreate(0);
 
  /* Get our priority. */
    if (SchedGet( 0, 0, &scheduling_params) != -1)
    {
       prio = scheduling_params.sched_priority;
    }
    else
    {
       prio = 10;
    }
 
   event.sigev_notify = SIGEV_PULSE;
   event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0, 
                                    chid, 
                                    _NTO_SIDE_CHANNEL, 0);
   event.sigev_priority = prio;
   event.sigev_code = MY_PULSE_CODE;
   timer_create(CLOCK_MONOTONIC, &event, &timer_id);

   itime.it_value.tv_sec = 1;
   /* 500 million nsecs = .5 secs */
   itime.it_value.tv_nsec = 500000000; 
   itime.it_interval.tv_sec = 1;
   /* 500 million nsecs = .5 secs */
   itime.it_interval.tv_nsec = 500000000; 
   timer_settime(timer_id, 0, &itime, NULL);

   /*
    * As of the timer_settime(), we will receive our pulse 
    * in 1.5 seconds (the itime.it_value) and every 1.5 
    * seconds thereafter (the itime.it_interval)
    */

   for (;;) {
       rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
       if (rcvid == 0) { /* we got a pulse */
            if (msg.pulse.code == MY_PULSE_CODE) {
                printf("we got a pulse from our timer\n");
            } /* else other pulses ... */
       } /* else other messages ... */
   }
   return(EXIT_SUCCESS);
}

Classification:

POSIX 1003.1

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes

Caveats:

This version of timer_create() is different from the QNX 4 version, which was based on a draft standard.