System Interface Guide

Timers

This section describes the timing facilities available for real-time applications under SunOS 5.0 through 5.8. Real-time applications that use these mechanisms require detailed information from the manual pages of the routines listed in this section.

The timing functions of SunOS 5.0 through 5.8 fall into two separate areas of functionality: timestamps and interval timers. The timestamp functions provide a measure of elapsed time and allow the application to measure the duration of a state or the time between events. Interval timers allow an application to wake up at specified times and to schedule activities based on the passage of time. Although an application can poll a timestamp function to schedule itself, such an application would monopolize the processor to the detriment of other system functions.

Timestamp Functions

Two functions provide timestamps. The gettimeofday(3C) function provides the current time in a timeval structure, representing the time in seconds and microseconds since midnight, Greenwich Mean Time, on January 1, 1970. The clock_gettime(3R) function, with a clockid of CLOCK_REALTIME, provides the current time in a timespec structure, representing in seconds and nanoseconds the same time interval returned by gettimeofday(3C).

SunOS 5.0 through 5.8 uses a hardware periodic timer. For some workstations, this is the sole timing information, and the accuracy of timestamps is limited to the resolution of that periodic timer. For other platforms, a timer register with a resolution of one microsecond allows SunOS 5.0 through 5.8 to provide timestamps accurate to one microsecond.

Interval Timer Functions

Real-time applications often schedule actions 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 current time or an absolute time. The timer expires once and is disarmed. Such 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. Each time the interval timer expires it is reloaded with the repetition interval and rearmed. This timer is useful for data logging or for servo-control. In calls to interval timer functions, time values smaller than the resolution of the system hardware periodic timer are rounded up to the next multiple of the hardware timer interval (typically 10 ms).

There are two sets of timer interfaces in SunOS 5.0 through 5.8. The setitimer(2) and getitimer(2) interfaces operate fixed set timers, called the BSD timers, using the timeval structure to specify time intervals. The POSIX timers, timer_create(3RT), operate the POSIX clock, CLOCK_REALTIME. POSIX timer operations are expressed in terms of the timespec structure.

The functions getitimer(2) and setitimer(2) retrieve and establish, respectively, the value of the specified BSD interval timer. There are three BSD interval timers available to a process, including a real-time timer designated ITIMER_REAL. If a BSD timer is armed and allowed to expire, the system sends a signal appropriate to the timer to the process that set the timer.

timer_create(3RT) 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. timer_settime(3RT) and timer_gettime(3RT) retrieve and establish respectively the value of the specified POSIX interval timer. Expirations of POSIX timers while the required signal is pending delivery are counted, and timer_getoverrun(3RT) retrieves the count of such expirations. timer_delete(3RT) deallocates a POSIX timer.

Example 8-1 illustrates how to use setitimer(2) to generate a periodic interrupt, and how to control the arrival of timer interrupts.


Example 8-1 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, &times, 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);
	}
}