Time

https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html

Defines

CLOCK_REALTIME (0u)

Settable wall-clock (calendar) time.

At boot it reads the same as CLOCK_MONOTONIC, but it can be set to an arbitrary value with clock_settime() (when the QRT_CFG_CLOCK_SETTIME_ENABLE build option is enabled).

Because it can be set, this clock is not monotonic — setting it may move the time forwards or backwards. A forward jump immediately fires any pending absolute (TIMER_ABSTIME) sleep or timer that the new time has passed; a backward jump never fires one early. Relative sleeps and timers are never affected by setting the clock, even when created with CLOCK_REALTIME.

Use this clock for calendar timestamps and absolute scheduling that should follow clock_settime() changes.

CLOCK_MONOTONIC (1u)

Monotonic time since boot.

Counts elapsed time since the system started. It always advances at a steady rate, never jumps, and cannot be set — clock_settime() rejects it with EINVAL — so it is unaffected by any wall-clock change.

Use this clock to measure how much time has elapsed. Query its resolution with clock_getres().

TIMER_ABSTIME (0x01)

Absolute time flag.

Functions

int clock_getcpuclockid(pid_t pid, clockid_t *clock_id)

Not supported.

Returns:

ENOSYS.

int clock_getres(clockid_t clock_id, struct timespec *res)

Report the granularity of clock_id into res.

Both CLOCK_MONOTONIC and CLOCK_REALTIME report the same resolution, derived from the frequency of the System Timer.

Error numbers:

Parameters:
  • clock_id – Clock identifier.

  • res – Pointer to a timespec where the resolution will be stored. Can be NULL, in which case the resolution is not stored.

Returns:

0 on success, or -1 on error.

int clock_gettime(clockid_t clock_id, struct timespec *tp)

Read the current value of clock_id into tp.

CLOCK_MONOTONIC reports the time elapsed since boot. CLOCK_REALTIME reports the wall-clock time as last set by clock_settime(). When QRT_CFG_DEFER_ENABLE is enabled the call may also be made from a deferred function or a timer callback (see qrt_defer_call()).

Error numbers:

  • EINVAL if tp is NULL or clock_id is not supported.

Parameters:
  • clock_id – Clock identifier.

  • tp – Pointer to a timespec where the current time will be stored.

Returns:

0 on success, or -1 on error.

int clock_settime(clockid_t clock_id, const struct timespec *tp)

Adjust CLOCK_REALTIME so that it currently reads tp.

Error numbers:

  • EINVAL if clock_id is not CLOCK_REALTIME.

  • EINVAL if tp is NULL or has a negative seconds value or nanoseconds outside [0, 999’999’999].

  • EINVAL if tp is later than the clock can represent (2^62 - 1 System Timer ticks).

Parameters:
  • clock_id – Clock identifier.

  • tp – Pointer to a timespec that specifies the new time for the specified clock.

Returns:

0 on success, or -1 on error.

int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp)

Block the calling thread for the duration specified by rqtp, measured on clock_id.

With TIMER_ABSTIME, rqtp is treated as a deadline on clock_id; otherwise it is treated as a relative interval. A deadline that has already passed, one with negative seconds (before the epoch) included, returns 0 at once without suspending the caller. Remaining time is not reported back: rmtp is accepted but ignored.

Error numbers:

Parameters:
  • clock_id – Clock identifier.

  • flags – Flags to control the behavior of the sleep operation.

    • TIMER_ABSTIME : the sleep time is interpreted as an absolute time.

  • rqtp – Pointer to a timespec that specifies the requested sleep duration.

  • rmtp – Not supported.

Returns:

0 on success, or error number.

void *periodic_thread(void *arg)
{
    unsigned int    *periods = (unsigned int *)arg;
    struct timespec  next;

    (void)clock_gettime(CLOCK_MONOTONIC, &next);

    for (;;)
    {
        next.tv_nsec += 10000000L;
        if (next.tv_nsec >= 1000000000L)
        {
            next.tv_nsec -= 1000000000L;
            next.tv_sec++;
        }
        (void)clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
                              &next, NULL);

        (*periods)++;
    }

    return NULL;
}

int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)

Block the calling thread for the relative duration rqtp.

Equivalent to clock_nanosleep() against CLOCK_REALTIME with no flags. Remaining time is not reported back.

Error numbers:

  • EINVAL if rqtp is NULL or has a negative seconds value or nanoseconds outside [0, 999’999’999].

Parameters:
  • rqtp – Pointer to a timespec that specifies the requested sleep duration.

  • rmtp – Not supported.

Returns:

0 on success, or -1 on error.

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

Allocate a kernel timer and bind it to an expiration callback.

The timer is allocated from the privileged kernel heap and released by timer_delete(). Signal notification is not supported: evp must either request SIGEV_NONE (callback-less timer) or SIGEV_THREAD (invoke sigev_notify_function on expiry).

The callback does not run in a thread: the kernel calls it directly on expiry, in the same context as a deferred call, and no thread runs until it returns. It must not block. Of the services declared here it may call only clock_gettime(), timer_gettime() and timer_settime(), and only when QRT_CFG_DEFER_ENABLE is enabled.

Because the callback runs in kernel context, with MPU support only a privileged thread can request SIGEV_THREAD; an unprivileged caller gets EPERM and no timer is created. SIGEV_NONE timers need no privilege.

Note

errno:

  • EINVAL if the clock ID is invalid.

  • EINVAL if timerid is NULL.

  • ENOTSUP if evp is NULL or specifies an unsupported notification type (e.g. SIGEV_SIGNAL).

  • EPERM if evp requests SIGEV_THREAD and the caller is unprivileged (only with MPU support).

  • EAGAIN if the limit on the number of existing timers is reached.

  • ENOMEM if the kernel heap has insufficient memory for the timer.

    static timer_t               timer;
    static volatile unsigned int expirations;
    
    static void on_expiry(union sigval value)
    {
        (void)value;
        expirations++;
    }
    
    int start_periodic_timer(void)
    {
        struct sigevent   sev = { .sigev_notify          = SIGEV_THREAD,
                                  .sigev_notify_function = on_expiry };
        struct itimerspec its = { .it_interval = { 0, 10000000L },
                                  .it_value    = { 0, 10000000L } };
        int               status;
    
        status = timer_create(CLOCK_MONOTONIC, &sev, &timer);
        if (status == 0)
        {
            status = timer_settime(timer, 0, &its, NULL);
        }
    
        return status;
    }
    

Parameters:
  • clockid – Clock identifier, CLOCK_MONOTONIC or CLOCK_REALTIME.

  • evp – Pointer to a sigevent that specifies the event to be delivered when the timer expires.

  • timerid – Pointer to a timer_t where the created timer ID will be stored.

Returns:

0 on success, -1 on error.

int timer_delete(timer_t timerid)

Disarm a timer and return its memory to the kernel heap.

Error numbers:

  • EINVAL if timerid does not refer to a currently allocated timer.

Parameters:
  • timerid – Timer ID to be deleted.

Returns:

0 on success, -1 on error.

int timer_getoverrun(timer_t timerid)

Not supported.

Returns:

-1 and sets errno to ENOSYS.

int timer_gettime(timer_t timerid, struct itimerspec *value)

Report the time until the next expiration and the configured reload interval of timerid.

A disarmed timer reports zero in it_value. A non-periodic timer reports zero in it_interval. When QRT_CFG_DEFER_ENABLE is enabled the call may also be made from a deferred function or a timer callback (see qrt_defer_call()).

Error numbers:

  • EINVAL if timerid does not refer to a currently allocated timer, or value is NULL.

Parameters:
  • timerid – Timer ID.

  • value – Pointer to a itimerspec where the remaining time will be stored.

Returns:

0 on success, -1 on error and errno set.

int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue)

Arm, re-arm, or disarm timerid.

The new configuration in value is applied as follows:

  • it_value zero disarms the timer, with or without TIMER_ABSTIME, whatever it_interval holds. it_interval still sets the reload interval that timer_gettime() reports, zero when it is malformed.

  • Non-zero it_value arms a one-shot timer when it_interval is zero, or a periodic timer otherwise.

  • With TIMER_ABSTIME, it_value is treated as a deadline on the clock chosen at timer_create() time; otherwise it is relative. A deadline that has already passed, one with negative seconds (before the epoch) included, expires at once.

An expiration later than the clock can represent (2^62 - 1 System Timer ticks) is held at that limit, and a periodic timer whose next expiration reaches or passes it is disarmed after its last expiration.

The previous configuration is written to ovalue when it is non-NULL. When QRT_CFG_DEFER_ENABLE is enabled the call may also be made from a deferred function or a timer callback (see qrt_defer_call()).

Error numbers:

  • EINVAL if timerid does not refer to a currently allocated timer, or value is NULL.

  • EINVAL if value has a non-zero it_value and contains a malformed timespec (nanoseconds outside [0, 999’999’999], or negative seconds in it_interval or in a relative it_value).

Parameters:
  • timerid – Timer ID.

  • flags – Flags to control the behavior of the timer set operation.

  • value – Pointer to a itimerspec that specifies the new timer settings.

  • ovalue – Pointer to a itimerspec where the old timer settings will be stored. Can be NULL if not needed.

Returns:

0 on success, -1 on error and errno set.

int timeout_restart(timer_t timer)
{
    struct itimerspec one_shot = { .it_value = { 0, 100000000L } };

    return timer_settime(timer, 0, &one_shot, NULL);
}

int timeout_cancel(timer_t timer)
{
    struct itimerspec disarm = { .it_value = { 0, 0 } };

    return timer_settime(timer, 0, &disarm, NULL);
}

struct timespec
#include <time.h>

Time value expressed as seconds plus nanoseconds.

Public Members

time_t tv_sec

Seconds.

long tv_nsec

Nanoseconds. [0, 999’999’999]

struct itimerspec
#include <time.h>

Timer setting: initial expiration and reload period.

Public Members

struct timespec it_interval

Timer period.

struct timespec it_value

Timer expiration.