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