add in OS X Monotonic clock as well as handling fall-back incase the OSX/Linux system doesn't have a monotonic clock.
authorEdward Rudd <urkle@outoforder.cc>
Thu, 02 May 2013 21:17:59 -0400
changeset 7137e4daf38f9bde
parent 7136 65c709a5da8a
child 7138 52ba4fa156c7
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 )
src/timer/unix/SDL_systimer.c
     1.1 --- a/src/timer/unix/SDL_systimer.c	Thu May 02 16:54:03 2013 -0700
     1.2 +++ b/src/timer/unix/SDL_systimer.c	Thu May 02 21:17:59 2013 -0400
     1.3 @@ -34,85 +34,113 @@
     1.4     for __USE_POSIX199309
     1.5     Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
     1.6  */
     1.7 +/* Reworked monotonic clock to not assume the current system has one
     1.8 +   as not all linux kernels provide a monotonic clock (yeah recent ones
     1.9 +   probably do)
    1.10 +   Also added OS X Monotonic clock support
    1.11 +   Based on work in https://github.com/ThomasHabets/monotonic_clock
    1.12 + */
    1.13  #if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME
    1.14  #include <time.h>
    1.15  #endif
    1.16 +#ifdef __APPLE__
    1.17 +#include <mach/mach_time.h>
    1.18 +#endif
    1.19  
    1.20  /* The first ticks value of the application */
    1.21 -#ifdef HAVE_CLOCK_GETTIME
    1.22 -static struct timespec start;
    1.23 -#else
    1.24 -static struct timeval start;
    1.25 -#endif /* HAVE_CLOCK_GETTIME */
    1.26 -
    1.27 +#if HAVE_CLOCK_GETTIME
    1.28 +static struct timespec start_ts;
    1.29 +#elif defined(__APPLE__)
    1.30 +static uint64_t start_mach;
    1.31 +mach_timebase_info_data_t mach_base_info;
    1.32 +#endif
    1.33 +static SDL_bool has_monotonic_time = SDL_FALSE;
    1.34 +static struct timeval start_tv;
    1.35  
    1.36  void
    1.37  SDL_StartTicks(void)
    1.38  {
    1.39      /* Set first ticks value */
    1.40  #if HAVE_CLOCK_GETTIME
    1.41 -    clock_gettime(CLOCK_MONOTONIC, &start);
    1.42 -#else
    1.43 -    gettimeofday(&start, NULL);
    1.44 +    if (clock_gettime(CLOCK_MONOTONIC, &start_ts) == 0) {
    1.45 +        has_monotonic_time = SDL_TRUE;
    1.46 +    } else
    1.47 +#elif defined(__APPLE__)
    1.48 +    start_mach = mach_absolute_time();
    1.49 +    kern_return_t ret = mach_timebase_info(&mach_base_info);
    1.50 +    if (ret == 0) {
    1.51 +        has_monotonic_time = SDL_TRUE;
    1.52 +    } else
    1.53  #endif
    1.54 +    {
    1.55 +        gettimeofday(&start_tv, NULL);
    1.56 +    }
    1.57  }
    1.58  
    1.59  Uint32
    1.60  SDL_GetTicks(void)
    1.61  {
    1.62 +    Uint32 ticks;
    1.63 +    if (has_monotonic_time) {
    1.64  #if HAVE_CLOCK_GETTIME
    1.65 -    Uint32 ticks;
    1.66 -    struct timespec now;
    1.67 +        struct timespec now;
    1.68 +        clock_gettime(CLOCK_MONOTONIC, &now);
    1.69 +        ticks = 
    1.70 +            (now.tv_sec - start_ts.tv_sec) * 1000 + (now.tv_nsec -
    1.71 +                                                 start_ts.tv_nsec) / 1000000;
    1.72 +#elif defined(__APPLE__)
    1.73 +        uint64_t now = mach_absolute_time();
    1.74 +        ticks = (now - start_mach) * mach_base_info.numer / mach_base_info.denom / 1000000;
    1.75 +#endif
    1.76 +    } else {
    1.77 +        struct timeval now;
    1.78  
    1.79 -    clock_gettime(CLOCK_MONOTONIC, &now);
    1.80 -    ticks =
    1.81 -        (now.tv_sec - start.tv_sec) * 1000 + (now.tv_nsec -
    1.82 -                                              start.tv_nsec) / 1000000;
    1.83 +        gettimeofday(&now, NULL);
    1.84 +        ticks =
    1.85 +            (now.tv_sec - start_tv.tv_sec) * 1000 + (now.tv_usec -
    1.86 +                                                  start_tv.tv_usec) / 1000;
    1.87 +    }
    1.88      return (ticks);
    1.89 -#else
    1.90 -    Uint32 ticks;
    1.91 -    struct timeval now;
    1.92 -
    1.93 -    gettimeofday(&now, NULL);
    1.94 -    ticks =
    1.95 -        (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec -
    1.96 -                                              start.tv_usec) / 1000;
    1.97 -    return (ticks);
    1.98 -#endif
    1.99  }
   1.100  
   1.101  Uint64
   1.102  SDL_GetPerformanceCounter(void)
   1.103  {
   1.104 +    Uint64 ticks;
   1.105 +    if (has_monotonic_time) {
   1.106  #if HAVE_CLOCK_GETTIME
   1.107 -    Uint64 ticks;
   1.108 -    struct timespec now;
   1.109 +        struct timespec now;
   1.110  
   1.111 -    clock_gettime(CLOCK_MONOTONIC, &now);
   1.112 -    ticks = now.tv_sec;
   1.113 -    ticks *= 1000000000;
   1.114 -    ticks += now.tv_nsec;
   1.115 +        clock_gettime(CLOCK_MONOTONIC, &now);
   1.116 +        ticks = now.tv_sec;
   1.117 +        ticks *= 1000000000;
   1.118 +        ticks += now.tv_nsec;
   1.119 +#elif defined(__APPLE__)
   1.120 +        ticks = mach_absolute_time();
   1.121 +#endif
   1.122 +    } else {
   1.123 +        struct timeval now;
   1.124 +
   1.125 +        gettimeofday(&now, NULL);
   1.126 +        ticks = now.tv_sec;
   1.127 +        ticks *= 1000000;
   1.128 +        ticks += now.tv_usec;
   1.129 +    }
   1.130      return (ticks);
   1.131 -#else
   1.132 -    Uint64 ticks;
   1.133 -    struct timeval now;
   1.134 -
   1.135 -    gettimeofday(&now, NULL);
   1.136 -    ticks = now.tv_sec;
   1.137 -    ticks *= 1000000;
   1.138 -    ticks += now.tv_usec;
   1.139 -    return (ticks);
   1.140 -#endif
   1.141  }
   1.142  
   1.143  Uint64
   1.144  SDL_GetPerformanceFrequency(void)
   1.145  {
   1.146 +    if (has_monotonic_time) {
   1.147  #if HAVE_CLOCK_GETTIME
   1.148 -    return 1000000000;
   1.149 -#else
   1.150 -    return 1000000;
   1.151 +        return 1000000000;
   1.152 +#elif defined(__APPLE__)
   1.153 +        return mach_base_info.denom / mach_base_info.numer * 1000000;
   1.154  #endif
   1.155 +    } else {
   1.156 +        return 1000000;
   1.157 +    }
   1.158  }
   1.159  
   1.160  void