Interval Timer Interfaces
Real-time applications often schedule actions by using interval timers. Interval timers can be either of two types: a one-shot type or a periodic type.
A one-shot is an armed timer that is set to an expiration time relative to either a current time or an absolute time. The timer expires once and is disarmed. This type of a timer is useful for clearing buffers after the data has been transferred to storage, or to time-out an operation.
A periodic timer is armed with an initial expiration time, either absolute or relative, and a repetition interval. Every time the interval timer expires, the timer is reloaded with the repetition interval. The timer is then rearmed. This timer is useful for data logging or for servo-control. In calls to interval timer interfaces, time values that are smaller than the timer's resolution are rounded up to the next multiple of the hardware timer interval. This interval is typically 10ms.
Oracle Solaris has two sets of timer interfaces. The setitimer
()
and
getitimer
()
interfaces operate fixed set timers, which are
called the BSD timers, using the timeval
structure to specify
time intervals. The POSIX timers, which are created with the
timer-create
command, operate the POSIX clock,
CLOCK_REALTIME
. POSIX timer operations are expressed in terms
of the timespec
structure.
The getitimer
()
and setitimer
()
functions retrieve and
establish, respectively, the value of the specified BSD interval timer. The three
BSD interval timers that are available to a process include a real-time timer
designated ITIMER_REAL
. If a BSD timer is armed and allowed to
expire, the system sends an appropriate signal to the process that set the timer.
For more information, see the
getitimer
(2) and
setitimer
(2) man pages.
The timer_create
command routine can create up to TIMER_MAX
POSIX timers. The caller can specify what signal and what
associated value are sent to the process when the timer expires. The timer_settime
()
and timer_gettime
()
routines retrieve and establish
respectively the value of the specified POSIX interval timer. POSIX timers
can expire while the required signal is pending delivery. The timer expirations
are counted, and timer_getoverrun
()
retrieves the count.
The timer_delete
command deallocates a POSIX timer.
The following example illustrates how to use setitimer
()
to generate a
periodic interrupt, and how to control the arrival of timer interrupts.
Example 11-2 Controlling Timer Interrupts
#include <unistd.h> #include <signal.h> #include <sys/time.h> #define TIMERCNT 8 void timerhandler(); int timercnt; struct timeval alarmtimes[TIMERCNT]; main() { struct itimerval times; sigset_t sigset; int i, ret; struct sigaction act; siginfo_t si; /* block SIGALRM */ sigemptyset (&sigset); sigaddset (&sigset, SIGALRM); sigprocmask (SIG_BLOCK, &sigset, NULL); /* set up handler for SIGALRM */ act.sa_action = timerhandler; sigemptyset (&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction (SIGALRM, &act, NULL); /* * set up interval timer, starting in three seconds, * then every 1/3 second */ times.it_value.tv_sec = 3; times.it_value.tv_usec = 0; times.it_interval.tv_sec = 0; times.it_interval.tv_usec = 333333; ret = setitimer (ITIMER_REAL, ×, NULL); printf ("main:setitimer ret = %d\n", ret); /* now wait for the alarms */ sigemptyset (&sigset); timerhandler (0, si, NULL); while (timercnt < TIMERCNT) { ret = sigsuspend (&sigset); } printtimes(); } void timerhandler (sig, siginfo, context) int sig; siginfo_t *siginfo; void *context; { printf ("timerhandler:start\n"); gettimeofday (&alarmtimes[timercnt], NULL); timercnt++; printf ("timerhandler:timercnt = %d\n", timercnt); } printtimes () { int i; for (i = 0; i < TIMERCNT; i++) { printf("%ld.%0l6d\n", alarmtimes[i].tv_sec, alarmtimes[i].tv_usec); } }