Skip to content

Commit

Permalink
Date: Mon, 10 Oct 2005 13:09:32 +0300
Browse files Browse the repository at this point in the history
From: Tommi Kyntola <tommi.kyntola@ray.fi>
To: sdl@libsdl.org
Subject: [SDL] [RFC] get_ticks broken on linux

It uses gettimeofday to calculate the timedifference.
Gettimeofday returns current time which is seldom monotonous.
This breaks SDL timer subsystem. (time callbacks and all that
get borked when the time difference ms is suddenly ~ 2^32)

I posted a message about this earlier but got no response.
Some thoughts on this matter would be appreciated.
(Or even an explanation for the lack of interest.)

A patch below would use the posix timers that have been around
since posix 93 and do provide a good source of monotonous time
on linux boxes (and on few others too).

The following patch is also availabe at:
http://www.hut.fi/u/tkyntola/SDL-1.2.9-clockfix.patch

It's against 1.2.9, but I can easily rediffit against
the cvs branch is needed.

cheers,
Tommi Kyntola            tommi.kyntola@ray.fi
  • Loading branch information
icculus committed Oct 11, 2005
1 parent 6f40c85 commit d11baf2
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions src/timer/linux/SDL_systimer.c
Expand Up @@ -34,6 +34,16 @@ static char rcsid =
#include <string.h>
#include <errno.h>

/* The clock_gettime provides monotonous time, so we should use it if
it's available. The clock_gettime function is behind ifdef
for __USE_POSIX199309
Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
*/
#if (defined _POSIX_TIMERS && _POSIX_TIMERS > 0)
#include <time.h>
#define USE_CLOCK_GETTIME
#endif

#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_timer_c.h"
Expand Down Expand Up @@ -86,6 +96,19 @@ static float calc_cpu_mhz(void)
float cpu_mhz;
unsigned long long tsc_start;
unsigned long long tsc_end;
/* Slight code doubling here for the sake of readability */
#ifdef USE_CLOCK_GETTIME
struct timespec tv_start, tv_end;
long usec_delay;

rdtsc(tsc_start);
clock_gettime(CLOCK_MONOTONIC,&tv_start);
sleep(1);
rdtsc(tsc_end);
clock_gettime(CLOCK_MONOTONIC,&tv_end);
usec_delay = (1000000000L * (tv_end.tv_sec - tv_start.tv_sec) +
(tv_end.tv_nsec - tv_start.tv_nsec)) / 1000;
#else
struct timeval tv_start, tv_end;
long usec_delay;

Expand All @@ -96,6 +119,7 @@ static float calc_cpu_mhz(void)
gettimeofday(&tv_end, NULL);
usec_delay = 1000000L * (tv_end.tv_sec - tv_start.tv_sec) +
(tv_end.tv_usec - tv_start.tv_usec);
#endif /* USE_CLOCK_GETTIME */
cpu_mhz = (float)(tsc_end-tsc_start) / usec_delay;
#if 0
printf("cpu MHz\t\t: %.3f\n", cpu_mhz);
Expand All @@ -106,7 +130,11 @@ static float calc_cpu_mhz(void)
#else

/* The first ticks value of the application */
#ifdef USE_CLOCK_GETTIME
static struct timespec start;
#else
static struct timeval start;
#endif /* USE_CLOCK_GETTIME */

#endif /* USE_RDTSC */

Expand All @@ -119,9 +147,11 @@ void SDL_StartTicks(void)
cpu_mhz1000 = calc_cpu_mhz() * 1000.0f;
}
rdtsc(start);
#elif defined(USE_CLOCK_GETTIME)
clock_gettime(CLOCK_MONOTONIC,&start);
#else
gettimeofday(&start, NULL);
#endif /* USE_RDTSC */
#endif
}

Uint32 SDL_GetTicks (void)
Expand All @@ -133,14 +163,19 @@ Uint32 SDL_GetTicks (void)
}
rdtsc(now);
return (Uint32)((now-start)/cpu_mhz1000);
#elif defined(USE_CLOCK_GETTIME)
Uint32 ticks;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC,&now);
ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_nsec-start.tv_nsec)/1000000;
return(ticks);
#else
struct timeval now;
Uint32 ticks;

struct timeval now;
gettimeofday(&now, NULL);
ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
return(ticks);
#endif /* USE_RDTSC */
#endif
}

void SDL_Delay (Uint32 ms)
Expand Down

0 comments on commit d11baf2

Please sign in to comment.