SDL_GetTicks() goes backwards

The attached program (a slightly modified version of Jakob Thomsen’s
WaveGL.c) puts a shell around SDL_GetTicks to check for time going backwards,
like this:

static int ticks;

int paranoid_set_ticks(void)
{
int newticks = SDL_GetTicks();
if (newticks - ticks < 0) {
printf(“Time went backwards by %i ticks!\n”, ticks - newticks);
return ticks; // try to pretend it didn’t happen
}
return ticks = newticks;
}

This is on Debian Sid, libsdl1.2debian-all, Version: 1.2.4-1. Could anyone
who’s interested in this problem please try the attached program and see if
it produces “Time went backwards” messages on the console. It’s kind of hard
to believe a bug like this could be in the mainline SDL tree without being
noticed, so I suspect it’s a compiler or toolchain issue. Anyway, I’ll track
it down in the fullness of time, but some independent confirmation would be
helpful.

To compile:

gcc time_goes_backwards.c -lSDL -lGL -lGLU && ./a.out–
Daniel
-------------- next part --------------
A non-text attachment was scrubbed…
Name: time_goes_backwards.tgz
Type: application/x-gzip
Size: 3277 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20021223/dda15bad/attachment.bin

if you notice that time goes backwards aprox. every 32,767 ticks then the
problem is that you are storing ticks (unsigned long int i think) in an int.
The problem you might be having is for instance if you have an unsigned char
set to 255 then add 1 it goes to 0 so it would apear that it went backwards
255 ticks…maybe youve ruled this out already but hope it helps!> ----- Original Message -----

From: phillips@arcor.de (Daniel Phillips)
To:
Sent: Monday, December 23, 2002 3:46 PM
Subject: [SDL] SDL_GetTicks() goes backwards

The attached program (a slightly modified version of Jakob Thomsen’s
WaveGL.c) puts a shell around SDL_GetTicks to check for time going
backwards,
like this:

static int ticks;

int paranoid_set_ticks(void)
{
int newticks = SDL_GetTicks();
if (newticks - ticks < 0) {
printf(“Time went backwards by %i ticks!\n”, ticks - newticks);
return ticks; // try to pretend it didn’t happen
}
return ticks = newticks;
}

This is on Debian Sid, libsdl1.2debian-all, Version: 1.2.4-1. Could
anyone
who’s interested in this problem please try the attached program and see
if
it produces “Time went backwards” messages on the console. It’s kind of
hard
to believe a bug like this could be in the mainline SDL tree without being
noticed, so I suspect it’s a compiler or toolchain issue. Anyway, I’ll
track
it down in the fullness of time, but some independent confirmation would
be
helpful.

To compile:

gcc time_goes_backwards.c -lSDL -lGL -lGLU && ./a.out


Daniel

if you notice that time goes backwards aprox. every 32,767 ticks then the
problem is that you are storing ticks (unsigned long int i think) in an
int. The problem you might be having is for instance if you have an
unsigned char set to 255 then add 1 it goes to 0 so it would apear that it
went backwards 255 ticks…maybe youve ruled this out already but hope it
helps!

Time goes backwards every few hundred milliseconds, by 8-20 ms. Anyway, if
you check the code, you’ll see the signedness is correct.On Tuesday 24 December 2002 01:16, Atrix Wolfe wrote:

----- Original Message -----
From: “Daniel Phillips” <@Daniel_Phillips>
To:
Sent: Monday, December 23, 2002 3:46 PM
Subject: [SDL] SDL_GetTicks() goes backwards

The attached program (a slightly modified version of Jakob Thomsen’s
WaveGL.c) puts a shell around SDL_GetTicks to check for time going

backwards,

like this:

static int ticks;

int paranoid_set_ticks(void)
{
int newticks = SDL_GetTicks();
if (newticks - ticks < 0) {
printf(“Time went backwards by %i ticks!\n”, ticks - newticks);
return ticks; // try to pretend it didn’t happen
}
return ticks = newticks;
}

This is on Debian Sid, libsdl1.2debian-all, Version: 1.2.4-1. Could

anyone

who’s interested in this problem please try the attached program and see

if

it produces “Time went backwards” messages on the console. It’s kind of

hard

to believe a bug like this could be in the mainline SDL tree without
being noticed, so I suspect it’s a compiler or toolchain issue. Anyway,
I’ll

track

it down in the fullness of time, but some independent confirmation would

be

helpful.

To compile:

gcc time_goes_backwards.c -lSDL -lGL -lGLU && ./a.out


Daniel


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Pardon me, you wrote “int”, I read “unsigned”. Anyway, it’s not the problem,
since sizeof(int) == sizeof(long) on i386.On Tuesday 24 December 2002 01:16, you wrote:

if you notice that time goes backwards aprox. every 32,767 ticks then the
problem is that you are storing ticks (unsigned long int i think) in an
int. The problem you might be having is for instance if you have an
unsigned char set to 255 then add 1 it goes to 0 so it would apear that it
went backwards 255 ticks…maybe youve ruled this out already but hope it
helps!


Daniel

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 moment. It’s possible the
low framerate could explain untested territory, or the software emulation,
but both these seem unlikely.

DanielOn Tuesday 24 December 2002 00:46, Daniel Phillips wrote:

This is on Debian Sid, libsdl1.2debian-all, Version: 1.2.4-1.

More data: I don’t get the reversing time on 2x1 Ghz dual PIII, also in
software emulation, and with a considerably faster screen blit. So far, the
only problem is on my laptop, and there it’s a very obvious problem. Time to
grab the SDL source and a) build it to verify it’s not packaging borkness and
b) put in some test harness and find out what the truth is.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 moment. It’s possible
the low framerate could explain untested territory, or the software
emulation, but both these seem unlikely.


Daniel

time didnt go backwards for me, im in win32 w/ dual 2.1ghz and a ti 4600.
If you need more specs let me know (:> ----- Original Message -----

From: phillips@arcor.de (Daniel Phillips)
To: ; “Daniel Phillips”
Sent: Monday, December 23, 2002 4:56 PM
Subject: Re: [SDL] SDL_GetTicks() goes backwards

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 moment. It’s possible
the
low framerate could explain untested territory, or the software emulation,
but both these seem unlikely.

Daniel


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

This is on Debian Sid, libsdl1.2debian-all, Version: 1.2.4-1. Could anyone
who’s interested in this problem please try the attached program and see if
it produces “Time went backwards” messages on the console. It’s kind of hard
to believe a bug like this could be in the mainline SDL tree without being
noticed, so I suspect it’s a compiler or toolchain issue. Anyway, I’ll track
it down in the fullness of time, but some independent confirmation would be
helpful.

We have similar code in Twilight, the clock itself on your system may be
going backwards every now and then, not a hell of a lot SDL itself can
do about it.

Zephaniah E. Hull.–
1024D/E65A7801 Zephaniah E. Hull <@Zephaniah_E_Hull>
92ED 94E4 B1E6 3624 226D 5727 4453 008B E65A 7801
CCs of replies from mailing lists are requested.

.net is microsofts perverted version of a java networked
environment uglified for windows-specific crap
– nonlinear in #opengl
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20021224/add697b2/attachment.pgp

In other words, it may be a kernel issue? (2.4.19) Well, if it is, at least
we need to assign blame. I should know for sure some time today.

DanielOn Tuesday 24 December 2002 12:43, Zephaniah E. Hull wrote:

We have similar code in Twilight, the clock itself on your system may be
going backwards every now and then, not a hell of a lot SDL itself can
do about it.

In other words, blame ntp.On Tue, Dec 24, 2002 at 04:06:57PM +0100, Daniel Phillips wrote:

We have similar code in Twilight, the clock itself on your system may be
going backwards every now and then, not a hell of a lot SDL itself can
do about it.

In other words, it may be a kernel issue? (2.4.19) Well, if it is, at least
we need to assign blame. I should know for sure some time today.


Joseph Carter <@Joseph_Carter> Goldfish don’t bounce

“We don’t necessarily discriminate. We simply exclude certain types of
people.”
– Colonel Gerald Wellman, ROTC Instructor

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20021224/159cbaa6/attachment.pgp

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.

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —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

And if you have to use NTP…? (I use it. Tired of having 'make’
fail due to clocks out of sync… heh) I think this has to be dealt
with at some level.

What I’m saying is basically: Who says time cannot go backwards? The
application? SDL? gettimeofday()?

If there’s an API that guarantees that time will not go backwards,
it’s implementation(s) should also make sure you can actually trust
the API spec.

The SDL 1.2.5 man files don’t say anything about this, so I’m
wondering whether you should really assume that SDL_GetTicks won’t
move backwards… I think not.

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Tuesday 24 December 2002 16.28, Joseph Carter wrote:

On Tue, Dec 24, 2002 at 04:06:57PM +0100, Daniel Phillips wrote:

We have similar code in Twilight, the clock itself on your
system may be going backwards every now and then, not a hell of
a lot SDL itself can do about it.

In other words, it may be a kernel issue? (2.4.19) Well, if it
is, at least we need to assign blame. I should know for sure
some time today.

In other words, blame ntp.

If there’s an API that guarantees that time will not go backwards,
it’s implementation(s) should also make sure you can actually trust
the API spec.

The SDL 1.2.5 man files don’t say anything about this, so I’m
wondering whether you should really assume that SDL_GetTicks won’t
move backwards… I think not.

From the web site for SDL_GetTicks

“Get the number of milliseconds since the SDL library initialization.”

From that definition I fail to see how it could go backwards !

Both Linux and Windows have counters which are based on how long the
system has been up (maybe in ms), and these should be independant of
anything that NTP may be doing to the system clock. I haven’t looked at
the SDL code to see what they are using, but the function and any of
your code should be using these functions and not anything to do with
the “clock” time.

AndyOn Tue, 2002-12-24 at 08:49, David Olofson wrote:


andy preston <@Andy_Preston>

If there’s an API that guarantees that time will not go
backwards, it’s implementation(s) should also make sure you can
actually trust the API spec.

The SDL 1.2.5 man files don’t say anything about this, so I’m
wondering whether you should really assume that SDL_GetTicks
won’t move backwards… I think not.

From the web site for SDL_GetTicks

“Get the number of milliseconds since the SDL library
initialization.”

From that definition I fail to see how it could go backwards !

Well, yeah. However, ‘man gettimeofday’ says:

“The tv_sec member of the struct is the number of seconds since the
Epoch (see time(2)), and tv_usec is the amount of microseconds
past the current tv_sec value.”

If this way of describing it implies that time cannot go backwards,
then there must be a bug in the way NTP adjusts time.

Both Linux and Windows have counters which are based on how long
the system has been up (maybe in ms), and these should be
independant of anything that NTP may be doing to the system clock.

That’s a good point. IIRC, the Win32 API docs explicitly say that the
multimedia timers are not necessarilly in sync with system time. So,
Win32 shouldn’t have a problem with mmtimers and NTP.

I haven’t looked at the SDL code to see what they are using, but
the function and any of your code should be using these functions
and not anything to do with the “clock” time.

Yeah. SDL_GetTicks for Linux:On Tuesday 24 December 2002 18.21, andy preston wrote:

On Tue, 2002-12-24 at 08:49, David Olofson wrote:


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;

    gettimeofday(&now, NULL);
ticks=(now.tv_sec-start.tv_sec)*1000 +
		(now.tv_usec-start.tv_usec)/1000;
    return(ticks);

#endif /* USE_RDTSC */
}

So, unless RDTSC is used, SDL_GetTicks() can potentially do the wrong
thing when NTP is used. (Or if the user changes the system clock
while your program is running.)

Maybe it should keep the last ‘ticks’ returned, and if the result is
less than that, adjust start.* and return 0?

Would have been nice if SDL could be informed of system clock
adjustments, but that might be overkill, if at all possible.

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se

[…]

From the web site for SDL_GetTicks

“Get the number of milliseconds since the SDL library
initialization.”

From that definition I fail to see how it could go backwards !
[…]

Oh, I forgot my point: Either your interpretation is wrong, or both
gettimeofday() and SDL_GetTicks() are broken. Both return “time in
unit X since reference time T”.

Either way, I think the most sensible fix would be to "fix"
SDL_GetTicks, and explicity state in the docs that it won’t go
backwards; only wrap every ~49 days. That’s how it will work on any
system with properly implemented multimedia timers anyway. (We don’t
have any on Linux - yet.)

(And ‘man gettimeofday’ should probably point out that time may go
backwards. Couldn’t find any hints in that direction…)

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Tuesday 24 December 2002 18.21, andy preston wrote:

But what if your clock has gone too far forward? NTP corrects your time
and suddenly you’re set backwards in time for a few seconds.

Technically then, time has gone backwards…On Tue, 2002-12-24 at 12:30, David Olofson wrote:

Well, yeah. However, ‘man gettimeofday’ says:

“The tv_sec member of the struct is the number of seconds since the
Epoch (see time(2)), and tv_usec is the amount of microseconds
past the current tv_sec value.”

If this way of describing it implies that time cannot go backwards,
then there must be a bug in the way NTP adjusts time.

Yes, that’s my point, basically - which means that there is a problem
with the documentation of gettimeofday().

So, either ‘man SDL_GetTicks’ should have a warning about time
potentially going backwards - or the SDL_GetTicks() implementation
should be fixed, and ‘man SDL_GetTicks’ should make it more clear
that time will not go backwards. IMHO, the latter makes more sense,
as we’re talking about a “multimedia timer” interface, rather than
something like gettimeofday().

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Tuesday 24 December 2002 19.43, Shawn wrote:

On Tue, 2002-12-24 at 12:30, David Olofson wrote:

Well, yeah. However, ‘man gettimeofday’ says:

“The tv_sec member of the struct is the number of seconds since
the Epoch (see time(2)), and tv_usec is the amount of
microseconds past the current tv_sec value.”

If this way of describing it implies that time cannot go
backwards, then there must be a bug in the way NTP adjusts time.

But what if your clock has gone too far forward? NTP corrects your
time and suddenly you’re set backwards in time for a few seconds.

Technically then, time has gone backwards…

I’m not running ntp.

DanielOn Tuesday 24 December 2002 16:28, Joseph Carter wrote:

In other words, blame ntp.

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.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.


Daniel

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.

…but they ARE expensive on many platforms, especially at the granularity
of a “tick”.

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?

You would be surprised about the 486 thing, but don’t forget the PowerPC,
Sparc, ARM, and probably at least 10 other CPUs that SDL is known to run
on.

If you find the bug in glibc, let me know…I’m genuinely curious as to
why that happens (and why rdtsc doesn’t demostrate this problem).

–ryan.