TimerInfo(), TimerInfo_r()

Get information about a timer

Synopsis:

#include <sys/neutrino.h>

int TimerInfo( pid_t pid,
               timer_t id,
               int flags,
               struct _timer_info* info );

int TimerInfo_r( pid_t pid,
                 timer_t id,
                 int flags,
                 struct _timer_info* info );

Arguments:

pid
The process ID that you're requesting the timer information for.
id
The ID of the timer, as returned by TimerCreate().
flags
Supported flags are:
  • _NTO_TIMER_RESET_OVERRUNS — reset the timer's overrun count to zero.
  • _NTO_TIMER_SEARCH — if this flag is specified and the timer ID doesn't exist, return information on the next timer ID. This provides a mechanism to discover all of the timers in the process.
  • _NTO_TIMER_SUPPORT_64BIT — use this bit if your process is for a 32-bit architecture and has to deal with a timer created for a 64-bit architecture. You must also pass a pointer to a _timer_info64 structure as the info argument.
  • _NTO_TI_REPORT_TOLERANCE — store the timer tolerance in the otime.interval_nsec member of the _timer_info structure.
info
A pointer to a _timer_info structure where the function can store the information about the specified timer. For more details, see struct _timer_info,” below.

You can pass NULL for this argument if the only bit set in flags is _NTO_TIMER_RESET_OVERRUNS.

Library:

libc

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

Description:

These kernel calls get information about a previously created timer specified by id, and store the information in the buffer pointed to by info.

The TimerInfo() and TimerInfo_r() functions are identical except in the way they indicate errors. See the Returns section for details.

Note:
  • Instead of using these kernel calls directly, consider calling timer_getexpstatus(), timer_getoverrun(), or timer_gettime().
  • In order to get timer information about a process belonging to a different user and simultaneously use the _NTO_TIMER_RESET_OVERRUNS flag, your process must have the PROCMGR_AID_TIMER ability enabled. In order to request information about another process, your process must have the PROCMGR_AID_XPROCESS_QUERY ability enabled. For more information, see procmgr_ability().
  • There's no generic way to query when a timer was activated. However, you can determine the activation time by reading the timer information after activation (TimerSettime() activates the timer) but before the first time the timer is fired, and then subtract the known initial interval (that is, for TimerSettime(), the value of struct _itimer nsec).

struct _timer_info

The _timer_info structure pointed to by info contains at least these members:

uint32_t flags
One or more of these bit flags:
_NTO_TI_ABSOLUTE
The timer is waiting for an absolute time to occur; otherwise, the timer is relative.
_NTO_TI_ACTIVE
The timer is active.
_NTO_TI_EXPIRED
The timer has expired.
_NTO_TI_PRECISE
The timer is precise, and excludes any default tolerance that was set for the process (see procmgr_timer_tolerance()).
_NTO_TI_PROCESS_TOLERANT
The timer is using the process's default tolerance.
_NTO_TI_TARGET_PROCESS
The timer targets the process, not a specific thread.
_NTO_TI_TOD_BASED
The timer the timer is based relative to the beginning of the Epoch (January 1, 1970, 00:00:00 GMT); otherwise, it's relative to the time that QNX Neutrino was started on the machine (see the system page qtime boot_time member).
_NTO_TI_TOLERANT
The timer has a nonzero tolerance (which could be the process's default tolerance).
int32_t tid
The thread to which the timer is directed (0 if it's directed to the process).
int32_t notify
The bottom 16 bits are the value of sigev_notify for the associated sigevent. The other bits are used internally.
clockid_t clockid
The type of clock used.
uint32_t overruns
The number of overruns.
struct sigevent event
The event dispatched when the timer expires.
struct _itimer itime
A struct _itimer with the following fields:
uint64_t nsec
When the timer is next scheduled to fire.
uint64_t interval_nsec
The timer's interval.
struct _itimer otime
The time remaining before the timer expires. If you specified _NTO_TI_REPORT_TOLERANCE in the flags argument, otime.interval_nsec is set to the timer tolerance.

For more information, see the description of TimerCreate().

Blocking states

These calls don't block.

Returns:

The ID of the timer that the information is for. If an error occurs:

Errors:

EINVAL
The timer specified by id doesn't exist.
EOVERFLOW
The timer specified by id is for a 64-bit architecture, and there isn't enough space in the 32-bit version of _timer_info to hold the information. Use the _NTO_TIMER_SUPPORT_64BIT bit, as described above.
EPERM
The calling process doesn't have the required permission; see procmgr_ability().
ESRCH
The process specified by pid doesn't exist.

Examples:

This program creates a timer and then gets information about it. The arguments are the timer's tolerance, the process's default tolerance, and a flag that indicates whether or not to use the process's default tolerance. For more information, see Tolerant and high-resolution timers in the Tick, Tock: Understanding the Microkernel's Concept of Time chapter of the QNX Neutrino Programmer's Guide.

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <sys/procmgr.h>

int main (int argc, char **argv)
{
        struct sigevent event;
        timer_t timerId;
        int tolerance = 0;
        struct itimerspec newTimerTolerance, newTimerSpec;
        int rc;
        struct _timer_info tinfo;
        struct _clockperiod period;
        int precise = 0, not_used = 0;
        uint64_t p_tolerance = 0;

        if (argc > 1) {
          tolerance = atoi (argv[1]);
        }

        if (argc > 2) {
          p_tolerance = atoi (argv[2]);
        }

        if (argc > 3) {
          precise = atoi (argv[3]);
        }

        // Set the process's default tolerance if it's nonzero.
        if (p_tolerance != 0) {
           rc = procmgr_timer_tolerance ( 0, &p_tolerance, NULL);
           if (rc == -1)
           {
              perror ("procmgr_timer_tolerance");
              return EXIT_FAILURE;
           }
        }

        event.sigev_notify = SIGEV_SIGNAL;
        event.sigev_signo = SIGUSR1;

        // Create a timer.
        rc = timer_create(CLOCK_MONOTONIC, &event, &timerId);
        if (rc == -1)
        {
          perror ("timer_create()");
          return EXIT_FAILURE;
        }

        // Set the tolerance on the timer first because
        // setting the time activates the timer.
        memset(&newTimerTolerance, 0, sizeof(newTimerTolerance));
        newTimerTolerance.it_value.tv_sec = 0;
        newTimerTolerance.it_value.tv_nsec = tolerance;
        newTimerTolerance.it_interval.tv_sec  = 0;
        newTimerTolerance.it_interval.tv_nsec = 0;
        rc = timer_settime(timerId, TIMER_TOLERANCE, &newTimerTolerance, NULL);
        if (rc == -1)
        {
          perror ("timer_settime() tolerance");
          return EXIT_FAILURE;
        }

        memset(&newTimerSpec, 0, sizeof(newTimerSpec));
        newTimerSpec.it_value.tv_sec =  5;
        newTimerSpec.it_value.tv_nsec = 5000;
        newTimerSpec.it_interval.tv_sec  = 0;
        newTimerSpec.it_interval.tv_nsec = 0;
        rc = timer_settime(timerId, precise ? TIMER_PRECISE : 0, &newTimerSpec, NULL);
        if (rc == -1)
        {
          perror ("timer_settime() time");
          return EXIT_FAILURE;
        }

        // Get the clock period.
        rc = ClockPeriod (CLOCK_MONOTONIC, NULL, &period, not_used);
        if (rc == -1)
        {
          perror ("ClockPeriod()");
          return EXIT_FAILURE;
        }
        printf ("Clock period: %d ns\n\n", period.nsec);

        // Get information about the timer.
        memset(&tinfo, 0, sizeof(struct _timer_info));
        rc = TimerInfo ( getpid(), timerId, _NTO_TI_REPORT_TOLERANCE, &tinfo);
        if (rc == -1)
        {
          perror ("TimerInfo()");
          return EXIT_FAILURE;
        }

        printf ("Timer information:\n");
        printf ("   Thread ID: %d\n", tinfo.tid);

        switch (tinfo.clockid) {
        case CLOCK_MONOTONIC:
          printf ("   CLOCK_MONOTONIC\n");
          break;

        case CLOCK_REALTIME:
          printf ("   CLOCK_REALTIME\n");
          break;

        case CLOCK_SOFTTIME:
          printf ("   CLOCK_SOFTTIME\n");
          break;

        }
        printf ("   Overruns: %d\n", tinfo.overruns);
        printf ("   Start time: %ld ns; interval: %ld ns\n", tinfo.itime.nsec,
                tinfo.itime.interval_nsec);
        printf ("   Remaining : %ld ns\n", tinfo.otime.nsec);

        if (tinfo.flags &_NTO_TI_ABSOLUTE) {
          printf ("   ABSOLUTE\n");
        } else {
          printf ("   Relative\n");
        }

        if (tinfo.flags &_NTO_TI_ACTIVE) {
          printf ("   ACTIVE\n");
        }

        if (tinfo.flags &_NTO_TI_EXPIRED) {
          printf ("   EXPIRED\n");
        }

        if (tinfo.flags &_NTO_TI_PRECISE) {
          printf ("   PRECISE\n");
        }

        if (tinfo.flags &_NTO_TI_PROCESS_TOLERANT) {
          printf ("   PROCESS_TOLERANT: %ld ns.\n", p_tolerance);
        }

        if (tinfo.flags &_NTO_TI_TARGET_PROCESS) {
          printf ("   TARGET_PROCESS\n");
        }

        if (tinfo.flags &_NTO_TI_TOD_BASED) {
          printf ("   TOD_BASED\n");
        }

        if (tinfo.flags &_NTO_TI_TOLERANT) {
           printf ("   TOLERANT");
           tolerance = tinfo.otime.interval_nsec;
           if ((tolerance > 0) && (tolerance < period.nsec)) {
              printf (" (high-resolution): %d ns.\n", tolerance);
           } else {
              printf (": %d ns.\n", tolerance);
           }

        }

        return EXIT_SUCCESS;
}

Classification:

QNX Neutrino

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