Subject: HZ, key repeat, i386
To: None <tech-kern@netbsd.org>
From: None <dlagno@mail.nnov.ru>
List: tech-kern
Date: 03/11/2004 17:51:40
Hi,

I was just curious and attempted to rebuild current kernel for i386 with 
lower HZ.

First kern/clock.c has switch that prescribes somehow fixed choice of HZ 
values in case you use NTP.  I use ntpd so I did not messed with that 
file.

Secondly arch/i386/isa/clock.c somewhat restricts value of HZ.  It will 
panic early in boot process if HZ < 38 and TIME_FREQ == 1193182 -- as is 
in my case.

So I tested new kernel with HZ=64.  And after raising 
ISA_TIMER_MSB_TABLE_SIZE in arch/i386/isa/clock.c I tested kernels with 
HZ=32 and HZ=16.

HZ=64 works fine, but I discovered that speed of keys autorepeat in 
console raised from ~30 symbols per second with HZ=100 to ~60 symbols per 
second with HZ=64.  At the same time I noticed no difference in XFree86 
behaviour.

HZ=32 also works fine, I had no problem to rebuild kernel on that machine 
but autorepeat feature is completely unusable -- if I hold key long 
enough time to trigger autorepeat then 1024 symbols are emited 
immediately.

HZ=16 boots fine, but I stopped in configuration of cgd device -- because 
each keypress generates several symbols so I cannot enter password 
correctly.

So it appears that keyboard driver somehow incorrectly uses HZ.  Maybe it 
should be fixed somehow??

Also I can provide patch that I used to enable HZ < 38 on i386:

--- arch/i386/isa/clock.c	2003-08-07 20:28:01.000000000 +0400
+++ arch/i386/isa/clock.c.new	2004-03-11 13:32:21.000000000 +0300
@@ -328,7 +328,13 @@
  *
  * time.tv_usec += isa_timer_msb_table[cnt_msb] - isa_timer_lsb_table
[cnt_lsb];
  */
+#if HZ > 36
 #define	ISA_TIMER_MSB_TABLE_SIZE	128
+#elif HZ > 18
+#define	ISA_TIMER_MSB_TABLE_SIZE	256
+#elif HZ > 9
+#define	ISA_TIMER_MSB_TABLE_SIZE	512
+#endif
 
 u_long	isa_timer_tick;		/* the number of microseconds in a 
tick */
 u_short	isa_timer_count;	/* the countdown count for the timer */
@@ -380,34 +386,34 @@
 		/* LSB table is easy, just divide and round */
 		t = ((u_long) s * 1000000 * 2) / TIMER_FREQ;
 		isa_timer_lsb_table[s] = (u_short) ((t / 2) + (t & 
0x1));
+	}
 
+	for (s = 0; s < ISA_TIMER_MSB_TABLE_SIZE; s++) {
 		/* MSB table is zero unless the MSB is <= 
isa_timer_count */
-		if (s < ISA_TIMER_MSB_TABLE_SIZE) {
-			msb = ((u_long) s) * 256;
-			if (msb > tval) {
-				isa_timer_msb_table[s] = 0;
-			} else {
-				/*
-				 * Harder computation here, since 
multiplying
-				 * the value by 1000000 can overflow 
a long.
-				 * To avoid 64-bit computations we 
divide
-				 * the high order byte and the low 
order
-				 * byte of the numerator separately, 
adding
-				 * the remainder of the first 
computation
-				 * into the second.  The constraint 
on
-				 * TIMER_FREQ above should prevent 
overflow
-				 * here.
-				 */
-				msb = tval - msb;
-				lsb = msb % 256;
-				msb = (msb / 256) * 1000000;
-				quotient = msb / TIMER_FREQ;
-				remainder = msb % TIMER_FREQ;
-				t = ((remainder * 256 * 2)
-				    + (lsb * 1000000 * 2)) / 
TIMER_FREQ;
-				isa_timer_msb_table[s] = (u_short)
((t / 2)
-				    + (t & 0x1) + (quotient * 256));
-			}
+		msb = ((u_long) s) * 256;
+		if (msb > tval) {
+			isa_timer_msb_table[s] = 0;
+		} else {
+			/*
+			 * Harder computation here, since multiplying
+			 * the value by 1000000 can overflow a long.
+			 * To avoid 64-bit computations we divide
+			 * the high order byte and the low order
+			 * byte of the numerator separately, adding
+			 * the remainder of the first computation
+			 * into the second.  The constraint on
+			 * TIMER_FREQ above should prevent overflow
+			 * here.
+			 */
+			msb = tval - msb;
+			lsb = msb % 256;
+			msb = (msb / 256) * 1000000;
+			quotient = msb / TIMER_FREQ;
+			remainder = msb % TIMER_FREQ;
+			t = ((remainder * 256 * 2)
+			    + (lsb * 1000000 * 2)) / TIMER_FREQ;
+			isa_timer_msb_table[s] = (u_short)((t / 2)
+			    + (t & 0x1) + (quotient * 256));
 		}
 	}