> --- sys/i386/isa/clock.c Thu Aug 30 17:01:31 2001
> +++ sys/i386/isa/clock.c.new Thu Aug 30 17:01:29 2001
> @@ -1203,7 +1203,7 @@
> high = inb(TIMER_CNTR0);
> count = timer0_max_count - ((high << 8) | low);
> if (count < i8254_lastcount ||
> - (!i8254_ticked && (clkintr_pending ||
> + (!i8254_ticked && (/*clkintr_pending || */
> ((count < 20 || (!(ef & PSL_I) && count < timer0_max_count /
> 2u)) &&
> #ifdef APIC_IO
> #define lapic_irr1 ((volatile u_int *)&lapic)[0x210 / 4] /*
> XXX XXX */
>
> We are looking now why this happens.
One scenario where this problem will happen:
CPU #0 CPU#1
calls i8254_gettimecount
locks clock_lock
reads high value for count
Gets interrupt from i8254
sets clkintr_pending
fails to get Giant
forward interrupt
sees clkintr_pending
steps i8254_offset due to clkintr_pending
sets i8254_ticked to 1
sets i8254_lastcount to high value
unlocks clock_lock
receive forwarded interrupt
locks clock_lock
doesn't step i8254_offset due to
i8254_ticked being 1
doesn't set i8254_lastcount
calls i8254_gettimecount again
locks clock_lock
reads low value for count
steps i8254_offset due to
count < i8254_lastcount
sets i8254_ticked to 1
The problem here is that CPU#1 fails to hold clock_lock while setting
clkintr_pending, causing i8254_offset to be stepped twice, first due
to clkintr_pending, then due to i8254_lastcount being larger than count.
According to icu_setup(), CPU interrupt vector TPR_FAST_INTS +
apic_8254_intr is used, normally 0x60. Thus any check for lapic_irr1
is bogus. Checking lapic_irr3 isn't failsafe since the interrupt can
be in the process of being delivered to another CPU.
- Tor Egge
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message