comparison 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
comparison
equal deleted inserted replaced
1156:8521404a33c7 1157:baf35853ad54
32 #include <signal.h> 32 #include <signal.h>
33 #include <unistd.h> 33 #include <unistd.h>
34 #include <string.h> 34 #include <string.h>
35 #include <errno.h> 35 #include <errno.h>
36 36
37 /* The clock_gettime provides monotonous time, so we should use it if
38 it's available. The clock_gettime function is behind ifdef
39 for __USE_POSIX199309
40 Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
41 */
42 #if (defined _POSIX_TIMERS && _POSIX_TIMERS > 0)
43 #include <time.h>
44 #define USE_CLOCK_GETTIME
45 #endif
46
37 #include "SDL_error.h" 47 #include "SDL_error.h"
38 #include "SDL_timer.h" 48 #include "SDL_timer.h"
39 #include "SDL_timer_c.h" 49 #include "SDL_timer_c.h"
40 50
41 #if _POSIX_THREAD_SYSCALL_SOFT 51 #if _POSIX_THREAD_SYSCALL_SOFT
84 static float calc_cpu_mhz(void) 94 static float calc_cpu_mhz(void)
85 { 95 {
86 float cpu_mhz; 96 float cpu_mhz;
87 unsigned long long tsc_start; 97 unsigned long long tsc_start;
88 unsigned long long tsc_end; 98 unsigned long long tsc_end;
99 /* Slight code doubling here for the sake of readability */
100 #ifdef USE_CLOCK_GETTIME
101 struct timespec tv_start, tv_end;
102 long usec_delay;
103
104 rdtsc(tsc_start);
105 clock_gettime(CLOCK_MONOTONIC,&tv_start);
106 sleep(1);
107 rdtsc(tsc_end);
108 clock_gettime(CLOCK_MONOTONIC,&tv_end);
109 usec_delay = (1000000000L * (tv_end.tv_sec - tv_start.tv_sec) +
110 (tv_end.tv_nsec - tv_start.tv_nsec)) / 1000;
111 #else
89 struct timeval tv_start, tv_end; 112 struct timeval tv_start, tv_end;
90 long usec_delay; 113 long usec_delay;
91 114
92 rdtsc(tsc_start); 115 rdtsc(tsc_start);
93 gettimeofday(&tv_start, NULL); 116 gettimeofday(&tv_start, NULL);
94 sleep(1); 117 sleep(1);
95 rdtsc(tsc_end); 118 rdtsc(tsc_end);
96 gettimeofday(&tv_end, NULL); 119 gettimeofday(&tv_end, NULL);
97 usec_delay = 1000000L * (tv_end.tv_sec - tv_start.tv_sec) + 120 usec_delay = 1000000L * (tv_end.tv_sec - tv_start.tv_sec) +
98 (tv_end.tv_usec - tv_start.tv_usec); 121 (tv_end.tv_usec - tv_start.tv_usec);
122 #endif /* USE_CLOCK_GETTIME */
99 cpu_mhz = (float)(tsc_end-tsc_start) / usec_delay; 123 cpu_mhz = (float)(tsc_end-tsc_start) / usec_delay;
100 #if 0 124 #if 0
101 printf("cpu MHz\t\t: %.3f\n", cpu_mhz); 125 printf("cpu MHz\t\t: %.3f\n", cpu_mhz);
102 #endif 126 #endif
103 return cpu_mhz; 127 return cpu_mhz;
104 } 128 }
105 129
106 #else 130 #else
107 131
108 /* The first ticks value of the application */ 132 /* The first ticks value of the application */
133 #ifdef USE_CLOCK_GETTIME
134 static struct timespec start;
135 #else
109 static struct timeval start; 136 static struct timeval start;
137 #endif /* USE_CLOCK_GETTIME */
110 138
111 #endif /* USE_RDTSC */ 139 #endif /* USE_RDTSC */
112 140
113 141
114 void SDL_StartTicks(void) 142 void SDL_StartTicks(void)
117 #ifdef USE_RDTSC 145 #ifdef USE_RDTSC
118 if ( ! cpu_mhz1000 ) { 146 if ( ! cpu_mhz1000 ) {
119 cpu_mhz1000 = calc_cpu_mhz() * 1000.0f; 147 cpu_mhz1000 = calc_cpu_mhz() * 1000.0f;
120 } 148 }
121 rdtsc(start); 149 rdtsc(start);
150 #elif defined(USE_CLOCK_GETTIME)
151 clock_gettime(CLOCK_MONOTONIC,&start);
122 #else 152 #else
123 gettimeofday(&start, NULL); 153 gettimeofday(&start, NULL);
124 #endif /* USE_RDTSC */ 154 #endif
125 } 155 }
126 156
127 Uint32 SDL_GetTicks (void) 157 Uint32 SDL_GetTicks (void)
128 { 158 {
129 #ifdef USE_RDTSC 159 #ifdef USE_RDTSC
131 if ( ! cpu_mhz1000 ) { 161 if ( ! cpu_mhz1000 ) {
132 return 0; /* Shouldn't happen. BUG!! */ 162 return 0; /* Shouldn't happen. BUG!! */
133 } 163 }
134 rdtsc(now); 164 rdtsc(now);
135 return (Uint32)((now-start)/cpu_mhz1000); 165 return (Uint32)((now-start)/cpu_mhz1000);
136 #else 166 #elif defined(USE_CLOCK_GETTIME)
167 Uint32 ticks;
168 struct timespec now;
169 clock_gettime(CLOCK_MONOTONIC,&now);
170 ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_nsec-start.tv_nsec)/1000000;
171 return(ticks);
172 #else
173 Uint32 ticks;
137 struct timeval now; 174 struct timeval now;
138 Uint32 ticks;
139
140 gettimeofday(&now, NULL); 175 gettimeofday(&now, NULL);
141 ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000; 176 ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
142 return(ticks); 177 return(ticks);
143 #endif /* USE_RDTSC */ 178 #endif
144 } 179 }
145 180
146 void SDL_Delay (Uint32 ms) 181 void SDL_Delay (Uint32 ms)
147 { 182 {
148 #ifdef ENABLE_PTH 183 #ifdef ENABLE_PTH