no-idle-hz aka dynamic ticks
PATCH 1/1 no-idle-hz aka dynamic ticks
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Cheers,
Con
---
This is the dynamic ticks patch for i386 as written by Tony Lindgen <[email protected]> and Tuukka Tikkanen <[email protected]>.
This version of the patch includes code style cleanups by Con Kolivas.
arch/i386/Kconfig | 33 +++++ arch/i386/kernel/Makefile | 1 arch/i386/kernel/apic.c | 19 +++ arch/i386/kernel/dyn-tick.c | 149 +++++++++++++++++++++++++ arch/i386/kernel/irq.c | 3 arch/i386/kernel/process.c | 3 arch/i386/kernel/time.c | 7 - arch/i386/kernel/timers/timer_pit.c | 37 ++++++ arch/i386/kernel/timers/timer_pm.c | 4 arch/i386/kernel/timers/timer_tsc.c | 10 + arch/i386/mach-default/setup.c | 16 ++ include/asm-i386/dyn-tick.h | 78 +++++++++++++ include/linux/dyn-tick.h | 66 +++++++++++ kernel/Makefile | 1 kernel/dyn-tick.c | 212 ++++++++++++++++++++++++++++++++++++ 15 files changed, 636 insertions(+), 3 deletions(-)
arch/i386/Kconfig +33 -0
@@ -457,6 +457,39 @@ config HPET_EMULATE_RTC bool "Provide RTC interrupt" depends on HPET_TIMER && RTC=y +config NO_IDLE_HZ + bool "Dynamic Tick Timer - Skip timer ticks during idle" + depends on EXPERIMENTAL + help + This option enables support for skipping timer ticks when the + processor is idle. During system load, timer is continuous. + This option saves power, as it allows the system to stay in + idle mode longer. Currently supported timers are ACPI PM + timer, local APIC timer, and TSC timer. HPET timer is currently + not supported. + + Note that you need to enable dynamic tick timer either by + passing dyntick=enable command line option, or via sysfs: + + # echo 1 > /sys/devices/system/timer/timer0/dyn_tick_state + +config DYN_TICK_USE_APIC + bool "Use APIC timer instead of PIT timer" + depends on NO_IDLE_HZ + help + This option enables using APIC timer interrupt if your hardware + supports it. APIC timer allows longer sleep periods compared + to PIT timer. + + Note that on most recent hardware disabling PIT timer also + disables APIC timer interrupts, and system won't run properly. + Symptoms include slow system boot, and time running slow. + + If unsure, don't enable this option. + + Note that to you still need to pass dyntick=enable,forceapic + command line option to use APIC timer. + config SMP bool "Symmetric multi-processing support" ---help---
arch/i386/kernel/apic.c +18 -1
@@ -27,6 +27,7 @@#include <linux/kernel_stat.h> #include <linux/sysdev.h> #include <linux/cpu.h> +#include <linux/dyn-tick.h> #include <asm/atomic.h> #include <asm/smp.h>
@@ -931,6 +932,8 @@ void (*wait_timer_tick)(void) __devinitd#define APIC_DIVISOR 16 +u32 apic_timer_val; +static void __setup_APIC_LVTT (unsigned int clocks) {unsigned int lvtt_value, tmp_value, ver;
@@ -949,7 +952,12 @@ static void __setup_APIC_LVTT(unsigned i & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | APIC_TDR_DIV_16); -apic_write_around (APIC_TMICT , clocks/APIC_DIVISOR ); + apic_timer_val = clocks /APIC_DIVISOR ; + +if (apic_timer_val) +set_dyn_tick_max_skip (apic_timer_val); + +apic_write_around (APIC_TMICT , apic_timer_val); }static void __devinit setup_APIC_timer (unsigned int clocks)
@@ -1062,6 +1070,8 @@ void __init setup_boot_APIC_clock(void)*/ setup_APIC_timer (calibration_result); +setup_dyn_tick_use_apic (calibration_result); +local_irq_enable (); }
@@ -1200,6 +1210,13 @@ fastcall void smp_apic_timer_interrupt(s* interrupt lock, which is the WrongThing (tm) to do. */ irq_enter (); + +/* +* Check if we need to wake up PIT interrupt handler. +* Otherwise just wake up local APIC timer. +*/ +wakeup_pit_or_apic (cpu, regs); +smp_local_timer_interrupt (regs);irq_exit (); }
arch/i386/kernel/dyn-tick.c +149 -0
149 lines not on this page · raw message
arch/i386/kernel/irq.c +3 -0
@@ -18,6 +18,7 @@#include <linux/notifier.h> #include <linux/cpu.h> #include <linux/delay.h> +#include <linux/dyn-tick.h> DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp;EXPORT_PER_CPU_SYMBOL (irq_stat);
@@ -76,6 +77,8 @@ fastcall unsigned int do_IRQ(struct pt_r }#endif +dyn_tick_interrupt (irq, regs); +#ifdef CONFIG_4KSTACKS curctx = (union irq_ctx *)current_thread_info ();
arch/i386/kernel/Makefile +1 -0
@@ -32,6 +32,7 @@ obj-$(CONFIG_MODULES) += module.o obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_HPET_TIMER) += time_hpet.o +obj-$(CONFIG_NO_IDLE_HZ) += dyn-tick.o obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
arch/i386/kernel/process.c +3 -0
@@ -39,6 +39,7 @@#include <linux/ptrace.h> #include <linux/random.h> #include <linux/kprobes.h> +#include <linux/dyn-tick.h> #include <asm/uaccess.h> #include <asm/pgtable.h>
@@ -200,6 +201,8 @@ void cpu_idle(void)if (cpu_is_offline (cpu))play_dead (); +dyn_tick_reprogram_timer (); +__get_cpu_var (irq_stat).idle_timestamp = jiffies;idle (); }
arch/i386/kernel/time.c +5 -2
@@ -46,6 +46,7 @@#include <linux/bcd.h> #include <linux/efi.h> #include <linux/mca.h> +#include <linux/dyn-tick.h> #include <asm/io.h> #include <asm/smp.h>
@@ -252,7 +253,7 @@ EXPORT_SYMBOL(profile_pc);* timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void do_timer_interrupt (int irq,void *dev_id, +inline void do_timer_interrupt (int irq,void *dev_id,struct pt_regs *regs) {#ifdef CONFIG_X86_IO_APIC
@@ -423,7 +424,7 @@ static struct sysdev_class timer_sysclas/* XXX this driverfs stuff should probably go elsewhere later -john */ -static struct sys_device device_timer = { +struct sys_device device_timer = { .id =0 , .cls = &timer_sysclass, };
@@ -479,5 +480,7 @@ void __init time_init(void) cur_timer =select_timer ();printk (KERN_INFO "Using %s for high-res timesource\n" ,cur_timer->name); +dyn_tick_time_init (cur_timer); +time_init_hook (); }
arch/i386/kernel/timers/timer_pit.c +37 -0
@@ -148,6 +148,43 @@ static unsigned long get_offset_pit(voidreturn count; } +/* +* REVISIT: Looks like on P3 APIC timer keeps running if PIT mode +* is changed. On P4, changing PIT mode seems to kill +* APIC timer interrupts. Same thing with disabling PIT +* interrupt. +*/ +void disable_pit_timer (void ) +{ +extern spinlock_t i8253_lock; +unsigned long flags; +spin_lock_irqsave (&i8253_lock, flags); +outb_p (0x32 ,PIT_MODE );/* binary, mode 1, LSB/MSB, ch 0 */ +spin_unlock_irqrestore (&i8253_lock, flags); +} + +/* +* Reprograms the next timer interrupt +* PIT timer reprogramming code taken from APM code. +* Note that PIT timer is a 16-bit timer, which allows max +* skip of only few seconds. +*/ +void reprogram_pit_timer (int jiffies_to_skip) +{ +int skip; +extern spinlock_t i8253_lock; +unsigned long flags; + + skip = jiffies_to_skip *LATCH ; +if (skip >0xffff ) + skip =0xffff ; + +spin_lock_irqsave (&i8253_lock, flags); +outb_p (0x34 ,PIT_MODE );/* binary, mode 2, LSB/MSB, ch 0 */ +outb_p (skip &0xff ,PIT_CH0 );/* LSB */ +outb (skip >>8 ,PIT_CH0 );/* MSB */ +spin_unlock_irqrestore (&i8253_lock, flags); +}/* tsc timer_opts struct */ struct timer_opts timer_pit = {
arch/i386/kernel/timers/timer_pm.c +4 -0
@@ -15,6 +15,7 @@#include <linux/module.h> #include <linux/device.h> #include <linux/init.h> +#include <linux/dyn-tick.h> #include <asm/types.h> #include <asm/timer.h> #include <asm/smp.h>
@@ -168,6 +169,9 @@ static void mark_offset_pmtmr(void) monotonic_base += delta *NSEC_PER_USEC ;write_sequnlock (&monotonic_lock); +if (dyn_tick_enabled ()) +return ; +/* convert to ticks */ delta += offset_delay; lost = delta / (USEC_PER_SEC /HZ );
arch/i386/kernel/timers/timer_tsc.c +10 -0
@@ -14,6 +14,7 @@#include <linux/cpufreq.h> #include <linux/string.h> #include <linux/jiffies.h> +#include <linux/dyn-tick.h> #include <asm/timer.h> #include <asm/io.h>
@@ -367,6 +368,9 @@ static void mark_offset_tsc(void)rdtsc (last_tsc_low, last_tsc_high); +if (dyn_tick_enabled ()) + goto monotonic_base; +spin_lock (&i8253_lock);outb_p (0x00 ,PIT_MODE );/* latch the count ASAP */
@@ -434,11 +438,17 @@ static void mark_offset_tsc(void)cpufreq_delayed_get (); }else lost_count =0 ; + + monotonic_base: +/* update the monotonic base value */ this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; monotonic_base +=cycles_2_ns (this_offset - last_offset);write_sequnlock (&monotonic_lock); +if (dyn_tick_enabled ()) +return ; +/* calculate delay_at_last_interrupt */ count = ((LATCH -1 ) - count) *TICK_SIZE ; delay_at_last_interrupt = (count +LATCH /2 ) /LATCH ;
arch/i386/mach-default/setup.c +16 -0
@@ -93,6 +93,22 @@ void __init time_init_hook(void)setup_irq (0 , &irq0); } +/** +* replace_timer_interrupt - allow replacing timer interrupt handler +* +* Description: +* Can be used to replace timer interrupt handler with a more optimized +* handler. Used for enabling and disabling of CONFIG_NO_IDLE_HZ. +*/ +void replace_timer_interrupt (void *new_handler) +{ +unsigned long flags; + +write_seqlock_irqsave (&xtime_lock, flags); + irq0.handler = new_handler; +write_sequnlock_irqrestore (&xtime_lock, flags); +} +#ifdef CONFIG_MCA /** * mca_nmi_hook - hook into MCA specific NMI chain
include/asm-i386/dyn-tick.h +78 -0
78 lines not on this page · raw message
include/linux/dyn-tick.h +66 -0
66 lines not on this page · raw message
kernel/dyn-tick.c +212 -0
212 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -30,6 +30,7 @@ obj-$(CONFIG_SYSFS) += ksysfs.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SECCOMP) += seccomp.o +obj-$(CONFIG_NO_IDLE_HZ) += dyn-tick.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
Quoted 2 lines · Con Kolivas
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
CC arch/i386/kernel/irq.o
In file included from include/linux/dyn-tick.h:64,
from arch/i386/kernel/irq.c:21:
include/asm/dyn-tick.h: In function `reprogram_apic_timer':include/asm/dyn-tick.h:48: warning: implicit declaration of function `apic_write_around'include/asm/dyn-tick.h:48: error: `APIC_TMICT' undeclared (first use in this function)include/asm/dyn-tick.h:48: error: (Each undeclared identifier is reported only onceinclude/asm/dyn-tick.h:48: error: for each function it appears in.) make[1]: *** [arch/i386/kernel/irq.o] Error 1
Cheers,
Prakash
Quoted 10 lines · Prakash Punnoor
Quoted 2 lines · Con Kolivas
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
CC
arch/i386/kernel/irq.o
In file included frominclude/linux/dyn-tick.h:64,from arch/i386/kernel/irq.c:21:
Quoted 9 lines
include/asm/dyn-tick.h: In function `reprogram_apic_timer':include/asm/dyn-tick.h:48: warning: implicit declaration of function `apic_write_around'include/asm/dyn-tick.h:48: error: `APIC_TMICT' undeclared (first use in this function)include/asm/dyn-tick.h:48: error: (Each undeclared identifier is reported only onceinclude/asm/dyn-tick.h:48: error: for each function it appears in.) make[1]: *** [arch/i386/kernel/irq.o] Error 1
Please send me a .config
Cheers,
Con
PATCH 1/1 no-idle-hz aka dynamic ticks-2
In reply to Prakash PunnoorQuoted 5 lines · Prakash Punnoor
Quoted 2 lines · Con Kolivas
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
Cheers,
Con
---
arch/i386/Kconfig +33 -0
@@ -457,6 +457,39 @@ config HPET_EMULATE_RTC bool "Provide RTC interrupt" depends on HPET_TIMER && RTC=y +config NO_IDLE_HZ + bool "Dynamic Tick Timer - Skip timer ticks during idle" + depends on EXPERIMENTAL + help + This option enables support for skipping timer ticks when the + processor is idle. During system load, timer is continuous. + This option saves power, as it allows the system to stay in + idle mode longer. Currently supported timers are ACPI PM + timer, local APIC timer, and TSC timer. HPET timer is currently + not supported. + + Note that you need to enable dynamic tick timer either by + passing dyntick=enable command line option, or via sysfs: + + # echo 1 > /sys/devices/system/timer/timer0/dyn_tick_state + +config DYN_TICK_USE_APIC + bool "Use APIC timer instead of PIT timer" + depends on NO_IDLE_HZ + help + This option enables using APIC timer interrupt if your hardware + supports it. APIC timer allows longer sleep periods compared + to PIT timer. + + Note that on most recent hardware disabling PIT timer also + disables APIC timer interrupts, and system won't run properly. + Symptoms include slow system boot, and time running slow. + + If unsure, don't enable this option. + + Note that to you still need to pass dyntick=enable,forceapic + command line option to use APIC timer. + config SMP bool "Symmetric multi-processing support" ---help---
arch/i386/kernel/apic.c +18 -1
@@ -27,6 +27,7 @@#include <linux/kernel_stat.h> #include <linux/sysdev.h> #include <linux/cpu.h> +#include <linux/dyn-tick.h> #include <asm/atomic.h> #include <asm/smp.h>
@@ -931,6 +932,8 @@ void (*wait_timer_tick)(void) __devinitd#define APIC_DIVISOR 16 +u32 apic_timer_val; +static void __setup_APIC_LVTT (unsigned int clocks) {unsigned int lvtt_value, tmp_value, ver;
@@ -949,7 +952,12 @@ static void __setup_APIC_LVTT(unsigned i & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | APIC_TDR_DIV_16); -apic_write_around (APIC_TMICT , clocks/APIC_DIVISOR ); + apic_timer_val = clocks /APIC_DIVISOR ; + +if (apic_timer_val) +set_dyn_tick_max_skip (apic_timer_val); + +apic_write_around (APIC_TMICT , apic_timer_val); }static void __devinit setup_APIC_timer (unsigned int clocks)
@@ -1062,6 +1070,8 @@ void __init setup_boot_APIC_clock(void)*/ setup_APIC_timer (calibration_result); +setup_dyn_tick_use_apic (calibration_result); +local_irq_enable (); }
@@ -1200,6 +1210,13 @@ fastcall void smp_apic_timer_interrupt(s* interrupt lock, which is the WrongThing (tm) to do. */ irq_enter (); + +/* +* Check if we need to wake up PIT interrupt handler. +* Otherwise just wake up local APIC timer. +*/ +wakeup_pit_or_apic (cpu, regs); +smp_local_timer_interrupt (regs);irq_exit (); }
arch/i386/kernel/dyn-tick.c +149 -0
149 lines not on this page · raw message
arch/i386/kernel/irq.c +3 -0
@@ -18,6 +18,7 @@#include <linux/notifier.h> #include <linux/cpu.h> #include <linux/delay.h> +#include <linux/dyn-tick.h> DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp;EXPORT_PER_CPU_SYMBOL (irq_stat);
@@ -76,6 +77,8 @@ fastcall unsigned int do_IRQ(struct pt_r }#endif +dyn_tick_interrupt (irq, regs); +#ifdef CONFIG_4KSTACKS curctx = (union irq_ctx *)current_thread_info ();
arch/i386/kernel/Makefile +1 -0
@@ -32,6 +32,7 @@ obj-$(CONFIG_MODULES) += module.o obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_HPET_TIMER) += time_hpet.o +obj-$(CONFIG_NO_IDLE_HZ) += dyn-tick.o obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
arch/i386/kernel/process.c +3 -0
@@ -39,6 +39,7 @@#include <linux/ptrace.h> #include <linux/random.h> #include <linux/kprobes.h> +#include <linux/dyn-tick.h> #include <asm/uaccess.h> #include <asm/pgtable.h>
@@ -200,6 +201,8 @@ void cpu_idle(void)if (cpu_is_offline (cpu))play_dead (); +dyn_tick_reprogram_timer (); +__get_cpu_var (irq_stat).idle_timestamp = jiffies;idle (); }
arch/i386/kernel/time.c +5 -2
@@ -46,6 +46,7 @@#include <linux/bcd.h> #include <linux/efi.h> #include <linux/mca.h> +#include <linux/dyn-tick.h> #include <asm/io.h> #include <asm/smp.h>
@@ -252,7 +253,7 @@ EXPORT_SYMBOL(profile_pc);* timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void do_timer_interrupt (int irq,void *dev_id, +inline void do_timer_interrupt (int irq,void *dev_id,struct pt_regs *regs) {#ifdef CONFIG_X86_IO_APIC
@@ -423,7 +424,7 @@ static struct sysdev_class timer_sysclas/* XXX this driverfs stuff should probably go elsewhere later -john */ -static struct sys_device device_timer = { +struct sys_device device_timer = { .id =0 , .cls = &timer_sysclass, };
@@ -479,5 +480,7 @@ void __init time_init(void) cur_timer =select_timer ();printk (KERN_INFO "Using %s for high-res timesource\n" ,cur_timer->name); +dyn_tick_time_init (cur_timer); +time_init_hook (); }
arch/i386/kernel/timers/timer_pit.c +37 -0
@@ -148,6 +148,43 @@ static unsigned long get_offset_pit(voidreturn count; } +/* +* REVISIT: Looks like on P3 APIC timer keeps running if PIT mode +* is changed. On P4, changing PIT mode seems to kill +* APIC timer interrupts. Same thing with disabling PIT +* interrupt. +*/ +void disable_pit_timer (void ) +{ +extern spinlock_t i8253_lock; +unsigned long flags; +spin_lock_irqsave (&i8253_lock, flags); +outb_p (0x32 ,PIT_MODE );/* binary, mode 1, LSB/MSB, ch 0 */ +spin_unlock_irqrestore (&i8253_lock, flags); +} + +/* +* Reprograms the next timer interrupt +* PIT timer reprogramming code taken from APM code. +* Note that PIT timer is a 16-bit timer, which allows max +* skip of only few seconds. +*/ +void reprogram_pit_timer (int jiffies_to_skip) +{ +int skip; +extern spinlock_t i8253_lock; +unsigned long flags; + + skip = jiffies_to_skip *LATCH ; +if (skip >0xffff ) + skip =0xffff ; + +spin_lock_irqsave (&i8253_lock, flags); +outb_p (0x34 ,PIT_MODE );/* binary, mode 2, LSB/MSB, ch 0 */ +outb_p (skip &0xff ,PIT_CH0 );/* LSB */ +outb (skip >>8 ,PIT_CH0 );/* MSB */ +spin_unlock_irqrestore (&i8253_lock, flags); +}/* tsc timer_opts struct */ struct timer_opts timer_pit = {
arch/i386/kernel/timers/timer_pm.c +4 -0
@@ -15,6 +15,7 @@#include <linux/module.h> #include <linux/device.h> #include <linux/init.h> +#include <linux/dyn-tick.h> #include <asm/types.h> #include <asm/timer.h> #include <asm/smp.h>
@@ -168,6 +169,9 @@ static void mark_offset_pmtmr(void) monotonic_base += delta *NSEC_PER_USEC ;write_sequnlock (&monotonic_lock); +if (dyn_tick_enabled ()) +return ; +/* convert to ticks */ delta += offset_delay; lost = delta / (USEC_PER_SEC /HZ );
arch/i386/kernel/timers/timer_tsc.c +10 -0
@@ -14,6 +14,7 @@#include <linux/cpufreq.h> #include <linux/string.h> #include <linux/jiffies.h> +#include <linux/dyn-tick.h> #include <asm/timer.h> #include <asm/io.h>
@@ -367,6 +368,9 @@ static void mark_offset_tsc(void)rdtsc (last_tsc_low, last_tsc_high); +if (dyn_tick_enabled ()) + goto monotonic_base; +spin_lock (&i8253_lock);outb_p (0x00 ,PIT_MODE );/* latch the count ASAP */
@@ -434,11 +438,17 @@ static void mark_offset_tsc(void)cpufreq_delayed_get (); }else lost_count =0 ; + + monotonic_base: +/* update the monotonic base value */ this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; monotonic_base +=cycles_2_ns (this_offset - last_offset);write_sequnlock (&monotonic_lock); +if (dyn_tick_enabled ()) +return ; +/* calculate delay_at_last_interrupt */ count = ((LATCH -1 ) - count) *TICK_SIZE ; delay_at_last_interrupt = (count +LATCH /2 ) /LATCH ;
arch/i386/mach-default/setup.c +16 -0
@@ -93,6 +93,22 @@ void __init time_init_hook(void)setup_irq (0 , &irq0); } +/** +* replace_timer_interrupt - allow replacing timer interrupt handler +* +* Description: +* Can be used to replace timer interrupt handler with a more optimized +* handler. Used for enabling and disabling of CONFIG_NO_IDLE_HZ. +*/ +void replace_timer_interrupt (void *new_handler) +{ +unsigned long flags; + +write_seqlock_irqsave (&xtime_lock, flags); + irq0.handler = new_handler; +write_sequnlock_irqrestore (&xtime_lock, flags); +} +#ifdef CONFIG_MCA /** * mca_nmi_hook - hook into MCA specific NMI chain
include/asm-i386/dyn-tick.h +80 -0
80 lines not on this page · raw message
include/linux/dyn-tick.h +66 -0
66 lines not on this page · raw message
kernel/dyn-tick.c +212 -0
212 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -30,6 +30,7 @@ obj-$(CONFIG_SYSFS) += ksysfs.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SECCOMP) += seccomp.o +obj-$(CONFIG_NO_IDLE_HZ) += dyn-tick.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
Re: [PATCH] no-idle-hz aka dynamic ticks-2
Hi!
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
I'm not sure if you added them, but...
CC arch/i386/kernel/timers/timer_tsc.oarch/i386/kernel/timers/timer_tsc.c: In function `mark_offset_tsc':arch/i386/kernel/timers/timer_tsc.c:345: warning: lost' might be used uninitialized in this function arch/i386/kernel/timers/timer_tsc.c:345: warning: delay' might be used uninitialized in this function arch/i386/kernel/timers/timer_tsc.c:347: warning: `count' might be used uninitialized in this function
Pavel
Signature · 1 line
teflon -- maybe it is a trademark, but it should not be.
Re: [PATCH] no-idle-hz aka dynamic ticks-2
Quoted 12 lines · Pavel Machek
Hi!
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
I'm not sure if you added them, but...
Quoted 7 lines
CC
arch/i386/kernel/timers/timer_tsc.oarch/i386/kernel/timers/timer_tsc.c: In function `mark_offset_tsc':arch/i386/kernel/timers/timer_tsc.c:345: warning: `lost' might be used uninitialized in this functionarch/i386/kernel/timers/timer_tsc.c:345:
warning:delay' might be used uninitialized in this function arch/i386/kernel/timers/timer_tsc.c:347: warning:count' might be used uninitialized in this function
Indeed the goto will bypass the setting of these variables and they will be uninitialised. Will fix with next version, thanks.
Con
Re: [PATCH] no-idle-hz aka dynamic ticks-2
Quoted 21 lines · Con Kolivas
Quoted 12 lines · Pavel Machek
Hi!
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
I'm not sure if you added them, but...
Quoted 7 lines
CC
arch/i386/kernel/timers/timer_tsc.oarch/i386/kernel/timers/timer_tsc.c: In function `mark_offset_tsc':arch/i386/kernel/timers/timer_tsc.c:345: warning: `lost' might be used uninitialized in this functionarch/i386/kernel/timers/timer_tsc.c:345:
warning:delay' might be used uninitialized in this function arch/i386/kernel/timers/timer_tsc.c:347: warning:count' might be used uninitialized in this function
Quoted 2 lines
Indeed the goto will bypass the setting of these variables and they will be uninitialised. Will fix with next version, thanks.
Looking yet further into this, if it gotos monotonic_base it will return without using any of these variables so it's a harmless warning but we may as well initialise them to quieten it.
Cheers,
Con
PATCH 1/1 dyn-tick3 tweaks
Quoted 3 lines · Con Kolivas
Looking yet further into this, if it gotos
monotonic_baseit will return without using any of these variables so it's a harmless warning but we may as well initialise them to quieten it.
Something like this on top is cleaner and quieter. I'll add this to pending changes for another version.
Cheers,
Con
---
arch/i386/kernel/timers/timer_tsc.c +18 -17
@@ -167,10 +167,20 @@ static void delay_tsc(unsigned long loop }while ((now-bclock) < loops); } +/* update the monotonic base value */ +static inline void update_monotonic_base (unsigned long long last_offset) +{ +unsigned long long this_offset; + + this_offset = ((unsigned long long )last_tsc_high <<32 ) | last_tsc_low; + monotonic_base +=cycles_2_ns (this_offset - last_offset); +write_sequnlock (&monotonic_lock); +} +#ifdef CONFIG_HPET_TIMER static void mark_offset_tsc_hpet (void ) { -unsigned long long this_offset, last_offset; +unsigned long long last_offset;unsigned long offset, temp, hpet_current;write_seqlock (&monotonic_lock);
@@ -198,10 +208,7 @@ static void mark_offset_tsc_hpet(void) } hpet_last = hpet_current; -/* update the monotonic base value */ - this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; - monotonic_base +=cycles_2_ns (this_offset - last_offset); -write_sequnlock (&monotonic_lock); +update_monotonic_base (last_offset);/* calculate delay_at_last_interrupt */ /*
@@ -347,7 +354,7 @@ static void mark_offset_tsc(void)int count;int countmp;static int count1 =0 ; -unsigned long long this_offset, last_offset; +unsigned long long last_offset;static int lost_count =0 ;write_seqlock (&monotonic_lock);
@@ -368,8 +375,10 @@ static void mark_offset_tsc(void)rdtsc (last_tsc_low, last_tsc_high); -if (dyn_tick_enabled ()) - goto monotonic_base; +if (dyn_tick_enabled ()) { +update_monotonic_base (last_offset); +return ; + }spin_lock (&i8253_lock);outb_p (0x00 ,PIT_MODE );/* latch the count ASAP */
@@ -439,15 +448,7 @@ static void mark_offset_tsc(void) }else lost_count =0 ; - monotonic_base: - -/* update the monotonic base value */ - this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; - monotonic_base +=cycles_2_ns (this_offset - last_offset); -write_sequnlock (&monotonic_lock); - -if (dyn_tick_enabled ()) -return ; +update_monotonic_base (last_offset);/* calculate delay_at_last_interrupt */ count = ((LATCH -1 ) - count) *TICK_SIZE ;
Re: [PATCH] dyn-tick3 tweaks
Quoted 13 lines · Con Kolivas
Something like this on top is cleaner and quieter. I'll add this to pending changes for another version.
------------------------------------------------------------------------
Index:
linux-2.6.13-rc5-ck2/arch/i386/kernel/timers/timer_tsc.c
===================================================================arch/i386/kernel/timers/timer_tsc.c +0
-0@@ -167,10 +167,20 @@ static void delay_tsc(unsigned long loop }while ((now-bclock) < loops); }
arch/i386/kernel/timers/timer_tsc.c static void delay_tsc(unsigned long loop · line 179
Quoted 10 lines
arch/i386/kernel/timers/timer_tsc.c +10
-0+/* update the monotonic base value */ +static inline void update_monotonic_base (unsigned long long last_offset) +{ +unsigned long long this_offset; + + this_offset = ((unsigned long long )last_tsc_high <<32 ) | last_tsc_low; + monotonic_base +=cycles_2_ns (this_offset - last_offset); +write_sequnlock (&monotonic_lock); +} +
All else being equal, it is much better if you unlock in the same function that takes the lock. For readability.
It looks like you should be able to leave all the flow control and locking the same, and use update_monotonic_base() to do the actual update?
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Re: [PATCH] dyn-tick3 tweaks
Quoted 32 lines · Nick Piggin
Quoted 17 lines · Con Kolivas
Something like this on top is cleaner and quieter. I'll add this to pending changes for another version.
------------------------------------------------------------------------
Index:
linux-2.6.13-rc5-ck2/arch/i386/kernel/timers/timer_tsc.c
===================================================================
---linux-2.6.13-rc5-ck2.orig/arch/i386/kernel/timers/timer_tsc.c2005-08-03
11:29:29.000000000 +1000 +++linux-2.6.13-rc5-ck2/arch/i386/kernel/timers/timer_tsc.c2005-08-05
10:22:25.000000000 +1000 @@ -167,10 +167,20 @@ static void delay_tsc(unsigned long looparch/i386/kernel/timers/timer_tsc.c +0
-0}while ((now-bclock) < loops); }arch/i386/kernel/timers/timer_tsc.c static void delay_tsc(unsigned long loop · line 179
Quoted 10 lines
arch/i386/kernel/timers/timer_tsc.c +10
-0+/* update the monotonic base value */ +static inline void update_monotonic_base (unsigned long long last_offset) +{ +unsigned long long this_offset; + + this_offset = ((unsigned long long )last_tsc_high <<32 ) | last_tsc_low; + monotonic_base +=cycles_2_ns (this_offset - last_offset); +write_sequnlock (&monotonic_lock); +} +All else being equal, it is much better if you unlock in the same function that takes the lock. For readability.
Quoted 3 lines
It looks like you should be able to leave all the flow control and locking the same, and use
update_monotonic_base()to do the actual update?
Good advice, thanks. Will respin.
Cheers,
Con
PATCH 1/1 dyn-tick3 tweaks respin
Quoted 9 lines · Con Kolivas
Quoted 6 lines · Nick Piggin
All else being equal, it is much better if you unlock in the same function that takes the lock. For readability.
It looks like you should be able to leave all the flow control and locking the same, and use
update_monotonic_base()to do the actual update?Good advice, thanks. Will respin.
Like this I assume you meant?
Cheers,
Con
---
arch/i386/kernel/timers/timer_tsc.c +18 -15
@@ -167,10 +167,19 @@ static void delay_tsc(unsigned long loop }while ((now-bclock) < loops); } +/* update the monotonic base value */ +static inline void update_monotonic_base (unsigned long long last_offset) +{ +unsigned long long this_offset; + + this_offset = ((unsigned long long )last_tsc_high <<32 ) | last_tsc_low; + monotonic_base +=cycles_2_ns (this_offset - last_offset); +} +#ifdef CONFIG_HPET_TIMER static void mark_offset_tsc_hpet (void ) { -unsigned long long this_offset, last_offset; +unsigned long long last_offset;unsigned long offset, temp, hpet_current;write_seqlock (&monotonic_lock);
@@ -198,9 +207,7 @@ static void mark_offset_tsc_hpet(void) } hpet_last = hpet_current; -/* update the monotonic base value */ - this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; - monotonic_base +=cycles_2_ns (this_offset - last_offset); +update_monotonic_base (last_offset);write_sequnlock (&monotonic_lock);/* calculate delay_at_last_interrupt */
@@ -347,7 +354,7 @@ static void mark_offset_tsc(void)int count;int countmp;static int count1 =0 ; -unsigned long long this_offset, last_offset; +unsigned long long last_offset;static int lost_count =0 ;write_seqlock (&monotonic_lock);
@@ -368,8 +375,11 @@ static void mark_offset_tsc(void)rdtsc (last_tsc_low, last_tsc_high); -if (dyn_tick_enabled ()) - goto monotonic_base; +if (dyn_tick_enabled ()) { +update_monotonic_base (last_offset); +write_sequnlock (&monotonic_lock); +return ; + }spin_lock (&i8253_lock);outb_p (0x00 ,PIT_MODE );/* latch the count ASAP */
@@ -439,16 +449,9 @@ static void mark_offset_tsc(void) }else lost_count =0 ; - monotonic_base: - -/* update the monotonic base value */ - this_offset = ((unsigned long long )last_tsc_high<<32 )|last_tsc_low; - monotonic_base +=cycles_2_ns (this_offset - last_offset); +update_monotonic_base (last_offset);write_sequnlock (&monotonic_lock); -if (dyn_tick_enabled ()) -return ; -/* calculate delay_at_last_interrupt */ count = ((LATCH -1 ) - count) *TICK_SIZE ; delay_at_last_interrupt = (count +LATCH /2 ) /LATCH ;
Re: [PATCH] dyn-tick3 tweaks respin
Quoted 2 lines · Con Kolivas
Like this I assume you meant?
Yeah that looks good.
Nick
Signature · 5 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Re: [PATCH] no-idle-hz aka dynamic ticks-2
In reply to Con KolivasHi!
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
Sorry, it breaks my machine in "interesting" way. Cursor no longer blinks, sleep 1 takes more than five seconds, ...
Pentium-M in compaq evo n620c notebok, cpufreq active:
pavel@Elf:~$ dmesg | grep tick dyn-tick: Found suitable timer: tsc dyn-tick: Registering dynamic tick timer v050610-1 dyn-tick: Maximum ticks to skip limited to 13 dyn-tick: Timer not enabled during boot pavel@Elf:~$
Ouch, even system time seems to go slower. I'll try setting DYNTICK_USE_APIC next.
Pavel
Signature · 1 line
teflon -- maybe it is a trademark, but it should not be.
Re: [PATCH] no-idle-hz aka dynamic ticks-2
Quoted 22 lines · Pavel Machek
Hi!
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
Sorry, it breaks my machine in "interesting" way. Cursor no longer blinks, sleep 1 takes more than five seconds, ...
Pentium-M in compaq evo n620c notebok, cpufreq active:
pavel@Elf:~$ dmesg | grep tick dyn-tick: Found suitable timer: tsc dyn-tick: Registering dynamic tick timer v050610-1 dyn-tick: Maximum ticks to skip limited to 13 dyn-tick: Timer not enabled during boot pavel@Elf:~$
Quoted 3 lines
Ouch, even system time seems to go slower. I'll try setting
DYNTICK_USE_APICnext.
Pavel
I assume you've confirmed this doesn't happen in vanilla rc5?
Cheers,
Con
Re: [PATCH] no-idle-hz aka dynamic ticks-2
In reply to Con KolivasHi!
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Doesn't compile for me w/ gcc 3.4.4:
Thanks for the report. Tiny change required. Here is a respun patch.
I tried setting DYN_TICK_USE_APIC, and it got even worse. Basically machine was frozen; if I pressed enough keys, it moved forward, then froze again.
Pavel
Signature · 1 line
teflon -- maybe it is a trademark, but it should not be.
Quoted 2 lines · Con Kolivas
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Please note that ARM already has dyn-tick merged in mainline. If we're going to be adding dyn-tick for x86, please do it in a way that we don't create another goddamned awful mess like we did for the ARM IRQ stuff.
I notice that this version does some things in a different way to the ARM version - for instance, it doesn't pass the "number of jiffies to skip" to the arch reprogram function.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 Serial core
Quoted 8 lines · Russell King
Quoted 2 lines · Con Kolivas
As promised, here is an updated patch for the newly released 2.6.13-rc5. Boots and runs fine on P4HT (SMP+SMT kernel) built with gcc 4.0.1.
Please note that ARM already has dyn-tick merged in mainline. If we're going to be adding dyn-tick for x86, please do it in a way that we don't create another goddamned awful mess like we did for the ARM IRQ stuff.
I agree, and will be working on that :)
Quoted 3 lines
I notice that this version does some things in a different way to the ARM version - for instance, it doesn't pass the "number of jiffies to skip" to the arch reprogram function.
I've been meaning to update the x86 stuff with the changes we did for ARM as soon as I have some time.
Tony