High-res-timers part 2 (x86 platform code) take 10
PATCH 2/3 High-res-timers part 2 (x86 platform code) take 10
Some how this got delayed by the mail system...
Well what happened is somehow it doubled in size and so lklm dropped it. Here it is without the extra baggage.
This patch, in conjunction with the "core" high-res-timers patch implements high resolution timers on the i386 platforms. The high-res-timers use the periodic interrupt to "remind" the system to look at the clock. The clock should be relatively high resolution (1 micro second or better). This patch allows configuring of three possible clocks, the TSC, the ACPI pm timer, or the Programmable interrupt timer (PIT). Most of the changes in this patch are in the arch/i386/kernel/timer/* code.
This patch uses (if available) the APIC timer(s) to generate 1/HZ ticks and sub 1/HZ ticks as needed. The PIT still interrupts, but if the APIC timer is available, just causes the wall clock update. No attempt is made to make this interrupt happen on jiffie boundaries, however, the APIC timers are disciplined to expire on 1/HZ boundaries to give consistent timer latencies WRT to the system time.
With this patch applied and enabled (at config time in the processor feature section), the system clock will be the specified clock. The PIT is not used to keep track of time, but only to remind the system to look at the clock. Sub jiffies are kept and available for code that knows how to use them.
Depends on the core high res timers patch.
Patch is against 2.5.45
This patch as well as the POSIX clocks & timers patch is available on the project site:
http://sourceforge.net/projects/high-res-timers/
The 3 parts to the high res timers are:
core The core kernel (i.e. platform independent) changes
*i386 The high-res changes for the i386 (x86) platform
posixhr The changes to the POSIX clocks & timers patch to
use high-res timers
Please apply.
Signature · 5 lines
George Anzinger [email protected] High-res-timers: http://sourceforge.net/projects/high-res-timers/ Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml
arch/i386/Kconfig +92 -0
@@ -315,6 +315,98 @@ If you don't know what to do here, say N. +config HIGH_RES_TIMERS + bool "Configure High-Resolution-Timers" + help + POSIX timers are available by default. This option enables + high resolution POSIX timers. With this option the resolution + is at least 1 micro second. High resolution is not free. If + enabled this option will add a small overhead each time a + timer expires that is not on a 1/HZ tick boundry. If no such + timers are used the overhead is nil. + + This option enables two additional POSIX CLOCKS, + CLOCK_REALTIME_HR and CLOCK_MONOTONIC_HR. Note that this + option does not change the resolution of CLOCK_REALTIME or + CLOCK_MONOTONIC which remain at 1/HZ resolution. + +choice + prompt "Clock source?" + default HIGH_RES_TIMER_TSC + help + This option allows you to choose the wall clock timer for your + system. With high resolution timers on the x86 platforms it + is best to keep the interrupt generating timer separate from + the time keeping timer. On x86 platforms there are three + possible sources implemented for the wall clock. These are: + + <timer> <resolution> + ACPI power management (pm) timer ~280 nano seconds + TSC (Time Stamp Counter) 1/CPU clock + PIT (Programmable Interrupt Timer) ~838 nano seconds + + The PIT is used to generate interrupts and at any given time + will be programmed to interrupt when the next timer is to + expire or on the next 1/HZ tick. For this reason it is best + to not use this timer as the wall clock timer. This timer has + a resolution of 838 nano seconds. THIS OPTION SHOULD ONLY BE + USED IF BOTH ACPI AND TSC ARE NOT AVAILABLE. + + The TSC runs at the cpu clock rate (i.e. its resolution is + 1/CPU clock) and it has a very low access time. However, it + is subject, in some (incorrect) processors, to throttling to + cool the cpu, and to other slow downs during power management. + If your cpu is correct and does not change the TSC frequency + for throttling or power management this is the best clock + timer. + + The ACPI pm timer is available on systems with Advanced + Configuration and Power Interface support. The pm timer is + available on these systems even if you don't use or enable + ACPI in the software or the BIOS (but see Default ACPI pm + timer address). The timer has a resolution of about 280 + nanoseconds, however, the access time is a bit higher that + that of the TSC. Since it is part of ACPI it is intended to + keep track of time while the system is under power management, + thus it is not subject to the problems of the TSC. + + If you enable the ACPI pm timer and it can not be found, it is + possible that your BIOS is not producing the ACPI table or + that your machine does not support ACPI. In the former case, + see "Default ACPI pm timer address". If the timer is not + found the boot will fail when trying to calibrate the delay + timer. + +config HIGH_RES_TIMER_ACPI_PM + bool "ACPI-pm-timer" + +config HIGH_RES_TIMER_TSC + bool "Time-stamp-counter/TSC" + depends on X86_TSC + +config HIGH_RES_TIMER_PIT + bool "Programable-interrupt-timer/PIT" + +endchoice + +config HIGH_RES_TIMER_ACPI_PM_ADD + int "Default ACPI pm timer address" + depends on HIGH_RES_TIMER_ACPI_PM + default 0 + help + This option is available for use on systems where the BIOS + does not generate the ACPI tables if ACPI is not enabled. For + example some BIOSes will not generate the ACPI tables if APM + is enabled. The ACPI pm timer is still available but can not + be found by the software. This option allows you to supply + the needed address. When the high resolution timers code + finds a valid ACPI pm timer address it reports it in the boot + messages log (look for lines that begin with + "High-res-timers:"). You can turn on the ACPI support in the + BIOS, boot the system and find this value. You can then enter + it at configure time. Both the report and the entry are in + decimal. + config PREEMPT bool "Preemptible Kernel" help
arch/i386/kernel/apic.c +13 -3
@@ -800,7 +800,7 @@* P5 APIC double write bug. */ -#define APIC_DIVISOR 16 +#define APIC_DIVISOR 1void __setup_APIC_LVTT (unsigned int clocks) {
@@ -811,12 +811,12 @@apic_write_around (APIC_LVTT , lvtt1_value);/* -* Divide PICLK by 16 +* Divide PICLK by 1 */ tmp_value =apic_read (APIC_TDCR );apic_write_around (APIC_TDCR , (tmp_value & ~(APIC_TDR_DIV_1 |APIC_TDR_DIV_TMBASE )) - |APIC_TDR_DIV_16 ); + |APIC_TDR_DIV_1 );apic_write_around (APIC_TMICT , clocks/APIC_DIVISOR ); }
@@ -1021,10 +1021,20 @@* Interrupts are already masked off at this point. */ prof_counter[cpu] = prof_multiplier[cpu]; +/* +* deal with profiling later... +*/ +#ifndef CONFIG_HIGH_RES_TIMERS if (prof_counter[cpu] != prof_old_multiplier[cpu]) {__setup_APIC_LVTT (calibration_result/prof_counter[cpu]); prof_old_multiplier[cpu] = prof_counter[cpu]; } +#else +/* +* This is the 1/HZ count, can be changed by HRT code. +*/ +__setup_APIC_LVTT (calibration_result); +#endif #ifdef CONFIG_SMP update_process_times (user_mode (regs));
arch/i386/kernel/time.c +97 -25
194 lines not on this page · raw message
arch/i386/kernel/timers/Makefile +6 -0
@@ -6,6 +6,12 @@ obj-y += timer_tsc.o obj-y += timer_pit.o +obj-$(CONFIG_X86_TSC) -= timer_pit.o +obj-$(CONFIG_HIGH_RES_TIMERS) -= timer_tsc.o obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o +obj-$(CONFIG_HIGH_RES_TIMER_ACPI_PM) += hrtimer_pm.o +obj-$(CONFIG_HIGH_RES_TIMER_ACPI_PM) += high-res-tbxfroot.o +obj-$(CONFIG_HIGH_RES_TIMER_TSC) += hrtimer_tsc.o +obj-$(CONFIG_HIGH_RES_TIMER_PIT) += hrtimer_pit.o include $(TOPDIR)/Rules.make
arch/i386/kernel/timers/high-res-tbxfroot.c +273 -0
273 lines not on this page · raw message
arch/i386/kernel/timers/hrtimer_pit.c +163 -0
163 lines not on this page · raw message
arch/i386/kernel/timers/hrtimer_pm.c +196 -0
196 lines not on this page · raw message
arch/i386/kernel/timers/hrtimer_tsc.c +288 -0
288 lines not on this page · raw message
arch/i386/kernel/timers/timer.c +18 -1
@@ -1,15 +1,32 @@#include <linux/kernel.h> +#include <linux/hrtime.h> #include <asm/timer.h> - +/* +* export this here so it can be used by more than one clock source +*/ +unsigned long fast_gettimeoffset_quotient;/* list of externed timers */ extern struct timer_opts timer_pit;extern struct timer_opts timer_tsc; +extern struct timer_opts hrtimer_tsc; +extern struct timer_opts hrtimer_pm; +extern struct timer_opts hrtimer_pit;/* list of timers, ordered by preference, NULL terminated */ static struct timer_opts* timers[] = { +#ifdef CONFIG_HIGH_RES_TIMERS +#ifdef CONFIG_HIGH_RES_TIMER_ACPI_PM + &hrtimer_pm, +#elif CONFIG_HIGH_RES_TIMER_TSC + &hrtimer_tsc, +#elif CONFIG_HIGH_RES_TIMER_PIT + &hrtimer_pit, +#endif +#else &timer_tsc, #ifndef CONFIG_X86_TSC &timer_pit, +#endif #endif NULL, };
arch/i386/kernel/timers/timer_pit.c +1 -0
@@ -9,6 +9,7 @@#include <asm/mpspec.h> #include <asm/timer.h> #include <asm/io.h> +#include <linux/hrtime.h> extern spinlock_t i8259A_lock;extern spinlock_t i8253_lock;
arch/i386/kernel/timers/timer_tsc.c +1 -1
@@ -26,7 +26,7 @@* Equal to 2^32 * (1 / (clocks per usec) ). * Initialized in time_init. */ -unsigned long fast_gettimeoffset_quotient; +extern unsigned long fast_gettimeoffset_quotient;static unsigned long get_offset_tsc (void ) {
arch/i386/mach-generic/do_timer.h +5 -0
@@ -14,6 +14,11 @@static inline void do_timer_interrupt_hook (struct pt_regs *regs) {do_timer (regs); +IF_HIGH_RES ( + if (!(new_jiffie() & 1)) + return; + jiffies_intr = 0; + )/* * In the SMP case we use the local APIC timer interrupt to do the * profiling, except when we simulate SMP mode on a uniprocessor
include/asm-i386/hrtime-M386.h +247 -0
247 lines not on this page · raw message
include/asm-i386/hrtime-M586.h +165 -0
165 lines not on this page · raw message
include/asm-i386/hrtime-Macpi.h +184 -0
184 lines not on this page · raw message
include/asm-i386/hrtime.h +486 -0
486 lines not on this page · raw message
include/asm-i386/sc_math.h +143 -0
143 lines not on this page · raw message
include/asm-i386/signal.h +2 -0
@@ -3,6 +3,8 @@#include <linux/types.h> #include <linux/linkage.h> +#include <linux/time.h> +#include <asm/ptrace.h> /* Avoid too many header ordering problems. */ struct siginfo ;