Use a periodic itimer instead of repeated calls to alarm() in

sidewaysintpr().  This increases the accuracy of the per-interval
counts when they are interpreted as rates.  Repeated calls to alarm(n)
give an average interval that is about 2 ticks larger than n and has
a large variance.  Periodic itimers normally get the average almost
right but have similarly large variance (due to scheduling delays).

Statistics utilities should use clock_gettime() to determine the
actual interval, but it is still useful to maximize the accuracy of
the interval, especially for cases like netstat -w where counts are
displayed so the program cannot hide the inaccuracy in a rate
conversion.
This commit is contained in:
Bruce Evans 2007-02-27 04:54:33 +00:00
parent e770bc6bf5
commit 93547b07b9

View File

@ -531,6 +531,7 @@ sidewaysintpr(unsigned interval1, u_long off)
struct ifnet ifnet;
u_long firstifnet;
struct ifnethead ifnethead;
struct itimerval interval_it;
struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
int line;
int oldmask, first;
@ -583,7 +584,10 @@ sidewaysintpr(unsigned interval1, u_long off)
(void)signal(SIGALRM, catchalarm);
signalled = NO;
(void)alarm(interval1);
interval_it.it_interval.tv_sec = interval1;
interval_it.it_interval.tv_usec = 0;
interval_it.it_value = interval_it.it_interval;
setitimer(ITIMER_REAL, &interval_it, NULL);
first = 1;
banner:
printf("%17s %14s %16s", "input",
@ -668,12 +672,10 @@ sidewaysintpr(unsigned interval1, u_long off)
putchar('\n');
fflush(stdout);
oldmask = sigblock(sigmask(SIGALRM));
if (! signalled) {
while (!signalled)
sigpause(0);
}
sigsetmask(oldmask);
signalled = NO;
(void)alarm(interval1);
sigsetmask(oldmask);
line++;
first = 0;
if (line == 21)
@ -684,8 +686,8 @@ sidewaysintpr(unsigned interval1, u_long off)
}
/*
* Called if an interval expires before sidewaysintpr has completed a loop.
* Sets a flag to not wait for the alarm.
* Set a flag to indicate that a signal from the periodic itimer has been
* caught.
*/
static void
catchalarm(int signo __unused)