Example B-1 demonstrates the use of SGI high-resolution timers. It will run high-resolution POSIX timers in both relative mode and absolute mode.
Example B-1. High-Resolution Timer
/*****************************************************************************
* *
* This sample program demonstrates the use of SGI high resolution timers *
* in SGI REACT. *
* *
* A simple way to build this sample program is: *
* cc -o timer_sample timer_sample.c -lrt *
* *
* Invocation example (500 usec timer): *
* ./timer_sample 500 *
* *
* Invocation example (500 usec timer on realtime cpu 2): *
* cpuset --invoke=/rtcpu2 --invokecmd=./timer_sample 500 *
* *
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <asm/unistd.h>
#include <pthread.h>
#include <strings.h>
#include <sys/time.h>
#include <getopt.h>
#include <libgen.h>
struct timespec time1;
int flag;
/* Timer has triggered, get current time and indicate completion */
void sigalarm(int signo)
{
clock_gettime(CLOCK_REALTIME,&time1);
flag = 1;
}
int timer_test(int clock_id, long nanosec) {
struct itimerspec ts;
struct sigevent se;
struct sigaction act;
sigset_t sigmask;
struct timespec sleeptime, time0;
timer_t timer_id;
long i;
int signum = SIGRTMAX;
int status;
/* Set up sleep time for loops: */
sleeptime.tv_sec = 1;
sleeptime.tv_nsec = 0;
/* Set up signal handler: */
sigfillset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = sigalarm;
sigaction(signum, &act, NULL);
/* Set up timer: */
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_SIGNAL;
se.sigev_signo = signum;
se.sigev_value.sival_int = 0;
status = timer_create(clock_id, &se, &timer_id);
if (status < 0) {
perror("timer_create");
return -1;
}
/* Start relative timer: */
ts.it_value.tv_sec = nanosec / 1000000000;
ts.it_value.tv_nsec = (nanosec % 1000000000);
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
printf("Waiting for timeout of relative timer: ");
fflush(stdout);
flag = 0;
/* Get current time for reference */
clock_gettime(CLOCK_REALTIME,&time0);
/*
* There will be some latency between getting the start time above,
* and setting the relative time in timer_settime.
*/
status = timer_settime(timer_id, 0, &ts, NULL);
if (status < 0) {
perror("timer_settime");
return -1;
}
/* Loop waiting for timer to go off */
while (!flag) nanosleep(&sleeptime, NULL);
if (time1.tv_nsec < time0.tv_nsec)
printf("Total time=%luns\n",
1000000000LL - (time0.tv_nsec - time1.tv_nsec) +
((time1.tv_sec - time0.tv_sec -1)*1000000000LL));
else
printf("Total time=%luns\n",
time1.tv_nsec - time0.tv_nsec +
((time1.tv_sec - time0.tv_sec)*1000000000LL));
/* Start absolute timer: */
printf("Waiting for timeout of absolute timer: ");
fflush(stdout);
flag = 0;
/* Get current time and add timeout to that for absolute time */
clock_gettime(CLOCK_REALTIME,&time0);
i = time0.tv_nsec + (nanosec % 1000000000);
ts.it_value.tv_nsec = i % 1000000000;
ts.it_value.tv_sec = (time0.tv_sec + (nanosec / 1000000000)) +
(i / 1000000000);
/* There should be less latency than what we saw above */
status = timer_settime(timer_id, TIMER_ABSTIME, &ts, NULL);
if (status < 0) {
perror("timer_settime");
return -1;
}
/* Loop waiting for timer to go off */
while (!flag) nanosleep(&sleeptime, NULL);
if (time1.tv_nsec < time0.tv_nsec)
printf("Total time=%luns\n",
1000000000LL - (time0.tv_nsec - time1.tv_nsec) +
((time1.tv_sec - time0.tv_sec -1)*1000000000LL));
else
printf("Total time=%luns\n",
time1.tv_nsec - time0.tv_nsec +
((time1.tv_sec - time0.tv_sec)*1000000000LL));
/* Cleanup */
timer_delete(timer_id);
return 0;
}
int main(int argc, char *argv[])
{
long timeout;
if (argc < 2) {
printf("usage: %s <timeout usec>\n", basename(argv[0]));
return -1;
}
timeout = atol(argv[1]);
if (timeout <= 0) {
printf("Timeout negative or 0 specified\n");
printf("usage: %s <timeout usec>\n", basename(argv[0]));
return -1;
}
/* Run timer_test with high resolution timer. */
printf("\nRunning with CLOCK_REALTIME (normal resolution)..\n");
if (timer_test(CLOCK_REALTIME, timeout * 1000)) {
return -1;
}
} |