Date: Fri, 6 Dec 1996 19:25:16 +0900 (JST) From: ohashi@mickey.ai.kyutech.ac.jp (Takeshi OHASHI) To: current@freebsd.org Cc: ohashi@mickey.ai.kyutech.ac.jp Subject: DELAY() in clock.c Message-ID: <199612061025.TAA03098@atohasi.mickey.ai.kyutech.ac.jp>
next in thread | raw e-mail | index | archive | help
Hi everyone,
I am a new subscriber of currnet, and I reported a bug of clock.c.
>Category: i386
>Responsible: freebsd-bugs
>Synopsis: DELAY() won't work for fast CPUs
>Arrival-Date: Mon Nov 4 21:00:01 PST 1996
This problem would make hanging up the system, especially that is
a Pentium or Pentum Pro box. For example, my Pentium Pro 200 box hung
up by keybord and NIC. I reported a quick bug fix patch with it.
We discussed the patch in freebsd-users-jp@jp.freebsd.org.
Many users said that it was a serious problem and the patch fixed it.
We made a new patch and tested it. We want to commit it as soon as
possible. Please check the following patch for /usr/src/sys/i386/isa/clock.c.
Thank you.
--
Takeshi OHASHI, Kyushu Inst. of Tech.
ohashi@mickey.ai.kyutech.ac.jp
--- clock.c.orig Sat Oct 26 09:11:57 1996
+++ clock.c Mon Dec 2 22:58:36 1996
@@ -133,6 +133,8 @@
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
+static u_int delay_offset = 20;
+
/* Values for timerX_state: */
#define RELEASED 0
#define RELEASE_PENDING 1
@@ -385,7 +387,7 @@
* multiplications and divisions to scale the count take a while).
*/
prev_tick = getit();
- n -= 20;
+ n = (n <= delay_offset) ? 1 : (n - delay_offset);
/*
* Calculate (n * (timer_freq / 1e6)) without using floating point
* and without any avoidable overflows.
@@ -485,6 +487,7 @@
{
u_int count, prev_count, tot_count;
int sec, start_sec, timeout;
+ int start_tick, end_tick, delay;
printf("Calibrating clock(s) relative to mc146818A clock ... ");
if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
@@ -564,6 +567,25 @@
#endif
printf("i8254 clock: %u Hz\n", tot_count);
+
+ /* init delay_offset */
+ delay_offset = 0;
+ /* some machine has too small max_count */
+ delay = timer0_max_count / 10 * 1000000 / timer_freq;
+ do {
+ start_tick = getit();
+ DELAY(delay);
+ end_tick = getit();
+ } while (start_tick <= end_tick);
+ /* avoid overflow */
+ delay_offset = (start_tick - end_tick) * 1000000.0 / timer_freq - delay;
+#ifdef DELAYOFFSETDEBUG
+ printf("DELAY: %d usec\n", delay);
+ printf("DELAY offset: %u usec\n", delay_offset);
+#endif
+ if (!(0 < delay_offset || delay_offset < 20))
+ delay_offset = 20;
+
return (tot_count);
fail:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612061025.TAA03098>
