Return to BSD News archive
Newsgroups: comp.os.386bsd.bugs
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!elroy.jpl.nasa.gov!sdd.hp.com!crash!fpm
From: fpm@crash.cts.com (Frank Maclachlan)
Subject: [NetBSD-0.8] Patch for kernel DELAY function
Organization: CTS Network Services (crash, ctsnet), El Cajon, CA
Date: 24 May 93 12:04:02 PDT
Message-ID: <1993May24.120402.23222@crash>
Keywords: patch NetBSD
Lines: 108
I hope that this is the correct group for this.
It was pointed out quite a while ago that the 386bsd kernel DELAY()
function didn't seem to work properly. In particular, the line
highlighted below:
/*
* Wait "n" microseconds. Relies on timer 0 to have 1Mhz clock, regardless
* of processor board speed. Note: timer had better have been programmed
* before this is first used!
*/
DELAY(n) {
int tick = getit(0,0) & 1;
while (n--) {
/* wait approximately 1 micro second */
while (tick == getit(0,0) & 1) ;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tick = getit(0,0) & 1;
}
}
should really be:
while (tick == (getit(0,0) & 1)) ;
This, however, causes the system to lock up when DELAY() is called.
The problem is that the processor is not fast enough to poll micro-
second events in this fashion. The original DELAY() is highly
processor speed dependent (uncalibrated software delay loop).
I replaced the DELAY() function in my NetBSD-0.8 system w/ a micro-
second delay routine based upon the calibrated spinwait() millisecond
delay routine Julian Elischer added to clock.c. The new DELAY() is
reasonably accurate and *IS* CPU speed independent.
A patch to the NetBSD-0.8 files is included below. The relevant files
are in /sys/i386/isa/.
==================== Cut here ===================
*** clock.c.ORIG Tue Mar 23 00:12:10 1993
--- clock.c Mon May 24 10:52:10 1993
***************
*** 261,263 ****
--- 261,283 ----
;
}
+
+ /*
+ * Delay approximately `usec' microseconds. Uses delaycount
+ * variable set up by findcpuspeed().
+ */
+ DELAY(usec)
+ int usec;
+ {
+ int msec, i;
+
+ /* Use spinwait() if delaying more than a millisecond. */
+ msec = usec / 1000;
+ if (msec > 0)
+ spinwait(msec);
+
+ /* Now delay for remaining usecs. */
+ usec = ((usec % 1000) * delaycount) / 1000;
+ for (i = 0; i < usec; i++)
+ ;
+ }
*** isa.c.ORIG Fri Apr 9 09:24:12 1993
--- isa.c Mon May 24 11:01:45 1993
***************
*** 531,560 ****
log(LOG_CRIT,"Too many ISA strayintr not logging any more\n");
}
- /*
- * Wait "n" microseconds. Relies on timer 0 to have 1Mhz clock, regardless
- * of processor board speed. Note: timer had better have been programmed
- * before this is first used!
- */
- DELAY(n) {
- int tick = getit(0,0) & 1;
-
- while (n--) {
- /* wait approximately 1 micro second */
- while (tick == getit(0,0) & 1) ;
-
- tick = getit(0,0) & 1;
- }
- }
-
- getit(unit, timer) {
- int port = (unit ? IO_TIMER2 : IO_TIMER1) + timer, val;
-
- val = inb(port);
- val = (inb(port) << 8) + val;
- return (val);
- }
-
extern int hz;
static beeping;
--- 531,536 ----
==================== Cut here ===================
--
UUCP: {hplabs!hp-sdd ucsd nosc}!crash!fpm
INET: fpm@crash.cts.com