diff src/timer/linux/SDL_systimer.c @ 1157:baf35853ad54

Date: Mon, 10 Oct 2005 13:09:32 +0300 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
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 11 Oct 2005 18:16:12 +0000
parents 8521404a33c7
children ec446adf8cb2
line wrap: on
line diff
--- a/src/timer/linux/SDL_systimer.c	Tue Oct 11 17:33:03 2005 +0000
+++ b/src/timer/linux/SDL_systimer.c	Tue Oct 11 18:16:12 2005 +0000
@@ -34,6 +34,16 @@
 #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"
@@ -86,6 +96,19 @@
 	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;
 
@@ -96,6 +119,7 @@
 	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);
@@ -106,7 +130,11 @@
 #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 */
 
@@ -119,9 +147,11 @@
 		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)
@@ -133,14 +163,19 @@
 	}
 	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
+	Uint32 ticks;
 	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 */
+#endif
 }
 
 void SDL_Delay (Uint32 ms)