svn commit: r247068 - head/sys/x86/isa
Warner Losh
imp at bsdimp.com
Thu Feb 21 14:52:41 UTC 2013
On Feb 21, 2013, at 5:31 AM, Bruce Evans wrote:
> On Thu, 21 Feb 2013, Warner Losh wrote:
>
>> Log:
>> Fix broken usage of splhigh() by removing it.
>
> 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
>> ==============================================================================
>> --- 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;
>>
>> /* 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
>>
>> /* wait for time update to complete */
>> /* If RTCSA_TUP is zero, we have at least 244us before next update */
>
> 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 = splhigh();
>
> It used to do something...
>
>> - while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
>> - splx(s);
>> - s = splhigh();
>> - }
>> + while (rtcin(RTC_STATUSA) & RTCSA_TUP)
>> + continue;
>
> 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 = 0;
>> ct.sec = readrtc(RTC_SEC);
>> ct.min = readrtc(RTC_MIN);
>>
>
> 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).
>
> 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=time 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
More information about the svn-src-head
mailing list