Next: , Previous: , Up: posix   [Index]


4.19 POSIX per–process timers

The POSIX timer API allows the creation of per–process timers triggering time–periodic events by specification of two time intervals:

  1. Initial expiration: how much time before the first event.
  2. Period: how much time between two time–adjacent events. When the period is zero: only one event notification is delivered.
    time before the
    first event       period      period      period
   |               |           |           |           |
---+---------------+-----------+-----------+-----------+----
   ^               ^           ^           ^           ^
  now          1st event   2nd event   3rd event   4th event

Each timer can be started, stopped, reconfigured and queried for how much time until the next event.

Function: timer-create clock-id

Interface to the C function timer_create(), see the manual page timer_create(2). Create a new per–process interval timer, initially disarmed; if successful return an exact integer representing the timer identifier, else raise an exception.

clock-id must be an exact integer representing the identifier of a clock to be used to measure time; it can be one of the constants:

CLOCK_REALTIME                  CLOCK_MONOTONIC
CLOCK_PROCESS_CPUTIME_ID        CLOCK_THREAD_CPUTIME_ID

or the return value of clock-getcpuclockid.

The call sets up the notification as with a C language struct sigevent having: sigev_notify set to SIGEV_SIGNAL, sigev_signo set to SIGALRM, sigev.sival_int set to the timer identifier. This means the timer expirations are notified to the process by delivering SIGALRM signals.

NOTE On GNU+Linux systems: for details on struct sigevent see the manual page sigevent(7).

Function: timer-delete timer-id

Interface to the C function timer_delete(), see the manual page timer_delete(2). Delete the timer referenced by timer-id; if successful return unspecified values, else raise an exception.

Function: timer-settime timer-id flags new
Function: timer-settime timer-id flags new old

Interface to the C function timer_settime(), see the manual page timer_settime(2). Arm or disarm the timer referenced by timer-id. If successful return old or #f when old is not given; if an error occurs raise an exception.

flags can be either the fixnum zero or TIMER_ABSTIME. new must be a valid instance of struct-itimerspec, which is used to set the timer. The optional old can be #f or a valid instance of struct-itimerspec; when given: it is filled with the old timer specification.

Function: timer-gettime timer-id
Function: timer-gettime timer-id curr

Interface to the C function timer_gettime(), see the manual page timer_gettime(2). Retrieve the current timer specification associated to the timer identifier timer-id. If successful return curr or a newly built instance of struct-itimerspec; if an error occurs: raise an exception.

The optional curr must be a valid instance of struct-itimerspec, when not given a new instance of this structure type is internally built: it is filled with the current timer specification.

Function: timer-getoverrun timer-id

Interface to the C function timer_getoverrun(), see the manual page timer_getoverrun(2). Get overrun count for the timer referenced by timer-id; if successful return a non–negative exact integer representing the overrun count of the specified timer, else raise an exception.

In the following example program:

  1. We use the BUB API to block all the signals, so including SIGALRM.
  2. Then we create a POSIX timer whose expirations are notified by delivering SIGALRM signals.
  3. Then we use sigtimedwait to count the expirations.

Note very well that to recognise that a SIGALRM signal is delivered by the expiration of the timer, we have to check the si_value.sival_int field of the struct-siginfo_t, not the si_timerid field.

#!r6rs
(import (vicare)
  (prefix (vicare posix) px.)
  (vicare platform constants)
  (vicare language-extensions syntaxes))

(px.signal-bub-init)

(define timer-id
  (px.timer-create CLOCK_REALTIME))
(px.timer-settime timer-id 0
      (px.make-struct-itimerspec
         ;;one event every 1 seconds
         (px.make-struct-timespec 1 0)
         ;;the first event after 1 nanosecond
         (px.make-struct-timespec 0 1)))

(unwind-protect
    (let next ((count 0))
      (if (fx= count 3)
          count
        (let-values
            (((signo info)
              (px.sigtimedwait SIGALRM
                 (px.make-struct-timespec 2 0))))
          (define was-sigalrm?
            (= signo SIGALRM))
          (define right-timer?
            (= timer-id
               (px.struct-siginfo_t-si_value.sival_int info)))
          (next (if (and was-sigalrm? right-timer?)
                    (+ 1 count)
                  count)))))
  (px.timer-delete timer-id)
  (px.signal-bub-final))
⇒ 3

Next: , Previous: , Up: posix   [Index]