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>