Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/system_wrappers/include/tick_util.h"
     12 
     13 #include <assert.h>
     14 
     15 namespace webrtc {
     16 
     17 int64_t TickTime::MillisecondTimestamp() {
     18   return TicksToMilliseconds(TickTime::Now().Ticks());
     19 }
     20 
     21 int64_t TickTime::MicrosecondTimestamp() {
     22   return TicksToMicroseconds(TickTime::Now().Ticks());
     23 }
     24 
     25 int64_t TickTime::MillisecondsToTicks(const int64_t ms) {
     26 #if _WIN32
     27   return ms;
     28 #elif defined(WEBRTC_LINUX)
     29   return ms * 1000000LL;
     30 #elif defined(WEBRTC_MAC)
     31   // TODO(pbos): Fix unsafe use of static locals.
     32   static double timebase_from_millisecond_fract = 0.0;
     33   if (timebase_from_millisecond_fract == 0.0) {
     34     mach_timebase_info_data_t timebase;
     35     (void)mach_timebase_info(&timebase);
     36     timebase_from_millisecond_fract = (timebase.denom * 1e6) / timebase.numer;
     37   }
     38   return ms * timebase_from_millisecond_fract;
     39 #else
     40   return ms * 1000LL;
     41 #endif
     42 }
     43 
     44 int64_t TickTime::TicksToMilliseconds(const int64_t ticks) {
     45 #if _WIN32
     46   return ticks;
     47 #elif defined(WEBRTC_LINUX)
     48   return ticks / 1000000LL;
     49 #elif defined(WEBRTC_MAC)
     50   // TODO(pbos): Fix unsafe use of static locals.
     51   static double timebase_microsecond_fract = 0.0;
     52   if (timebase_microsecond_fract == 0.0) {
     53     mach_timebase_info_data_t timebase;
     54     (void)mach_timebase_info(&timebase);
     55     timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e6);
     56   }
     57   return ticks * timebase_microsecond_fract;
     58 #else
     59   return ticks;
     60 #endif
     61 }
     62 
     63 int64_t TickTime::TicksToMicroseconds(const int64_t ticks) {
     64 #if _WIN32
     65   return ticks * 1000LL;
     66 #elif defined(WEBRTC_LINUX)
     67   return ticks / 1000LL;
     68 #elif defined(WEBRTC_MAC)
     69   // TODO(pbos): Fix unsafe use of static locals.
     70   static double timebase_microsecond_fract = 0.0;
     71   if (timebase_microsecond_fract == 0.0) {
     72     mach_timebase_info_data_t timebase;
     73     (void)mach_timebase_info(&timebase);
     74     timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e3);
     75   }
     76   return ticks * timebase_microsecond_fract;
     77 #else
     78   return ticks;
     79 #endif
     80 }
     81 
     82 // Gets the native system tick count. The actual unit, resolution, and epoch
     83 // varies by platform:
     84 // Windows: Milliseconds of uptime with rollover count in the upper 32-bits.
     85 // Linux/Android: Nanoseconds since the Unix epoch.
     86 // Mach (Mac/iOS): "absolute" time since first call.
     87 // Unknown POSIX: Microseconds since the Unix epoch.
     88 int64_t TickTime::QueryOsForTicks() {
     89 #if _WIN32
     90   static volatile LONG last_time_get_time = 0;
     91   static volatile int64_t num_wrap_time_get_time = 0;
     92   volatile LONG* last_time_get_time_ptr = &last_time_get_time;
     93   DWORD now = timeGetTime();
     94   // Atomically update the last gotten time
     95   DWORD old = InterlockedExchange(last_time_get_time_ptr, now);
     96   if (now < old) {
     97     // If now is earlier than old, there may have been a race between
     98     // threads.
     99     // 0x0fffffff ~3.1 days, the code will not take that long to execute
    100     // so it must have been a wrap around.
    101     if (old > 0xf0000000 && now < 0x0fffffff) {
    102       // TODO(pbos): Fix unsafe use of static locals.
    103       num_wrap_time_get_time++;
    104     }
    105   }
    106   return now + (num_wrap_time_get_time << 32);
    107 #elif defined(WEBRTC_LINUX)
    108   struct timespec ts;
    109   // TODO(wu): Remove CLOCK_REALTIME implementation.
    110 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
    111   clock_gettime(CLOCK_REALTIME, &ts);
    112 #else
    113   clock_gettime(CLOCK_MONOTONIC, &ts);
    114 #endif
    115   return 1000000000LL * ts.tv_sec + ts.tv_nsec;
    116 #elif defined(WEBRTC_MAC)
    117   // Return absolute time as an offset from the first call to this function, so
    118   // that we can do floating-point (double) operations on it without losing
    119   // precision. This holds true until the elapsed time is ~11 days,
    120   // at which point we'll start to lose some precision, though not enough to
    121   // matter for millisecond accuracy for another couple years after that.
    122   // TODO(pbos): Fix unsafe use of static locals.
    123   static uint64_t timebase_start = 0;
    124   if (timebase_start == 0) {
    125     timebase_start = mach_absolute_time();
    126   }
    127   return mach_absolute_time() - timebase_start;
    128 #else
    129   struct timeval tv;
    130   gettimeofday(&tv, NULL);
    131   return 1000000LL * tv.tv_sec + tv.tv_usec;
    132 #endif
    133 }
    134 
    135 }  // namespace webrtc
    136