Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Aug 2001 00:54:21 +0200
From:      Tor.Egge@fast.no
To:        mb@imp.ch
Cc:        bde@zeta.org.au, bkarp@icsi.berkeley.edu, kpielorz@tdx.co.uk, sthaug@nethelp.no, atrn@zeta.org.au, roberto@eurocontrol.fr, drussell@saturn-tech.com, phk@FreeBSD.ORG, Patrick.Guelat@imp.ch, freebsd-hackers@FreeBSD.ORG, freebsd-smp@FreeBSD.ORG
Subject:   Re: Clock speedup on 4.X FreeBSD SMP and serverworks chipset
Message-ID:  <200108302254.AAA75808@midten.fast.no>
In-Reply-To: Your message of "Thu, 30 Aug 2001 17:14:33 %2B0200 (CEST)"
References:  <20010830171101.I676-100000@levais.imp.ch>

next in thread | previous in thread | raw e-mail | index | archive | help

> --- 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 majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108302254.AAA75808>