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