Subject: kern/10699: microtime() is not monotomically increasing using Cyrix MediaGX i8254
To: None <gnats-bugs@gnats.netbsd.org>
From: None <joff@newmonics.com>
List: netbsd-bugs
Date: 07/27/2000 21:13:14
>Number: 10699
>Category: kern
>Synopsis: microtime() is not monotomically increasing using Cyrix MediaGX i8254
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jul 27 21:14:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: Jesse Off
>Release: 1.4.2
>Organization:
NewMonics, Inc.
>Environment:
NetBSD cypher 1.4.2 NetBSD 1.4.2 (GENERIC) #3: Wed Mar 15 23:41:54 PST 2000 toddpw@vader.toddpw.net:/usr/src/sys/arch/i386/compile/GENERIC i386
Cyrix MediaGX 266mx.
>Description:
microtime() (and hence, the gettimeofday() syscall) uses the buggy Cyrix
MediaGX i8254 with the broken LATCH command. The result is that
gettimeofday() sometimes goes backward in time on sequential calls
therefore causing havoc on applications (and drivers, if any)
that depend on a monotomically increasing microtime(). (which is what is
documented in the microtime manpage)
>How-To-Repeat:
Run the following on a MediaGX system. You will get an assertion
failure somewhere between 0-500 iterations.
#include<sys/time.h>
#include<unistd.h>
#include<assert.h>
int main(void) {
struct timeval tv[2];
struct timeval *now, *prev;
int iterations = 0;
now = &tv[0];
prev = &tv[1];
gettimeofday(prev, NULL);
for(;;) {
struct timeval *tmp;
gettimeofday(now, NULL);
assert((now->tv_sec > prev->tv_sec) ||
(now->tv_sec == prev->tv_sec && now->tv_usec >= prev->tv_usec));
tmp = prev;
prev = now;
now = tmp;
iterations++;
}
}
>Fix:
arch/i386/isa/clock.c has a decent workaround which reads the 8254
multiple times, but microtime.s does not use this and only reads the
8254 once. There are a number of potential fixes:
*) Blow it off (Not really a fix, but MediaGX's aren't being
manufactured anymore.)
*) use Pentium RDTSC for microtime like OpenBSD does.
*) Don't even use the 8254 latch for microtime. Just take the timeval from
the last clock tick. Sure, low resolution and the potential
for reading the same value twice, but at least
gettimeofday() won't go backward in time.
>Release-Note:
>Audit-Trail:
>Unformatted: