blob: c02b5314a4f3b0e634b14e95b66d6c7b0f71b738 [file] [log] [blame]
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +00001/*
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
Henrik Kjellander98f53512015-10-28 18:17:40 +010011#include "webrtc/system_wrappers/include/tick_util.h"
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +000014
15namespace webrtc {
16
thaloun2935e012015-11-17 15:02:44 -080017int64_t TickTime::MillisecondTimestamp() {
18 return TicksToMilliseconds(TickTime::Now().Ticks());
19}
20
21int64_t TickTime::MicrosecondTimestamp() {
22 return TicksToMicroseconds(TickTime::Now().Ticks());
23}
24
25int64_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
44int64_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
63int64_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
thaloun2935e012015-11-17 15:02:44 -080082// 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.
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +000088int64_t TickTime::QueryOsForTicks() {
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +000089#if _WIN32
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +000090 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) {
thaloun2935e012015-11-17 15:02:44 -0800102 // TODO(pbos): Fix unsafe use of static locals.
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000103 num_wrap_time_get_time++;
104 }
105 }
thaloun2935e012015-11-17 15:02:44 -0800106 return now + (num_wrap_time_get_time << 32);
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000107#elif defined(WEBRTC_LINUX)
108 struct timespec ts;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000109 clock_gettime(CLOCK_MONOTONIC, &ts);
thaloun2935e012015-11-17 15:02:44 -0800110 return 1000000000LL * ts.tv_sec + ts.tv_nsec;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000111#elif defined(WEBRTC_MAC)
thaloun2935e012015-11-17 15:02:44 -0800112 // Return absolute time as an offset from the first call to this function, so
113 // that we can do floating-point (double) operations on it without losing
114 // precision. This holds true until the elapsed time is ~11 days,
115 // at which point we'll start to lose some precision, though not enough to
116 // matter for millisecond accuracy for another couple years after that.
117 // TODO(pbos): Fix unsafe use of static locals.
118 static uint64_t timebase_start = 0;
119 if (timebase_start == 0) {
120 timebase_start = mach_absolute_time();
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000121 }
thaloun2935e012015-11-17 15:02:44 -0800122 return mach_absolute_time() - timebase_start;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000123#else
124 struct timeval tv;
125 gettimeofday(&tv, NULL);
thaloun2935e012015-11-17 15:02:44 -0800126 return 1000000LL * tv.tv_sec + tv.tv_usec;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000127#endif
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000128}
129
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +0000130} // namespace webrtc