1 /*
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
11 #include "webrtc/system_wrappers/include/tick_util.h"
12
13 #include <assert.h>
14
15 namespace webrtc {
16
MillisecondTimestamp()17 int64_t TickTime::MillisecondTimestamp() {
18 return TicksToMilliseconds(TickTime::Now().Ticks());
19 }
20
MicrosecondTimestamp()21 int64_t TickTime::MicrosecondTimestamp() {
22 return TicksToMicroseconds(TickTime::Now().Ticks());
23 }
24
MillisecondsToTicks(const int64_t ms)25 int64_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
TicksToMilliseconds(const int64_t ticks)44 int64_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
TicksToMicroseconds(const int64_t ticks)63 int64_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
82 // 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.
QueryOsForTicks()88 int64_t TickTime::QueryOsForTicks() {
89 #if _WIN32
90 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) {
102 // TODO(pbos): Fix unsafe use of static locals.
103 num_wrap_time_get_time++;
104 }
105 }
106 return now + (num_wrap_time_get_time << 32);
107 #elif defined(WEBRTC_LINUX)
108 struct timespec ts;
109 // TODO(wu): Remove CLOCK_REALTIME implementation.
110 #ifdef WEBRTC_CLOCK_TYPE_REALTIME
111 clock_gettime(CLOCK_REALTIME, &ts);
112 #else
113 clock_gettime(CLOCK_MONOTONIC, &ts);
114 #endif
115 return 1000000000LL * ts.tv_sec + ts.tv_nsec;
116 #elif defined(WEBRTC_MAC)
117 // Return absolute time as an offset from the first call to this function, so
118 // that we can do floating-point (double) operations on it without losing
119 // precision. This holds true until the elapsed time is ~11 days,
120 // at which point we'll start to lose some precision, though not enough to
121 // matter for millisecond accuracy for another couple years after that.
122 // TODO(pbos): Fix unsafe use of static locals.
123 static uint64_t timebase_start = 0;
124 if (timebase_start == 0) {
125 timebase_start = mach_absolute_time();
126 }
127 return mach_absolute_time() - timebase_start;
128 #else
129 struct timeval tv;
130 gettimeofday(&tv, NULL);
131 return 1000000LL * tv.tv_sec + tv.tv_usec;
132 #endif
133 }
134
135 } // namespace webrtc
136