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.
This commit is contained in:
parent
22b9cd6f99
commit
835bd1ce62
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=19172
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user