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 1198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/tick_util.h" 124cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <assert.h> 144cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 154cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.orgnamespace webrtc { 164cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org 172935e0141939adc642d73da6d8048a4e918a8382thalounint64_t TickTime::MillisecondTimestamp() { 182935e0141939adc642d73da6d8048a4e918a8382thaloun return TicksToMilliseconds(TickTime::Now().Ticks()); 192935e0141939adc642d73da6d8048a4e918a8382thaloun} 202935e0141939adc642d73da6d8048a4e918a8382thaloun 212935e0141939adc642d73da6d8048a4e918a8382thalounint64_t TickTime::MicrosecondTimestamp() { 222935e0141939adc642d73da6d8048a4e918a8382thaloun return TicksToMicroseconds(TickTime::Now().Ticks()); 232935e0141939adc642d73da6d8048a4e918a8382thaloun} 242935e0141939adc642d73da6d8048a4e918a8382thaloun 252935e0141939adc642d73da6d8048a4e918a8382thalounint64_t TickTime::MillisecondsToTicks(const int64_t ms) { 262935e0141939adc642d73da6d8048a4e918a8382thaloun#if _WIN32 272935e0141939adc642d73da6d8048a4e918a8382thaloun return ms; 282935e0141939adc642d73da6d8048a4e918a8382thaloun#elif defined(WEBRTC_LINUX) 292935e0141939adc642d73da6d8048a4e918a8382thaloun return ms * 1000000LL; 302935e0141939adc642d73da6d8048a4e918a8382thaloun#elif defined(WEBRTC_MAC) 312935e0141939adc642d73da6d8048a4e918a8382thaloun // TODO(pbos): Fix unsafe use of static locals. 322935e0141939adc642d73da6d8048a4e918a8382thaloun static double timebase_from_millisecond_fract = 0.0; 332935e0141939adc642d73da6d8048a4e918a8382thaloun if (timebase_from_millisecond_fract == 0.0) { 342935e0141939adc642d73da6d8048a4e918a8382thaloun mach_timebase_info_data_t timebase; 352935e0141939adc642d73da6d8048a4e918a8382thaloun (void)mach_timebase_info(&timebase); 362935e0141939adc642d73da6d8048a4e918a8382thaloun timebase_from_millisecond_fract = (timebase.denom * 1e6) / timebase.numer; 372935e0141939adc642d73da6d8048a4e918a8382thaloun } 382935e0141939adc642d73da6d8048a4e918a8382thaloun return ms * timebase_from_millisecond_fract; 392935e0141939adc642d73da6d8048a4e918a8382thaloun#else 402935e0141939adc642d73da6d8048a4e918a8382thaloun return ms * 1000LL; 412935e0141939adc642d73da6d8048a4e918a8382thaloun#endif 422935e0141939adc642d73da6d8048a4e918a8382thaloun} 432935e0141939adc642d73da6d8048a4e918a8382thaloun 442935e0141939adc642d73da6d8048a4e918a8382thalounint64_t TickTime::TicksToMilliseconds(const int64_t ticks) { 452935e0141939adc642d73da6d8048a4e918a8382thaloun#if _WIN32 462935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks; 472935e0141939adc642d73da6d8048a4e918a8382thaloun#elif defined(WEBRTC_LINUX) 482935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks / 1000000LL; 492935e0141939adc642d73da6d8048a4e918a8382thaloun#elif defined(WEBRTC_MAC) 502935e0141939adc642d73da6d8048a4e918a8382thaloun // TODO(pbos): Fix unsafe use of static locals. 512935e0141939adc642d73da6d8048a4e918a8382thaloun static double timebase_microsecond_fract = 0.0; 522935e0141939adc642d73da6d8048a4e918a8382thaloun if (timebase_microsecond_fract == 0.0) { 532935e0141939adc642d73da6d8048a4e918a8382thaloun mach_timebase_info_data_t timebase; 542935e0141939adc642d73da6d8048a4e918a8382thaloun (void)mach_timebase_info(&timebase); 552935e0141939adc642d73da6d8048a4e918a8382thaloun timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e6); 562935e0141939adc642d73da6d8048a4e918a8382thaloun } 572935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks * timebase_microsecond_fract; 582935e0141939adc642d73da6d8048a4e918a8382thaloun#else 592935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks; 602935e0141939adc642d73da6d8048a4e918a8382thaloun#endif 612935e0141939adc642d73da6d8048a4e918a8382thaloun} 622935e0141939adc642d73da6d8048a4e918a8382thaloun 632935e0141939adc642d73da6d8048a4e918a8382thalounint64_t TickTime::TicksToMicroseconds(const int64_t ticks) { 642935e0141939adc642d73da6d8048a4e918a8382thaloun#if _WIN32 652935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks * 1000LL; 662935e0141939adc642d73da6d8048a4e918a8382thaloun#elif defined(WEBRTC_LINUX) 672935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks / 1000LL; 682935e0141939adc642d73da6d8048a4e918a8382thaloun#elif defined(WEBRTC_MAC) 692935e0141939adc642d73da6d8048a4e918a8382thaloun // TODO(pbos): Fix unsafe use of static locals. 702935e0141939adc642d73da6d8048a4e918a8382thaloun static double timebase_microsecond_fract = 0.0; 712935e0141939adc642d73da6d8048a4e918a8382thaloun if (timebase_microsecond_fract == 0.0) { 722935e0141939adc642d73da6d8048a4e918a8382thaloun mach_timebase_info_data_t timebase; 732935e0141939adc642d73da6d8048a4e918a8382thaloun (void)mach_timebase_info(&timebase); 742935e0141939adc642d73da6d8048a4e918a8382thaloun timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e3); 752935e0141939adc642d73da6d8048a4e918a8382thaloun } 762935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks * timebase_microsecond_fract; 772935e0141939adc642d73da6d8048a4e918a8382thaloun#else 782935e0141939adc642d73da6d8048a4e918a8382thaloun return ticks; 792935e0141939adc642d73da6d8048a4e918a8382thaloun#endif 802935e0141939adc642d73da6d8048a4e918a8382thaloun} 812935e0141939adc642d73da6d8048a4e918a8382thaloun 822935e0141939adc642d73da6d8048a4e918a8382thaloun// Gets the native system tick count. The actual unit, resolution, and epoch 832935e0141939adc642d73da6d8048a4e918a8382thaloun// varies by platform: 842935e0141939adc642d73da6d8048a4e918a8382thaloun// Windows: Milliseconds of uptime with rollover count in the upper 32-bits. 852935e0141939adc642d73da6d8048a4e918a8382thaloun// Linux/Android: Nanoseconds since the Unix epoch. 862935e0141939adc642d73da6d8048a4e918a8382thaloun// Mach (Mac/iOS): "absolute" time since first call. 872935e0141939adc642d73da6d8048a4e918a8382thaloun// Unknown POSIX: Microseconds since the Unix epoch. 881d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.orgint64_t TickTime::QueryOsForTicks() { 891d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#if _WIN32 901d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static volatile LONG last_time_get_time = 0; 911d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org static volatile int64_t num_wrap_time_get_time = 0; 921d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org volatile LONG* last_time_get_time_ptr = &last_time_get_time; 931d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org DWORD now = timeGetTime(); 941d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // Atomically update the last gotten time 951d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org DWORD old = InterlockedExchange(last_time_get_time_ptr, now); 961d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org if (now < old) { 971d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // If now is earlier than old, there may have been a race between 981d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // threads. 991d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // 0x0fffffff ~3.1 days, the code will not take that long to execute 1001d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // so it must have been a wrap around. 1011d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org if (old > 0xf0000000 && now < 0x0fffffff) { 1022935e0141939adc642d73da6d8048a4e918a8382thaloun // TODO(pbos): Fix unsafe use of static locals. 1031d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org num_wrap_time_get_time++; 1041d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 1051d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 1062935e0141939adc642d73da6d8048a4e918a8382thaloun return now + (num_wrap_time_get_time << 32); 1071d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#elif defined(WEBRTC_LINUX) 1081d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org struct timespec ts; 1091d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org // TODO(wu): Remove CLOCK_REALTIME implementation. 1101d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#ifdef WEBRTC_CLOCK_TYPE_REALTIME 1111d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org clock_gettime(CLOCK_REALTIME, &ts); 1121d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#else 1131d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org clock_gettime(CLOCK_MONOTONIC, &ts); 1141d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#endif 1152935e0141939adc642d73da6d8048a4e918a8382thaloun return 1000000000LL * ts.tv_sec + ts.tv_nsec; 1161d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#elif defined(WEBRTC_MAC) 1172935e0141939adc642d73da6d8048a4e918a8382thaloun // Return absolute time as an offset from the first call to this function, so 1182935e0141939adc642d73da6d8048a4e918a8382thaloun // that we can do floating-point (double) operations on it without losing 1192935e0141939adc642d73da6d8048a4e918a8382thaloun // precision. This holds true until the elapsed time is ~11 days, 1202935e0141939adc642d73da6d8048a4e918a8382thaloun // at which point we'll start to lose some precision, though not enough to 1212935e0141939adc642d73da6d8048a4e918a8382thaloun // matter for millisecond accuracy for another couple years after that. 1222935e0141939adc642d73da6d8048a4e918a8382thaloun // TODO(pbos): Fix unsafe use of static locals. 1232935e0141939adc642d73da6d8048a4e918a8382thaloun static uint64_t timebase_start = 0; 1242935e0141939adc642d73da6d8048a4e918a8382thaloun if (timebase_start == 0) { 1252935e0141939adc642d73da6d8048a4e918a8382thaloun timebase_start = mach_absolute_time(); 1261d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org } 1272935e0141939adc642d73da6d8048a4e918a8382thaloun return mach_absolute_time() - timebase_start; 1281d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#else 1291d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org struct timeval tv; 1301d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org gettimeofday(&tv, NULL); 1312935e0141939adc642d73da6d8048a4e918a8382thaloun return 1000000LL * tv.tv_sec + tv.tv_usec; 1321d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org#endif 1331d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org} 1341d4a2d5daf8a01321b51f77a594f98f5edde0044fischman@webrtc.org 1354cebe6cded9e3c8a1177f69cb71f48f993df3e5aphoglund@webrtc.org} // namespace webrtc 136