Match delay/DELAY on x86 with delay(9). It takes an unsigned int as

argument. Use this and replace the inline assembly (mul + div using the
64bit intermediate result) with normal 32bit multiplication and
division. The compiler can turn the division into a multiplication and
shift, making it even cheaper then the original assembly. For extreme
long delays, just use 64bit arithmetic.
This commit is contained in:
joerg 2007-10-26 13:24:39 +00:00
parent c71c45f606
commit 930e1f6e1d
9 changed files with 65 additions and 77 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.64 2007/10/18 15:28:32 yamt Exp $ */
/* $NetBSD: machdep.c,v 1.65 2007/10/26 13:24:39 joerg Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.64 2007/10/18 15:28:32 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.65 2007/10/26 13:24:39 joerg Exp $");
#include "opt_user_ldt.h"
#include "opt_ddb.h"
@ -211,7 +211,7 @@ struct vm_map *phys_map = NULL;
extern paddr_t avail_start, avail_end;
void (*delay_func)(int) = i8254_delay;
void (*delay_func)(unsigned int) = i8254_delay;
void (*initclock_func)(void) = i8254_initclocks;
#ifdef MTRR

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.29 2007/10/18 15:28:34 yamt Exp $ */
/* $NetBSD: cpu.h,v 1.30 2007/10/26 13:24:39 joerg Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -244,7 +244,7 @@ extern void cpu_signotify(struct lwp *);
/*
* We need a machine-independent name for this.
*/
extern void (*delay_func)(int);
extern void (*delay_func)(unsigned int);
#define DELAY(x) (*delay_func)(x)
#define delay(x) (*delay_func)(x)
@ -288,7 +288,7 @@ void child_trampoline(void);
/* clock.c */
void initrtclock(u_long);
void startrtclock(void);
void i8254_delay(int);
void i8254_delay(unsigned int);
void i8254_microtime(struct timeval *);
void i8254_initclocks(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.610 2007/10/18 15:28:35 yamt Exp $ */
/* $NetBSD: machdep.c,v 1.611 2007/10/26 13:24:40 joerg Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006 The NetBSD Foundation, Inc.
@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.610 2007/10/18 15:28:35 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.611 2007/10/26 13:24:40 joerg Exp $");
#include "opt_beep.h"
#include "opt_compat_ibcs2.h"
@ -264,7 +264,7 @@ struct vm_map *phys_map = NULL;
extern paddr_t avail_start, avail_end;
void (*delay_func)(int) = i8254_delay;
void (*delay_func)(unsigned int) = i8254_delay;
void (*initclock_func)(void) = i8254_initclocks;
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.148 2007/10/18 15:28:37 yamt Exp $ */
/* $NetBSD: cpu.h,v 1.149 2007/10/26 13:24:40 joerg Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -281,7 +281,7 @@ extern void cpu_signotify(struct lwp *);
/*
* We need a machine-independent name for this.
*/
extern void (*delay_func)(int);
extern void (*delay_func)(unsigned int);
struct timeval;
#define DELAY(x) (*delay_func)(x)
@ -362,7 +362,7 @@ void lwp_trampoline(void);
/* clock.c */
void initrtclock(u_long);
void startrtclock(void);
void i8254_delay(int);
void i8254_delay(unsigned int);
void i8254_microtime(struct timeval *);
void i8254_initclocks(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock.c,v 1.11 2007/10/17 19:58:15 garbled Exp $ */
/* $NetBSD: clock.c,v 1.12 2007/10/26 13:24:40 joerg Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -121,7 +121,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.11 2007/10/17 19:58:15 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.12 2007/10/26 13:24:40 joerg Exp $");
/* #define CLOCKDEBUG */
/* #define CLOCK_PARANOIA */
@ -181,7 +181,8 @@ int clock_debug = 0;
#define DPRINTF(arg)
#endif
int gettick(void);
/* Used by lapic.c */
unsigned int gettick(void);
void sysbeep(int, int);
static void tickle_tc(void);
@ -194,7 +195,7 @@ static int cmoscheck(void);
static int clock_expandyear(int);
static inline int gettick_broken_latch(void);
static unsigned int gettick_broken_latch(void);
static volatile uint32_t i8254_lastcount;
static volatile uint32_t i8254_offset;
@ -253,7 +254,7 @@ static int ticks[6];
* machdep sets the variable 'clock_broken_latch' to indicate it.
*/
int
static unsigned int
gettick_broken_latch(void)
{
u_long flags;
@ -449,7 +450,7 @@ i8254_get_timecount(struct timecounter *tc)
return (count);
}
int
unsigned int
gettick(void)
{
u_long flags;
@ -478,9 +479,10 @@ gettick(void)
* Don't rely on this being particularly accurate.
*/
void
i8254_delay(int n)
i8254_delay(unsigned int n)
{
int delay_tick, odelay_tick;
unsigned int cur_tick, initial_tick;
int remaining;
static const int delaytab[26] = {
0, 2, 3, 4, 5, 6, 7, 9, 10, 11,
12, 13, 15, 16, 17, 18, 19, 21, 22, 23,
@ -495,49 +497,34 @@ i8254_delay(int n)
* Read the counter first, so that the rest of the setup overhead is
* counted.
*/
odelay_tick = gettick();
initial_tick = gettick();
if (n <= 25)
n = delaytab[n];
else {
#ifdef __GNUC__
remaining = delaytab[n];
else if (n <= UINT_MAX / TIMER_FREQ) {
/*
* Calculate ((n * TIMER_FREQ) / 1e6) using explicit assembler
* code so we can take advantage of the intermediate 64-bit
* quantity to prevent loss of significance.
* For unsigned arithmetic, division can be replaced with
* multiplication with the inverse and a shift.
*/
int m;
__asm volatile("mul %3"
: "=a" (n), "=d" (m)
: "0" (n), "r" (TIMER_FREQ));
__asm volatile("div %4"
: "=a" (n), "=d" (m)
: "0" (n), "1" (m), "r" (1000000));
#else
/*
* Calculate ((n * TIMER_FREQ) / 1e6) without using floating
* point and without any avoidable overflows.
remaining = n * TIMER_FREQ / 1000000;
} else {
/* This is a very long delay.
* Being slow here doesn't matter.
*/
int sec = n / 1000000,
usec = n % 1000000;
n = sec * TIMER_FREQ +
usec * (TIMER_FREQ / 1000000) +
usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 +
usec * (TIMER_FREQ % 1000) / 1000000;
#endif
remaining = (unsigned long long) n * TIMER_FREQ / 1000000;
}
while (n > 0) {
while (remaining > 0) {
#ifdef CLOCK_PARANOIA
int delta;
delay_tick = gettick();
if (delay_tick > odelay_tick)
delta = rtclock_tval - (delay_tick - odelay_tick);
cur_tick = gettick();
if (cur_tick > initial_tick)
delta = rtclock_tval - (cur_tick - initial_tick);
else
delta = odelay_tick - delay_tick;
delta = initial_tick - cur_tick;
if (delta < 0 || delta >= rtclock_tval / 2) {
DPRINTF(("delay: ignore ticks %.4x-%.4x",
odelay_tick, delay_tick));
initial_tick, cur_tick));
if (clock_broken_latch) {
DPRINTF((" (%.4x %.4x %.4x %.4x %.4x %.4x)\n",
ticks[0], ticks[1], ticks[2],
@ -546,15 +533,15 @@ i8254_delay(int n)
DPRINTF(("\n"));
}
} else
n -= delta;
remaining -= delta;
#else
delay_tick = gettick();
if (delay_tick > odelay_tick)
n -= rtclock_tval - (delay_tick - odelay_tick);
cur_tick = gettick();
if (cur_tick > initial_tick)
remaining -= rtclock_tval - (cur_tick - initial_tick);
else
n -= odelay_tick - delay_tick;
remaining -= initial_tick - cur_tick;
#endif
odelay_tick = delay_tick;
initial_tick = cur_tick;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: lapic.c,v 1.24 2007/10/17 19:58:17 garbled Exp $ */
/* $NetBSD: lapic.c,v 1.25 2007/10/26 13:24:41 joerg Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.24 2007/10/17 19:58:17 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.25 2007/10/26 13:24:41 joerg Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@ -75,10 +75,11 @@ __KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.24 2007/10/17 19:58:17 garbled Exp $");
#include <machine/i82489reg.h>
#include <machine/i82489var.h>
void lapic_delay(int);
void lapic_microtime(struct timeval *);
static u_int32_t lapic_gettick(void);
/* Referenced from vector.S */
void lapic_clockintr(void *, struct intrframe *);
static void lapic_delay(unsigned int);
static uint32_t lapic_gettick(void);
static void lapic_map(paddr_t);
static void lapic_hwmask(struct pic *, int);
@ -369,7 +370,7 @@ lapic_initclocks()
i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR);
}
extern int gettick(void); /* XXX put in header file */
extern unsigned int gettick(void); /* XXX put in header file */
extern int rtclock_tval; /* XXX put in header file */
extern void (*initclock_func)(void); /* XXX put in header file */
@ -455,7 +456,7 @@ lapic_calibrate_timer(ci)
/*
* Compute fixed-point ratios between cycles and
* microseconds to avoid having to do any division
* in lapic_delay and lapic_microtime.
* in lapic_delay.
*/
tmp = (1000000 * (u_int64_t)1<<32) / lapic_per_second;
@ -490,8 +491,8 @@ lapic_calibrate_timer(ci)
* delay for N usec.
*/
void lapic_delay(usec)
int usec;
static void
lapic_delay(unsigned int usec)
{
int32_t xtick, otick;
int64_t deltat; /* XXX may want to be 64bit */

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.44 2007/10/17 19:58:19 garbled Exp $ */
/* $NetBSD: machdep.c,v 1.45 2007/10/26 13:24:41 joerg Exp $ */
/* NetBSD: machdep.c,v 1.559 2004/07/22 15:12:46 mycroft Exp */
/*-
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.44 2007/10/17 19:58:19 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.45 2007/10/26 13:24:41 joerg Exp $");
#include "opt_beep.h"
#include "opt_compat_ibcs2.h"
@ -261,11 +261,11 @@ extern paddr_t avail_start, avail_end;
extern paddr_t pmap_pa_start, pmap_pa_end;
#ifdef ISA_CLOCK
void (*delay_func)(int) = i8254_delay;
void (*delay_func)(unsigned int) = i8254_delay;
void (*microtime_func)(struct timeval *) = i8254_microtime;
void (*initclock_func)(void) = i8254_initclocks;
#else
void (*delay_func)(int) = xen_delay;
void (*delay_func)(unsigned int) = xen_delay;
void (*initclock_func)(void) = xen_initclocks;
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.22 2007/10/17 19:58:28 garbled Exp $ */
/* $NetBSD: cpu.h,v 1.23 2007/10/26 13:24:41 joerg Exp $ */
/* NetBSD: cpu.h,v 1.113 2004/02/20 17:35:01 yamt Exp */
/*-
@ -269,7 +269,7 @@ extern void cpu_signotify(struct lwp *);
/*
* We need a machine-independent name for this.
*/
extern void (*delay_func)(int);
extern void (*delay_func)(unsigned int);
#define DELAY(x) (*delay_func)(x)
#define delay(x) (*delay_func)(x)
@ -351,12 +351,12 @@ void lwp_trampoline(void);
#ifdef ISA_CLOCK
void initrtclock(void);
void startrtclock(void);
void i8254_delay(int);
void i8254_delay(unsigned int);
void i8254_microtime(struct timeval *);
void i8254_initclocks(void);
#else
void startrtclock(void);
void xen_delay(int);
void xen_delay(unsigned int);
void xen_initclocks(void);
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock.c,v 1.40 2007/10/17 19:58:32 garbled Exp $ */
/* $NetBSD: clock.c,v 1.41 2007/10/26 13:24:44 joerg Exp $ */
/*
*
@ -34,7 +34,7 @@
#include "opt_xen.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.40 2007/10/17 19:58:32 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.41 2007/10/26 13:24:44 joerg Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -398,7 +398,7 @@ startrtclock()
* Wait approximately `n' microseconds.
*/
void
xen_delay(int n)
xen_delay(unsigned int n)
{
if (n < 500000) {
/*