add in OS X Monotonic clock as well as handling fall-back incase the OSX/Linux system doesn't have a monotonic clock.

Code curtesy of Thomas Habets ( https://github.com/ThomasHabets/monotonic_clock )

--HG--
extra : rebase_source : 767f4fbc2b7bda8d59c7b10a24467043770e94f1
This commit is contained in:
Edward Rudd 2013-05-02 21:17:59 -04:00
parent 98819d0d8d
commit 2c6d6e45d9

View file

@ -34,85 +34,113 @@
for __USE_POSIX199309 for __USE_POSIX199309
Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005 Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
*/ */
/* Reworked monotonic clock to not assume the current system has one
as not all linux kernels provide a monotonic clock (yeah recent ones
probably do)
Also added OS X Monotonic clock support
Based on work in https://github.com/ThomasHabets/monotonic_clock
*/
#if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME #if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME
#include <time.h> #include <time.h>
#endif #endif
#ifdef __APPLE__
#include <mach/mach_time.h>
#endif
/* The first ticks value of the application */ /* The first ticks value of the application */
#ifdef HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
static struct timespec start; static struct timespec start_ts;
#else #elif defined(__APPLE__)
static struct timeval start; static uint64_t start_mach;
#endif /* HAVE_CLOCK_GETTIME */ mach_timebase_info_data_t mach_base_info;
#endif
static SDL_bool has_monotonic_time = SDL_FALSE;
static struct timeval start_tv;
void void
SDL_StartTicks(void) SDL_StartTicks(void)
{ {
/* Set first ticks value */ /* Set first ticks value */
#if HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
clock_gettime(CLOCK_MONOTONIC, &start); if (clock_gettime(CLOCK_MONOTONIC, &start_ts) == 0) {
#else has_monotonic_time = SDL_TRUE;
gettimeofday(&start, NULL); } else
#elif defined(__APPLE__)
start_mach = mach_absolute_time();
kern_return_t ret = mach_timebase_info(&mach_base_info);
if (ret == 0) {
has_monotonic_time = SDL_TRUE;
} else
#endif #endif
{
gettimeofday(&start_tv, NULL);
}
} }
Uint32 Uint32
SDL_GetTicks(void) SDL_GetTicks(void)
{ {
Uint32 ticks;
if (has_monotonic_time) {
#if HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
Uint32 ticks; struct timespec now;
struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now);
ticks =
clock_gettime(CLOCK_MONOTONIC, &now); (now.tv_sec - start_ts.tv_sec) * 1000 + (now.tv_nsec -
ticks = start_ts.tv_nsec) / 1000000;
(now.tv_sec - start.tv_sec) * 1000 + (now.tv_nsec - #elif defined(__APPLE__)
start.tv_nsec) / 1000000; uint64_t now = mach_absolute_time();
return (ticks); ticks = (now - start_mach) * mach_base_info.numer / mach_base_info.denom / 1000000;
#else
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 #endif
} else {
struct timeval now;
gettimeofday(&now, NULL);
ticks =
(now.tv_sec - start_tv.tv_sec) * 1000 + (now.tv_usec -
start_tv.tv_usec) / 1000;
}
return (ticks);
} }
Uint64 Uint64
SDL_GetPerformanceCounter(void) SDL_GetPerformanceCounter(void)
{ {
Uint64 ticks;
if (has_monotonic_time) {
#if HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
Uint64 ticks; struct timespec now;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
ticks = now.tv_sec; ticks = now.tv_sec;
ticks *= 1000000000; ticks *= 1000000000;
ticks += now.tv_nsec; ticks += now.tv_nsec;
return (ticks); #elif defined(__APPLE__)
#else ticks = mach_absolute_time();
Uint64 ticks;
struct timeval now;
gettimeofday(&now, NULL);
ticks = now.tv_sec;
ticks *= 1000000;
ticks += now.tv_usec;
return (ticks);
#endif #endif
} else {
struct timeval now;
gettimeofday(&now, NULL);
ticks = now.tv_sec;
ticks *= 1000000;
ticks += now.tv_usec;
}
return (ticks);
} }
Uint64 Uint64
SDL_GetPerformanceFrequency(void) SDL_GetPerformanceFrequency(void)
{ {
if (has_monotonic_time) {
#if HAVE_CLOCK_GETTIME #if HAVE_CLOCK_GETTIME
return 1000000000; return 1000000000;
#else #elif defined(__APPLE__)
return 1000000; return mach_base_info.denom / mach_base_info.numer * 1000000;
#endif #endif
} else {
return 1000000;
}
} }
void void