diff options
author | bde <bde@FreeBSD.org> | 1996-10-25 13:01:56 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1996-10-25 13:01:56 +0000 |
commit | df0eda67f3449abc68f3b3b7a4b8088f713f9410 (patch) | |
tree | 5968eb78feb617d966921606e10992b228f61554 /sys | |
parent | 546845af741d292452163e8a23e043024e484fbf (diff) | |
download | FreeBSD-src-df0eda67f3449abc68f3b3b7a4b8088f713f9410.zip FreeBSD-src-df0eda67f3449abc68f3b3b7a4b8088f713f9410.tar.gz |
Improved biasing of i586 clock by adjusting for hardclock() latency.
I decided to do this for every hardclock() call instead of lazily
in microtime(). The lazy method is simpler but has more overhead
if microtime() is called a lot.
CPU_THISTICKLEN() is now a no-op and should probably go away.
Previously it did nothing directly but had the side effect of
setting i586_last_tick for CPU_CLOCKUPDATE() and i586_avg_tick for
debugging. CPU_CLOCKUPDATE() now uses a better method and
i586_avg_tick is too much trouble to maintain.
Reduced nesting of #includes in the usual case.
Increased nesting of #includes when CLOCK_HAIR is defined. This
is a kludge to get typedefs for inline functions only when the
inline functions are used. Normally only kern_clock.c defines
this. kern_clock.c can't include the i386 headers directly.
Removed unused LOCORE support.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/include/clock.h | 113 | ||||
-rw-r--r-- | sys/i386/include/clock.h | 113 | ||||
-rw-r--r-- | sys/kern/kern_clock.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_timeout.c | 3 |
5 files changed, 130 insertions, 105 deletions
diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h index 9c6646e..f20902f 100644 --- a/sys/amd64/include/clock.h +++ b/sys/amd64/include/clock.h @@ -3,48 +3,24 @@ * Garrett Wollman, September 1994. * This file is in the public domain. * - * $Id: clock.h,v 1.18 1996/10/10 10:25:26 bde Exp $ + * $Id: clock.h,v 1.19 1996/10/17 17:31:25 bde Exp $ */ #ifndef _MACHINE_CLOCK_H_ #define _MACHINE_CLOCK_H_ #if defined(I586_CPU) || defined(I686_CPU) - -/* - * When we update the clock, we also update this bias value which is - * automatically subtracted in microtime(). We assume that CPU_THISTICKLEN() - * has been called at some point in the past, so that an appropriate value is - * set up in i586_last_tick. (This works even if we are not being called - * from hardclock because hardclock will have run before and will made the - * call.) - */ -#define CPU_CLOCKUPDATE(otime, ntime) \ - do { \ - if (i586_ctr_freq != 0) { \ - disable_intr(); \ - i586_ctr_bias = i586_last_tick; \ - *(otime) = *(ntime); \ - enable_intr(); \ - } else { \ - *(otime) = *(ntime); \ - } \ - } while(0) - -#define CPU_THISTICKLEN(dflt) cpu_thisticklen(dflt) +#define CPU_CLOCKUPDATE(otime, ntime) cpu_clockupdate((otime), (ntime)) #else -#define CPU_CLOCKUPDATE(otime, ntime) \ - (*(otime) = *(ntime)) -#define CPU_THISTICKLEN(dflt) dflt +#define CPU_CLOCKUPDATE(otime, ntime) (*(otime) = *(ntime)) #endif +#define CPU_THISTICKLEN(dflt) dflt + #define I586_CTR_COMULTIPLIER_SHIFT 20 #define I586_CTR_MULTIPLIER_SHIFT 32 -#if defined(KERNEL) && !defined(LOCORE) -#include <sys/cdefs.h> -#include <machine/frame.h> - +#ifdef KERNEL /* * i386 to clock driver interface. * XXX almost all of it is misplaced. i586 stuff is done in isa/clock.c @@ -57,8 +33,6 @@ extern u_int i586_ctr_bias; extern u_int i586_ctr_comultiplier; extern u_int i586_ctr_freq; extern u_int i586_ctr_multiplier; -extern long long i586_last_tick; -extern unsigned long i586_avg_tick; #endif extern int statclock_disable; extern u_int timer_freq; @@ -67,27 +41,11 @@ extern u_int timer0_overflow_threshold; extern u_int timer0_prescaler_count; extern int wall_cmos_clock; -#if defined(I586_CPU) || defined(I686_CPU) -static __inline u_long -cpu_thisticklen(u_long dflt) -{ - long long old; - long len; - - if (i586_ctr_freq != 0) { - old = i586_last_tick; - i586_last_tick = rdtsc(); - len = ((i586_last_tick - old) * i586_ctr_multiplier) - >> I586_CTR_MULTIPLIER_SHIFT; - i586_avg_tick = i586_avg_tick * 15 / 16 + len / 16; - } - return dflt; -} -#endif - /* * Driver to clock driver interface. */ +struct clockframe; + void DELAY __P((int usec)); int acquire_timer0 __P((int rate, void (*function)(struct clockframe *frame))); @@ -105,6 +63,59 @@ void rtc_outb __P((int val)); #endif int sysbeep __P((int pitch, int period)); -#endif /* KERNEL && !LOCORE */ +#ifdef CLOCK_HAIR + +#include <i386/isa/isa.h> /* XXX */ +#include <i386/isa/timerreg.h> /* XXX */ + +static __inline u_int +clock_latency(void) +{ + u_char high, low; + + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); + low = inb(TIMER_CNTR0); + high = inb(TIMER_CNTR0); + return (timer0_prescaler_count + timer0_max_count + - ((high << 8) | low)); +} + +#if defined(I586_CPU) || defined(I686_CPU) +/* + * When we update `time', on i586's we also update `i586_ctr_bias' + * atomically. `i586_ctr_bias' is the best available approximation to + * the value of the i586 counter (mod 2^32) at the time of the i8254 + * counter transition that caused the clock interrupt that caused the + * update. clock_latency() gives the time between the transition and + * the update to within a few usec provided another such transition + * hasn't occurred. We don't bother checking for counter overflow as + * in microtime(), since if it occurs then we're close to losing clock + * interrupts. + */ +static __inline void +cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime) +{ + if (i586_ctr_freq != 0) { + u_int i586_count; /* truncated */ + u_int i8254_count; + + disable_intr(); + i8254_count = clock_latency(); + i586_count = rdtsc(); + i586_ctr_bias = i586_count + - (u_int) + (((unsigned long long)i586_ctr_comultiplier + * i8254_count) + >> I586_CTR_COMULTIPLIER_SHIFT); + *otime = *ntime; + enable_intr(); + } else + *otime = *ntime; +} +#endif /* I586_CPU || I686_CPU */ + +#endif /* CLOCK_HAIR */ + +#endif /* KERNEL */ #endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h index 9c6646e..f20902f 100644 --- a/sys/i386/include/clock.h +++ b/sys/i386/include/clock.h @@ -3,48 +3,24 @@ * Garrett Wollman, September 1994. * This file is in the public domain. * - * $Id: clock.h,v 1.18 1996/10/10 10:25:26 bde Exp $ + * $Id: clock.h,v 1.19 1996/10/17 17:31:25 bde Exp $ */ #ifndef _MACHINE_CLOCK_H_ #define _MACHINE_CLOCK_H_ #if defined(I586_CPU) || defined(I686_CPU) - -/* - * When we update the clock, we also update this bias value which is - * automatically subtracted in microtime(). We assume that CPU_THISTICKLEN() - * has been called at some point in the past, so that an appropriate value is - * set up in i586_last_tick. (This works even if we are not being called - * from hardclock because hardclock will have run before and will made the - * call.) - */ -#define CPU_CLOCKUPDATE(otime, ntime) \ - do { \ - if (i586_ctr_freq != 0) { \ - disable_intr(); \ - i586_ctr_bias = i586_last_tick; \ - *(otime) = *(ntime); \ - enable_intr(); \ - } else { \ - *(otime) = *(ntime); \ - } \ - } while(0) - -#define CPU_THISTICKLEN(dflt) cpu_thisticklen(dflt) +#define CPU_CLOCKUPDATE(otime, ntime) cpu_clockupdate((otime), (ntime)) #else -#define CPU_CLOCKUPDATE(otime, ntime) \ - (*(otime) = *(ntime)) -#define CPU_THISTICKLEN(dflt) dflt +#define CPU_CLOCKUPDATE(otime, ntime) (*(otime) = *(ntime)) #endif +#define CPU_THISTICKLEN(dflt) dflt + #define I586_CTR_COMULTIPLIER_SHIFT 20 #define I586_CTR_MULTIPLIER_SHIFT 32 -#if defined(KERNEL) && !defined(LOCORE) -#include <sys/cdefs.h> -#include <machine/frame.h> - +#ifdef KERNEL /* * i386 to clock driver interface. * XXX almost all of it is misplaced. i586 stuff is done in isa/clock.c @@ -57,8 +33,6 @@ extern u_int i586_ctr_bias; extern u_int i586_ctr_comultiplier; extern u_int i586_ctr_freq; extern u_int i586_ctr_multiplier; -extern long long i586_last_tick; -extern unsigned long i586_avg_tick; #endif extern int statclock_disable; extern u_int timer_freq; @@ -67,27 +41,11 @@ extern u_int timer0_overflow_threshold; extern u_int timer0_prescaler_count; extern int wall_cmos_clock; -#if defined(I586_CPU) || defined(I686_CPU) -static __inline u_long -cpu_thisticklen(u_long dflt) -{ - long long old; - long len; - - if (i586_ctr_freq != 0) { - old = i586_last_tick; - i586_last_tick = rdtsc(); - len = ((i586_last_tick - old) * i586_ctr_multiplier) - >> I586_CTR_MULTIPLIER_SHIFT; - i586_avg_tick = i586_avg_tick * 15 / 16 + len / 16; - } - return dflt; -} -#endif - /* * Driver to clock driver interface. */ +struct clockframe; + void DELAY __P((int usec)); int acquire_timer0 __P((int rate, void (*function)(struct clockframe *frame))); @@ -105,6 +63,59 @@ void rtc_outb __P((int val)); #endif int sysbeep __P((int pitch, int period)); -#endif /* KERNEL && !LOCORE */ +#ifdef CLOCK_HAIR + +#include <i386/isa/isa.h> /* XXX */ +#include <i386/isa/timerreg.h> /* XXX */ + +static __inline u_int +clock_latency(void) +{ + u_char high, low; + + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); + low = inb(TIMER_CNTR0); + high = inb(TIMER_CNTR0); + return (timer0_prescaler_count + timer0_max_count + - ((high << 8) | low)); +} + +#if defined(I586_CPU) || defined(I686_CPU) +/* + * When we update `time', on i586's we also update `i586_ctr_bias' + * atomically. `i586_ctr_bias' is the best available approximation to + * the value of the i586 counter (mod 2^32) at the time of the i8254 + * counter transition that caused the clock interrupt that caused the + * update. clock_latency() gives the time between the transition and + * the update to within a few usec provided another such transition + * hasn't occurred. We don't bother checking for counter overflow as + * in microtime(), since if it occurs then we're close to losing clock + * interrupts. + */ +static __inline void +cpu_clockupdate(volatile struct timeval *otime, struct timeval *ntime) +{ + if (i586_ctr_freq != 0) { + u_int i586_count; /* truncated */ + u_int i8254_count; + + disable_intr(); + i8254_count = clock_latency(); + i586_count = rdtsc(); + i586_ctr_bias = i586_count + - (u_int) + (((unsigned long long)i586_ctr_comultiplier + * i8254_count) + >> I586_CTR_COMULTIPLIER_SHIFT); + *otime = *ntime; + enable_intr(); + } else + *otime = *ntime; +} +#endif /* I586_CPU || I686_CPU */ + +#endif /* CLOCK_HAIR */ + +#endif /* KERNEL */ #endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index d94d53e..b1f3bb0 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.26 1996/07/30 16:59:22 bde Exp $ + * $Id: kern_clock.c,v 1.27 1996/10/10 10:25:03 bde Exp $ */ /* Portions of this software are covered by the following: */ @@ -76,6 +76,7 @@ #include <sys/sysctl.h> #include <machine/cpu.h> +#define CLOCK_HAIR /* XXX */ #include <machine/clock.h> #ifdef GPROF diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index d94d53e..b1f3bb0 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.26 1996/07/30 16:59:22 bde Exp $ + * $Id: kern_clock.c,v 1.27 1996/10/10 10:25:03 bde Exp $ */ /* Portions of this software are covered by the following: */ @@ -76,6 +76,7 @@ #include <sys/sysctl.h> #include <machine/cpu.h> +#define CLOCK_HAIR /* XXX */ #include <machine/clock.h> #ifdef GPROF diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index d94d53e..b1f3bb0 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.26 1996/07/30 16:59:22 bde Exp $ + * $Id: kern_clock.c,v 1.27 1996/10/10 10:25:03 bde Exp $ */ /* Portions of this software are covered by the following: */ @@ -76,6 +76,7 @@ #include <sys/sysctl.h> #include <machine/cpu.h> +#define CLOCK_HAIR /* XXX */ #include <machine/clock.h> #ifdef GPROF |