tick_util.cc revision 1d4a2d5daf8a01321b51f77a594f98f5edde0044
14cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org/* 24cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 34cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * 44cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * Use of this source code is governed by a BSD-style license 54cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * that can be found in the LICENSE file in the root of the source 64cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * tree. An additional intellectual property rights grant can be found 74cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * in the file PATENTS. All contributing project authors may 84cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org * be found in the AUTHORS file in the root of the source tree. 94cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org */ 104cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 115c8d9d30e25a4cf3433c1e29a7d7076e1f87e46dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h" 124cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 134cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org#include <cassert> 144cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 154cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.orgnamespace webrtc { 164cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 175c8d9d30e25a4cf3433c1e29a7d7076e1f87e46dphoglund@webrtc.orgbool TickTime::use_fake_clock_ = false; 18046deb9b2050ebdf98a41e2d22f852e104dd365apbos@webrtc.orgint64_t TickTime::fake_ticks_ = 0; 194cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 20046deb9b2050ebdf98a41e2d22f852e104dd365apbos@webrtc.orgvoid TickTime::UseFakeClock(int64_t start_millisecond) { 215c8d9d30e25a4cf3433c1e29a7d7076e1f87e46dphoglund@webrtc.org use_fake_clock_ = true; 225c8d9d30e25a4cf3433c1e29a7d7076e1f87e46dphoglund@webrtc.org fake_ticks_ = MillisecondsToTicks(start_millisecond); 234cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org} 244cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 25046deb9b2050ebdf98a41e2d22f852e104dd365apbos@webrtc.orgvoid TickTime::AdvanceFakeClock(int64_t milliseconds) { 265c8d9d30e25a4cf3433c1e29a7d7076e1f87e46dphoglund@webrtc.org assert(use_fake_clock_); 275c8d9d30e25a4cf3433c1e29a7d7076e1f87e46dphoglund@webrtc.org fake_ticks_ += MillisecondsToTicks(milliseconds); 284cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org} 294cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 301d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.orgint64_t TickTime::QueryOsForTicks() { 311d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org TickTime result; 321d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#if _WIN32 331d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // TODO(wu): Remove QueryPerformanceCounter implementation. 341d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#ifdef USE_QUERY_PERFORMANCE_COUNTER 351d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // QueryPerformanceCounter returns the value from the TSC which is 361d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // incremented at the CPU frequency. The algorithm used requires 371d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // the CPU frequency to be constant. Technology like speed stepping 381d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // which has variable CPU frequency will therefore yield unpredictable, 391d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // incorrect time estimations. 401d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org LARGE_INTEGER qpcnt; 411d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org QueryPerformanceCounter(&qpcnt); 421d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org result.ticks_ = qpcnt.QuadPart; 431d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#else 441d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static volatile LONG last_time_get_time = 0; 451d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static volatile int64_t num_wrap_time_get_time = 0; 461d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org volatile LONG* last_time_get_time_ptr = &last_time_get_time; 471d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org DWORD now = timeGetTime(); 481d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // Atomically update the last gotten time 491d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org DWORD old = InterlockedExchange(last_time_get_time_ptr, now); 501d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org if (now < old) { 511d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // If now is earlier than old, there may have been a race between 521d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // threads. 531d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // 0x0fffffff ~3.1 days, the code will not take that long to execute 541d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // so it must have been a wrap around. 551d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org if (old > 0xf0000000 && now < 0x0fffffff) { 561d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org num_wrap_time_get_time++; 571d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 581d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 591d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org result.ticks_ = now + (num_wrap_time_get_time << 32); 601d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#endif 611d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#elif defined(WEBRTC_LINUX) 621d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org struct timespec ts; 631d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // TODO(wu): Remove CLOCK_REALTIME implementation. 641d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#ifdef WEBRTC_CLOCK_TYPE_REALTIME 651d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org clock_gettime(CLOCK_REALTIME, &ts); 661d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#else 671d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org clock_gettime(CLOCK_MONOTONIC, &ts); 681d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#endif 691d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org result.ticks_ = 1000000000LL * static_cast<int64_t>(ts.tv_sec) + 701d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static_cast<int64_t>(ts.tv_nsec); 711d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#elif defined(WEBRTC_MAC) 721d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static mach_timebase_info_data_t timebase; 731d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org if (timebase.denom == 0) { 741d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // Get the timebase if this is the first time we run. 751d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // Recommended by Apple's QA1398. 761d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org kern_return_t retval = mach_timebase_info(&timebase); 771d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org if (retval != KERN_SUCCESS) { 781d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // TODO(wu): Implement CHECK similar to chrome for all the platforms. 791d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // Then replace this with a CHECK(retval == KERN_SUCCESS); 801d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#ifndef WEBRTC_IOS 811d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org asm("int3"); 821d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#else 831d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org __builtin_trap(); 841d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#endif // WEBRTC_IOS 851d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 861d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 871d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // Use timebase to convert absolute time tick units into nanoseconds. 881d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org result.ticks_ = mach_absolute_time() * timebase.numer / timebase.denom; 891d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#else 901d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org struct timeval tv; 911d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org gettimeofday(&tv, NULL); 921d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org result.ticks_ = 1000000LL * static_cast<int64_t>(tv.tv_sec) + 931d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static_cast<int64_t>(tv.tv_usec); 941d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#endif 951d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org return result.ticks_; 961d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org} 971d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org 984cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org} // namespace webrtc 99