blob: cae817dc55b199c22d35afe8a013d9cc98e631db [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
phoglund@webrtc.org5c8d9d32013-01-03 09:50:17 +000017bool TickTime::use_fake_clock_ = false;
pbos@webrtc.org046deb92013-04-09 09:06:11 +000018int64_t TickTime::fake_ticks_ = 0;
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +000019
thaloun2935e012015-11-17 15:02:44 -080020int64_t TickTime::MillisecondTimestamp() {
21 return TicksToMilliseconds(TickTime::Now().Ticks());
22}
23
24int64_t TickTime::MicrosecondTimestamp() {
25 return TicksToMicroseconds(TickTime::Now().Ticks());
26}
27
28int64_t TickTime::MillisecondsToTicks(const int64_t ms) {
29#if _WIN32
30 return ms;
31#elif defined(WEBRTC_LINUX)
32 return ms * 1000000LL;
33#elif defined(WEBRTC_MAC)
34 // TODO(pbos): Fix unsafe use of static locals.
35 static double timebase_from_millisecond_fract = 0.0;
36 if (timebase_from_millisecond_fract == 0.0) {
37 mach_timebase_info_data_t timebase;
38 (void)mach_timebase_info(&timebase);
39 timebase_from_millisecond_fract = (timebase.denom * 1e6) / timebase.numer;
40 }
41 return ms * timebase_from_millisecond_fract;
42#else
43 return ms * 1000LL;
44#endif
45}
46
47int64_t TickTime::TicksToMilliseconds(const int64_t ticks) {
48#if _WIN32
49 return ticks;
50#elif defined(WEBRTC_LINUX)
51 return ticks / 1000000LL;
52#elif defined(WEBRTC_MAC)
53 // TODO(pbos): Fix unsafe use of static locals.
54 static double timebase_microsecond_fract = 0.0;
55 if (timebase_microsecond_fract == 0.0) {
56 mach_timebase_info_data_t timebase;
57 (void)mach_timebase_info(&timebase);
58 timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e6);
59 }
60 return ticks * timebase_microsecond_fract;
61#else
62 return ticks;
63#endif
64}
65
66int64_t TickTime::TicksToMicroseconds(const int64_t ticks) {
67#if _WIN32
68 return ticks * 1000LL;
69#elif defined(WEBRTC_LINUX)
70 return ticks / 1000LL;
71#elif defined(WEBRTC_MAC)
72 // TODO(pbos): Fix unsafe use of static locals.
73 static double timebase_microsecond_fract = 0.0;
74 if (timebase_microsecond_fract == 0.0) {
75 mach_timebase_info_data_t timebase;
76 (void)mach_timebase_info(&timebase);
77 timebase_microsecond_fract = timebase.numer / (timebase.denom * 1e3);
78 }
79 return ticks * timebase_microsecond_fract;
80#else
81 return ticks;
82#endif
83}
84
pbos@webrtc.org046deb92013-04-09 09:06:11 +000085void TickTime::UseFakeClock(int64_t start_millisecond) {
phoglund@webrtc.org5c8d9d32013-01-03 09:50:17 +000086 use_fake_clock_ = true;
87 fake_ticks_ = MillisecondsToTicks(start_millisecond);
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +000088}
89
pbos@webrtc.org046deb92013-04-09 09:06:11 +000090void TickTime::AdvanceFakeClock(int64_t milliseconds) {
phoglund@webrtc.org5c8d9d32013-01-03 09:50:17 +000091 assert(use_fake_clock_);
92 fake_ticks_ += MillisecondsToTicks(milliseconds);
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +000093}
94
thaloun2935e012015-11-17 15:02:44 -080095// Gets the native system tick count. The actual unit, resolution, and epoch
96// varies by platform:
97// Windows: Milliseconds of uptime with rollover count in the upper 32-bits.
98// Linux/Android: Nanoseconds since the Unix epoch.
99// Mach (Mac/iOS): "absolute" time since first call.
100// Unknown POSIX: Microseconds since the Unix epoch.
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000101int64_t TickTime::QueryOsForTicks() {
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000102#if _WIN32
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000103 static volatile LONG last_time_get_time = 0;
104 static volatile int64_t num_wrap_time_get_time = 0;
105 volatile LONG* last_time_get_time_ptr = &last_time_get_time;
106 DWORD now = timeGetTime();
107 // Atomically update the last gotten time
108 DWORD old = InterlockedExchange(last_time_get_time_ptr, now);
109 if (now < old) {
110 // If now is earlier than old, there may have been a race between
111 // threads.
112 // 0x0fffffff ~3.1 days, the code will not take that long to execute
113 // so it must have been a wrap around.
114 if (old > 0xf0000000 && now < 0x0fffffff) {
thaloun2935e012015-11-17 15:02:44 -0800115 // TODO(pbos): Fix unsafe use of static locals.
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000116 num_wrap_time_get_time++;
117 }
118 }
thaloun2935e012015-11-17 15:02:44 -0800119 return now + (num_wrap_time_get_time << 32);
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000120#elif defined(WEBRTC_LINUX)
121 struct timespec ts;
122 // TODO(wu): Remove CLOCK_REALTIME implementation.
123#ifdef WEBRTC_CLOCK_TYPE_REALTIME
124 clock_gettime(CLOCK_REALTIME, &ts);
125#else
126 clock_gettime(CLOCK_MONOTONIC, &ts);
127#endif
thaloun2935e012015-11-17 15:02:44 -0800128 return 1000000000LL * ts.tv_sec + ts.tv_nsec;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000129#elif defined(WEBRTC_MAC)
thaloun2935e012015-11-17 15:02:44 -0800130 // Return absolute time as an offset from the first call to this function, so
131 // that we can do floating-point (double) operations on it without losing
132 // precision. This holds true until the elapsed time is ~11 days,
133 // at which point we'll start to lose some precision, though not enough to
134 // matter for millisecond accuracy for another couple years after that.
135 // TODO(pbos): Fix unsafe use of static locals.
136 static uint64_t timebase_start = 0;
137 if (timebase_start == 0) {
138 timebase_start = mach_absolute_time();
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000139 }
thaloun2935e012015-11-17 15:02:44 -0800140 return mach_absolute_time() - timebase_start;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000141#else
142 struct timeval tv;
143 gettimeofday(&tv, NULL);
thaloun2935e012015-11-17 15:02:44 -0800144 return 1000000LL * tv.tv_sec + tv.tv_usec;
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000145#endif
fischman@webrtc.org1d4a2d52013-06-27 17:15:20 +0000146}
147
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +0000148} // namespace webrtc