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