Messages in this thread Patches in this message | | | Date | Fri, 15 Jul 2005 05:46:44 +0200 | From | Jesper Juhl <> | Subject | Re: [PATCH] i386: Selectable Frequency of the Timer Interrupt |
| |
Linus Torvalds wrote: > > On Thu, 14 Jul 2005, Lee Revell wrote: > >>I don't think this will fly because we take a big performance hit by >>calculating HZ at runtime. > > > I think it might be an acceptable solution for a distribution that really > needed it, since it should be fairly simple. However, it's definitely not > the right solution. > > HOWEVER. I bet that somebody who really really cares (hint hint) could > easily make HZ be 1000, and then dynamically tweak the divisor at bootup > to be either 1000, 250, or 100, and then increment "jiffies" by 1, 4 or > 10. > > My wild guess is that this is 20 lines of code, plus another 20 for > "setup", so that you can choose between 100/250/1000 Hz with a kernel > command line. > > It wouldn't be "dynamic" at first - you'd just set it up at bootup, and > set a "jiffies_increment" variable, and change the > > jiffies_64++; > > into > > jiffies_64 += jiffies_increment; > > and you'd be done. > > Really. I dare you guys. First one to send me a tested patch gets a gold > star. >
I don't know if this will earn me that gold star or not, but it's what I have at this point. It's buggy, that I know. setting kernel_hz (the new boot parameter) to 250 causes my system clock to run at something like 4-5 times normal speed, and key repeat is all funny (super fast) and various other nasty things - however, it does build and it does boot (i386 only as that's all I have) and apart from the kernels notion of time being way off it does seem to be a step in the right direction. Me never having looked at the kernels timer code before is most likely the explanation for the bugs - that and the fact that I didn't try to tackle the bogomips calculation at all... Ohh, and it'll probably bee even more strange if you build the kernel with CONFIG_HZ set to anything other than 1000 - if this is what we want to do, then I guess CONFIG_HZ needs to go away completely and just always be 1000 and then people should use the boot option to modify if needed/wanted.
Anyway, is this somewhere along the lines of what you were thinking?
The patch is below, but I've also attached it since I suspect thunderbird will mangle it.
diff -upr linux-2.6.13-rc3-orig/arch/i386/kernel/time.c linux-2.6.13-rc3/arch/i386/kernel/time.c --- linux-2.6.13-rc3-orig/arch/i386/kernel/time.c 2005-07-14 20:33:35.000000000 +0200 +++ linux-2.6.13-rc3/arch/i386/kernel/time.c 2005-07-15 04:02:50.000000000 +0200 @@ -75,6 +75,7 @@ int pit_latch_buggy; /* ext #include "do_timer.h"
u64 jiffies_64 = INITIAL_JIFFIES; +u16 jiffies_increment = 1;
EXPORT_SYMBOL(jiffies_64);
@@ -481,3 +482,27 @@ void __init time_init(void)
time_init_hook(); } + +static int __init jiffies_increment_setup(char *str) +{ + printk(KERN_NOTICE "setting up jiffies_increment : "); + if (str) { + printk("kernel_hz = %s, ", str); + } else { + printk("kernel_hz is unset, "); + } + if (!strncmp("100", str, 3)) { + jiffies_increment = 10; + printk("jiffies_increment set to 10, effective HZ will be 100\n"); + } else if (!strncmp("250", str, 3)) { + jiffies_increment = 4; + printk("jiffies_increment set to 4, effective HZ will be 250\n"); + } else { + jiffies_increment = 1; + printk("jiffies_increment set to 1, effective HZ will be 1000\n"); + } + + return 1; +} + +__setup("kernel_hz=", jiffies_increment_setup); diff -upr linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_pm.c linux-2.6.13-rc3/arch/i386/kernel/timers/timer_pm.c --- linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_pm.c 2005-07-14 20:33:35.000000000 +0200 +++ linux-2.6.13-rc3/arch/i386/kernel/timers/timer_pm.c 2005-07-15 02:59:39.000000000 +0200 @@ -176,7 +176,7 @@ static void mark_offset_pmtmr(void)
/* compensate for lost ticks */ if (lost >= 2) - jiffies_64 += lost - 1; + jiffies_64 += (lost * jiffies_increment) - 1;
/* don't calculate delay for first run, or if we've got less then a tick */ diff -upr linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_tsc.c linux-2.6.13-rc3/arch/i386/kernel/timers/timer_tsc.c --- linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_tsc.c 2005-07-14 20:33:35.000000000 +0200 +++ linux-2.6.13-rc3/arch/i386/kernel/timers/timer_tsc.c 2005-07-15 02:59:13.000000000 +0200 @@ -193,7 +193,7 @@ static void mark_offset_tsc_hpet(void) offset = hpet_readl(HPET_T0_CMP) - hpet_tick; if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { int lost_ticks = (offset - hpet_last) / hpet_tick; - jiffies_64 += lost_ticks; + jiffies_64 += lost_ticks * jiffies_increment; } hpet_last = hpet_current;
@@ -415,7 +415,7 @@ static void mark_offset_tsc(void) lost = delta/(1000000/HZ); delay = delta%(1000000/HZ); if (lost >= 2) { - jiffies_64 += lost-1; + jiffies_64 += (lost * jiffies_increment) - 1;
/* sanity check to ensure we're not always losing ticks */ if (lost_count++ > 100) { @@ -448,7 +448,7 @@ static void mark_offset_tsc(void) * usec delta is > 90% # of usecs/tick) */ if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) - jiffies_64++; + jiffies_64 += jiffies_increment; }
static int __init init_tsc(char* override) diff -upr linux-2.6.13-rc3-orig/include/linux/jiffies.h linux-2.6.13-rc3/include/linux/jiffies.h --- linux-2.6.13-rc3-orig/include/linux/jiffies.h 2005-06-17 21:48:29.000000000 +0200 +++ linux-2.6.13-rc3/include/linux/jiffies.h 2005-07-15 03:42:57.000000000 +0200 @@ -83,6 +83,7 @@ */ extern u64 __jiffy_data jiffies_64; extern unsigned long volatile __jiffy_data jiffies; +extern u16 jiffies_increment;
#if (BITS_PER_LONG < 64) u64 get_jiffies_64(void); diff -upr linux-2.6.13-rc3-orig/kernel/timer.c linux-2.6.13-rc3/kernel/timer.c --- linux-2.6.13-rc3-orig/kernel/timer.c 2005-07-14 20:34:24.000000000 +0200 +++ linux-2.6.13-rc3/kernel/timer.c 2005-07-15 02:55:45.000000000 +0200 @@ -948,7 +948,7 @@ static inline void update_times(void)
void do_timer(struct pt_regs *regs) { - jiffies_64++; + jiffies_64 += jiffies_increment; update_times(); }
-- Jesper Juhl
diff -upr linux-2.6.13-rc3-orig/arch/i386/kernel/time.c linux-2.6.13-rc3/arch/i386/kernel/time.c --- linux-2.6.13-rc3-orig/arch/i386/kernel/time.c 2005-07-14 20:33:35.000000000 +0200 +++ linux-2.6.13-rc3/arch/i386/kernel/time.c 2005-07-15 04:02:50.000000000 +0200 @@ -75,6 +75,7 @@ int pit_latch_buggy; /* ext #include "do_timer.h" u64 jiffies_64 = INITIAL_JIFFIES; +u16 jiffies_increment = 1; EXPORT_SYMBOL(jiffies_64); @@ -481,3 +482,27 @@ void __init time_init(void) time_init_hook(); } + +static int __init jiffies_increment_setup(char *str) +{ + printk(KERN_NOTICE "setting up jiffies_increment : "); + if (str) { + printk("kernel_hz = %s, ", str); + } else { + printk("kernel_hz is unset, "); + } + if (!strncmp("100", str, 3)) { + jiffies_increment = 10; + printk("jiffies_increment set to 10, effective HZ will be 100\n"); + } else if (!strncmp("250", str, 3)) { + jiffies_increment = 4; + printk("jiffies_increment set to 4, effective HZ will be 250\n"); + } else { + jiffies_increment = 1; + printk("jiffies_increment set to 1, effective HZ will be 1000\n"); + } + + return 1; +} + +__setup("kernel_hz=", jiffies_increment_setup); diff -upr linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_pm.c linux-2.6.13-rc3/arch/i386/kernel/timers/timer_pm.c --- linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_pm.c 2005-07-14 20:33:35.000000000 +0200 +++ linux-2.6.13-rc3/arch/i386/kernel/timers/timer_pm.c 2005-07-15 02:59:39.000000000 +0200 @@ -176,7 +176,7 @@ static void mark_offset_pmtmr(void) /* compensate for lost ticks */ if (lost >= 2) - jiffies_64 += lost - 1; + jiffies_64 += (lost * jiffies_increment) - 1; /* don't calculate delay for first run, or if we've got less then a tick */ diff -upr linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_tsc.c linux-2.6.13-rc3/arch/i386/kernel/timers/timer_tsc.c --- linux-2.6.13-rc3-orig/arch/i386/kernel/timers/timer_tsc.c 2005-07-14 20:33:35.000000000 +0200 +++ linux-2.6.13-rc3/arch/i386/kernel/timers/timer_tsc.c 2005-07-15 02:59:13.000000000 +0200 @@ -193,7 +193,7 @@ static void mark_offset_tsc_hpet(void) offset = hpet_readl(HPET_T0_CMP) - hpet_tick; if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { int lost_ticks = (offset - hpet_last) / hpet_tick; - jiffies_64 += lost_ticks; + jiffies_64 += lost_ticks * jiffies_increment; } hpet_last = hpet_current; @@ -415,7 +415,7 @@ static void mark_offset_tsc(void) lost = delta/(1000000/HZ); delay = delta%(1000000/HZ); if (lost >= 2) { - jiffies_64 += lost-1; + jiffies_64 += (lost * jiffies_increment) - 1; /* sanity check to ensure we're not always losing ticks */ if (lost_count++ > 100) { @@ -448,7 +448,7 @@ static void mark_offset_tsc(void) * usec delta is > 90% # of usecs/tick) */ if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) - jiffies_64++; + jiffies_64 += jiffies_increment; } static int __init init_tsc(char* override) diff -upr linux-2.6.13-rc3-orig/include/linux/jiffies.h linux-2.6.13-rc3/include/linux/jiffies.h --- linux-2.6.13-rc3-orig/include/linux/jiffies.h 2005-06-17 21:48:29.000000000 +0200 +++ linux-2.6.13-rc3/include/linux/jiffies.h 2005-07-15 03:42:57.000000000 +0200 @@ -83,6 +83,7 @@ */ extern u64 __jiffy_data jiffies_64; extern unsigned long volatile __jiffy_data jiffies; +extern u16 jiffies_increment; #if (BITS_PER_LONG < 64) u64 get_jiffies_64(void); diff -upr linux-2.6.13-rc3-orig/kernel/timer.c linux-2.6.13-rc3/kernel/timer.c --- linux-2.6.13-rc3-orig/kernel/timer.c 2005-07-14 20:34:24.000000000 +0200 +++ linux-2.6.13-rc3/kernel/timer.c 2005-07-15 02:55:45.000000000 +0200 @@ -948,7 +948,7 @@ static inline void update_times(void) void do_timer(struct pt_regs *regs) { - jiffies_64++; + jiffies_64 += jiffies_increment; update_times(); } | |