Re: [PATCH] i386: Selectable Frequency of the Timer Interrupt

From: George Anzinger
Date: Mon Jul 11 2005 - 19:43:52 EST


Martin J. Bligh wrote:
Lots of people have switched from 2.4 to 2.6 (100 Hz to 1000 Hz) with no impact in
stability, AFAIK. (I only remember some weird warning about HZ with debian woody's
ps).


Yes, that's called "progress" so no one complained. Going back is
called a "regression". People don't like those as much.


That's a very subjective viewpoint. Realize that this is a balancing
act between latency and overhead ... and you're firmly only looking
at one side of the argument, instead of taking a compromise in the
middle ...

If I start arguing for 100HZ on the grounds that it's much more efficient,
will that make 250/300 look much better to you? ;-)

I would like to interject an addition data point, and I will NOT be subjective. The nature of the PIT is that it can _hit_ some frequencies better than others. We have had complaints about repeating timers not keeping good time. These are not jitter issues, but drift issues. The standard says we may not return early from a timer so any timer will either be on time or late. The amount of lateness depends very much on the HZ value. Here is what the values are for the standard CLOCK_TICK_RATE:

HZ TICK RATE jiffie(ns) second(ns) error (ppbillion)
100 1193180 10000000 1000000000 0
200 1193180 5000098 1000019600 19600
250 1193180 4000250 1000062500 62500
500 1193180 1999703 1001851203 1851203
1000 1193180 999848 1000847848 847848

The jiffie values here are exactly what the kernel uses and are based on the best one can do with the PIT hardware.

I am not suggesting any given default HZ, but rather an argumentation of the help text that goes with it. For those who want timers to repeat at one second (or multiples there of) this is useful info.

For you enjoyment I have attached the program used to print this. It allows you to try additional values...


--
George Anzinger george@xxxxxxxxxx
HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/


#define NSEC_PER_SEC 1000000000
//#define CLOCK_TICK_RATE /*100000000 */ 1193180
#define LATCH(CLOCK_TICK_RATE,HZ) ((CLOCK_TICK_RATE + HZ/2) / HZ)
#define SH_DIV(NOM,DEN,LSH) ( ((NOM / DEN) << LSH) \
+ (((NOM % DEN) << LSH) + DEN / 2) / DEN)
#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH(CLOCK_TICK_RATE,HZ), 8))
#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8))


struct {
int hz;
int clocktickrate;
} vals[] = {{100, 1193180}, {200, 1193180}, {250, 1193180}, {500, 1193180}, {1000, 1193180},{0,0}};

void do_it(int hz,int tickrate)
{
int HZ = hz;
int CLOCK_TICK_RATE = tickrate;
int tick_nsec = TICK_NSEC;
int ticks_per_sec = NSEC_PER_SEC/tick_nsec;
int sec_size = ticks_per_sec * tick_nsec;
int one_sec_p;
int err;

if (sec_size < NSEC_PER_SEC)
sec_size += tick_nsec;
one_sec_p = sec_size;
err = one_sec_p - NSEC_PER_SEC;
printf( "%4d\t%8d\t%8d\t%10d\t%8d\n",hz, tickrate, tick_nsec,
one_sec_p, err);
}

void bail(void)
{
printf("run as: as [hz [clock_tick_rate]]\n");
exit(1);
}

main(int argc, char** argv)
{
int i = 0;
int phz = 0;
int pcr = vals[0].clocktickrate;

if (argc > 1) {
phz = atoi(argv[1]);
if (!phz)
bail();
}
if (argc > 2) {
pcr = atoi(argv[2]);
if (!pcr)
bail();
}

printf("HZ \tTICK RATE\tjiffie(ns)\tsecond(ns)\t error (ppbillion)\n");
while(vals[i].hz) {
do_it(vals[i].hz, vals[i].clocktickrate);
i++;
}
if (phz)
do_it(phz, pcr);
}