Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Feb 2013 07:52:37 -0700
From:      Warner Losh <imp@bsdimp.com>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, Warner Losh <imp@freebsd.org>
Subject:   Re: svn commit: r247068 - head/sys/x86/isa
Message-ID:  <9BB56E45-A272-46D7-AF3F-833424017F2D@bsdimp.com>
In-Reply-To: <20130221225538.J1447@besplex.bde.org>
References:  <201302210040.r1L0e80m095140@svn.freebsd.org> <20130221225538.J1447@besplex.bde.org>

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

On Feb 21, 2013, at 5:31 AM, Bruce Evans wrote:

> On Thu, 21 Feb 2013, Warner Losh wrote:
>=20
>> Log:
>> Fix broken usage of splhigh() by removing it.
>=20
> This is more broken than before.  The splhigh() served to indicate
> missing locking.

Depends on what you mean by more :)  It is less depessimized after the =
nopification of splhigh().

>> Modified: head/sys/x86/isa/atrtc.c
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- head/sys/x86/isa/atrtc.c	Thu Feb 21 00:36:12 2013	=
(r247067)
>> +++ head/sys/x86/isa/atrtc.c	Thu Feb 21 00:40:08 2013	=
(r247068)
>> @@ -328,7 +328,6 @@ static int
>> atrtc_gettime(device_t dev, struct timespec *ts)
>> {
>> 	struct clocktime ct;
>> -	int s;
>>=20
>> 	/* Look if we have a RTC present and the time is valid */
>> 	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
>> @@ -338,11 +337,8 @@ atrtc_gettime(device_t dev, struct times
>>=20
>> 	/* wait for time update to complete */
>> 	/* If RTCSA_TUP is zero, we have at least 244us before next =
update */
>=20
> As the comment says, this is time-critical code.  It needs to do =
something
> to prevent it being preempted for more than 244 usec

That's a long time...

>> -	s =3D splhigh();
>=20
> It used to do something...
>=20
>> -	while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
>> -		splx(s);
>> -		s =3D splhigh();
>> -	}
>> +	while (rtcin(RTC_STATUSA) & RTCSA_TUP)
>> +		continue;
>=20
> You should probably have changed this to a critical section like you =
did
> in ppc.  Disabling hardware interrupts would be even better.

I'll replace with a critical section.

> There is a problem with the "show rtc" command in ddb.  It was born
> broken (racy), and the races were turned into deadlocks by adding
> locking in rtcin().  So if you trace through this code, then
> "show rtc" while holding the lock in rtcin() will deadlock.  It is a
> bug for ddb to call any code that might try to acquire a mutex, but
> "show rtc" always calls rtcin() and rtcin() always tries to aquire a
> mutex.  Similar deadlocks on the i8254 lock in DELAY() are worked
> around by not trying to acquire the lock in kdb mode.

kbd_active is what I need to check, right? I'll fix that while here.

>> 	ct.nsec =3D 0;
>> 	ct.sec =3D readrtc(RTC_SEC);
>> 	ct.min =3D readrtc(RTC_MIN);
>>=20
>=20
> There are 8 or 9 readrtc()'s altogether.  These must be atomic, and =
all
> within the 244 usec limit.  There is considerable danger of exceeding =
the
> limit without even being preempted.  Each readrtc() does 1 or 4 isa =
bus
> accesses.  I've seen a single isa bus access taking 139 usec (delayed =
by
> PCI DMA).
>=20
> Another way of doing this without any locking against preemption or
> timing magic is to read the time before and after.  If it took more =
than
> 244 usec from before seeing RTCSA_TUP deasserted to after the last
> readrtc(), then retry.

By computing a time difference, or by checking RTCSA_TUP?

> My version still depends on splhigh() working, but it does more
> sophisticated waiting that gives a full second to read the registers
> without getting more than a stale time.  The above reads an RTC value
> that may be stale by almost 1 second.  My version busy-waits until
> just after after the counter rolls over.  This is only suitable for
> boot=3Dtime initialization.  Debugging printfs show that this never =
got
> preempted over the last few years -- the whole operation always
> completed within about 40 usec of seeing the rollover.

So this isn't a problem on fast machines?

> Linux does even more sophisticated waiting for writing the registers,
> so as not to be off by another second in the write operation.

Yea, that would be nice, I may have to look into that, once I'm done =
fetching these stones.

Warner




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9BB56E45-A272-46D7-AF3F-833424017F2D>