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/interface/tick_util.h" 12 13 #include <assert.h> 14 15 namespace webrtc { 16 17 bool TickTime::use_fake_clock_ = false; 18 int64_t TickTime::fake_ticks_ = 0; 19 UseFakeClock(int64_t start_millisecond)20void TickTime::UseFakeClock(int64_t start_millisecond) { 21 use_fake_clock_ = true; 22 fake_ticks_ = MillisecondsToTicks(start_millisecond); 23 } 24 AdvanceFakeClock(int64_t milliseconds)25void TickTime::AdvanceFakeClock(int64_t milliseconds) { 26 assert(use_fake_clock_); 27 fake_ticks_ += MillisecondsToTicks(milliseconds); 28 } 29 QueryOsForTicks()30int64_t TickTime::QueryOsForTicks() { 31 TickTime result; 32 #if _WIN32 33 // TODO(wu): Remove QueryPerformanceCounter implementation. 34 #ifdef USE_QUERY_PERFORMANCE_COUNTER 35 // QueryPerformanceCounter returns the value from the TSC which is 36 // incremented at the CPU frequency. The algorithm used requires 37 // the CPU frequency to be constant. Technology like speed stepping 38 // which has variable CPU frequency will therefore yield unpredictable, 39 // incorrect time estimations. 40 LARGE_INTEGER qpcnt; 41 QueryPerformanceCounter(&qpcnt); 42 result.ticks_ = qpcnt.QuadPart; 43 #else 44 static volatile LONG last_time_get_time = 0; 45 static volatile int64_t num_wrap_time_get_time = 0; 46 volatile LONG* last_time_get_time_ptr = &last_time_get_time; 47 DWORD now = timeGetTime(); 48 // Atomically update the last gotten time 49 DWORD old = InterlockedExchange(last_time_get_time_ptr, now); 50 if (now < old) { 51 // If now is earlier than old, there may have been a race between 52 // threads. 53 // 0x0fffffff ~3.1 days, the code will not take that long to execute 54 // so it must have been a wrap around. 55 if (old > 0xf0000000 && now < 0x0fffffff) { 56 num_wrap_time_get_time++; 57 } 58 } 59 result.ticks_ = now + (num_wrap_time_get_time << 32); 60 #endif 61 #elif defined(WEBRTC_LINUX) 62 struct timespec ts; 63 // TODO(wu): Remove CLOCK_REALTIME implementation. 64 #ifdef WEBRTC_CLOCK_TYPE_REALTIME 65 clock_gettime(CLOCK_REALTIME, &ts); 66 #else 67 clock_gettime(CLOCK_MONOTONIC, &ts); 68 #endif 69 result.ticks_ = 1000000000LL * static_cast<int64_t>(ts.tv_sec) + 70 static_cast<int64_t>(ts.tv_nsec); 71 #elif defined(WEBRTC_MAC) 72 static mach_timebase_info_data_t timebase; 73 if (timebase.denom == 0) { 74 // Get the timebase if this is the first time we run. 75 // Recommended by Apple's QA1398. 76 kern_return_t retval = mach_timebase_info(&timebase); 77 if (retval != KERN_SUCCESS) { 78 // TODO(wu): Implement CHECK similar to chrome for all the platforms. 79 // Then replace this with a CHECK(retval == KERN_SUCCESS); 80 #ifndef WEBRTC_IOS 81 asm("int3"); 82 #else 83 __builtin_trap(); 84 #endif // WEBRTC_IOS 85 } 86 } 87 // Use timebase to convert absolute time tick units into nanoseconds. 88 result.ticks_ = mach_absolute_time() * timebase.numer / timebase.denom; 89 #else 90 struct timeval tv; 91 gettimeofday(&tv, NULL); 92 result.ticks_ = 1000000LL * static_cast<int64_t>(tv.tv_sec) + 93 static_cast<int64_t>(tv.tv_usec); 94 #endif 95 return result.ticks_; 96 } 97 98 } // namespace webrtc 99