[SDL] SDL_GetTicks() goes backwards - blame assigned
Daniel Phillips
phillips at arcor.de
Tue Dec 24 21:04:09 PST 2002
On Tuesday 24 December 2002 02:26, David Olofson wrote:
> On Tuesday 24 December 2002 02.08, Daniel Phillips wrote:
> > On Tuesday 24 December 2002 01:56, you wrote:
> > > On Tuesday 24 December 2002 00:46, Daniel Phillips wrote:
> > > > This is on Debian Sid, libsdl1.2debian-all, Version: 1.2.4-1.
> > >
> > > One thing I forget to mention: it's Mesa's software emulation -
> > > runs around 10 fps on the 500 Mhz laptop I'm playing on at the
>
> Wait! Laptop... Check two things:
>
> 1. Is the machine using CPU clock throtling?
>
> 2. Is RDTSC used for gettimeofday()?
>
> Can't quite see how this could make time go *backwards*, but I don't
> know much about how Linux deals with it.
Well, now I know this is *not* an SDL issue. I wrapped a debug check around
gettimeofday, and sure enough, it goes backwards frequently, always by
something close to 24000 microseconds:
static long long check2;
Uint32 SDL_GetTicks (void)
{
#ifdef USE_RDTSC
unsigned long long now;
if ( ! cpu_mhz1000 ) {
return 0; /* Shouldn't happen. BUG!! */
}
rdtsc(now);
return (Uint32)((now-start)/cpu_mhz1000);
#else
struct timeval now;
Uint32 ticks;
long long ticks2;
gettimeofday(&now, NULL);
ticks2 = (((long long) now.tv_sec) * 1000000) + now.tv_usec;
if (ticks2 - check2 < 0)
printf("gettimeofday went backwards by %i microseconds!\n", check2 - ticks2);
check2 = ticks2;
ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
return(ticks);
#endif /* USE_RDTSC */
}
The error check triggers every few seconds. So this is definately something
lower level than SDL. Things work perfectly with USE_RDTSC. So it's now
narrowed down to one of:
- Glibc bug
- Toolchain bug causing a faulty build
- Kernel bug
Since this is a pretty serious issue, plus it's rare, I suppose I have the
moral responsibility to pursue it further. I'm not looking forward to
building/installing glibc though, so next I'll see if it's kernel-dependent
and try to postpone mucking with glibc as long as possible. I'd far rather
muck around with the kernel than glibc, maybe it's just me.
Moral of the story: it is a bad idea to trust the system timer to run
forward correctly at all times. Putting in code to handle small time
reversals is highly recommended. At least, do not crash or freeze if time
happens to go backward for a moment.
Second moral: Dividing the time result into two longs, one part with
microseconds, was an incredibly stupid design decision on the part of the
glibc people and just had to bite sometime. Long longs are not that scary,
people.
Recommendation for SDL: USE_RDTSC should be the default. It's more
reliable and faster, and where exactly are you going to find a 486 running
SDL?
Thanks for all the input everybody.
--
Daniel
More information about the SDL
mailing list