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 // System independant wrapper for polling elapsed time in ms and us. 12 // The implementation works in the tick domain which can be mapped over to the 13 // time domain. 14 #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 15 #define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 16 17 #if _WIN32 18 #include <windows.h> 19 #include <mmsystem.h> 20 #elif WEBRTC_LINUX 21 #include <ctime> 22 #elif WEBRTC_MAC 23 #include <mach/mach_time.h> 24 #include <string.h> 25 #else 26 #include <sys/time.h> 27 #include <time.h> 28 #endif 29 30 #include "typedefs.h" 31 32 namespace webrtc { 33 class TickInterval; 34 35 class TickTime 36 { 37 public: 38 // Current time in the tick domain. 39 static TickTime Now(); 40 41 // Now in the time domain in ms. 42 static WebRtc_Word64 MillisecondTimestamp(); 43 44 // Now in the time domain in us. 45 static WebRtc_Word64 MicrosecondTimestamp(); 46 47 WebRtc_Word64 Ticks() const; 48 49 static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms); 50 51 static WebRtc_Word64 TicksToMilliseconds(const WebRtc_Word64 ticks); 52 53 // Returns a TickTime that is ticks later than the passed TickTime 54 friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks); 55 TickTime& operator+=(const WebRtc_Word64& rhs); 56 57 58 // Returns a TickInterval that is the difference in ticks beween rhs and lhs 59 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); 60 private: 61 WebRtc_Word64 _ticks; 62 }; 63 64 class TickInterval 65 { 66 public: 67 TickInterval(); 68 69 WebRtc_Word64 Milliseconds() const; 70 WebRtc_Word64 Microseconds() const; 71 72 // Returns the sum of two TickIntervals as a TickInterval 73 friend TickInterval operator+(const TickInterval& lhs, 74 const TickInterval& rhs); 75 TickInterval& operator-=(const TickInterval& rhs); 76 77 // Returns a TickInterval corresponding to rhs - lhs 78 friend TickInterval operator-(const TickInterval& lhs, 79 const TickInterval& rhs); 80 TickInterval& operator+=(const TickInterval& rhs); 81 82 friend bool operator>(const TickInterval& lhs, const TickInterval& rhs); 83 friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs); 84 friend bool operator<(const TickInterval& lhs, const TickInterval& rhs); 85 friend bool operator>=(const TickInterval& lhs, const TickInterval& rhs); 86 87 private: 88 TickInterval(WebRtc_Word64 interval); 89 90 friend class TickTime; 91 friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); 92 93 private: 94 WebRtc_Word64 _interval; 95 }; 96 97 inline TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs) 98 { 99 return TickInterval(lhs._interval + rhs._interval); 100 } 101 102 inline TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs) 103 { 104 return TickInterval(lhs._interval - rhs._interval); 105 } 106 107 inline TickInterval operator-(const TickTime& lhs,const TickTime& rhs) 108 { 109 return TickInterval(lhs._ticks - rhs._ticks); 110 } 111 112 inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks) 113 { 114 TickTime time = lhs; 115 time._ticks += ticks; 116 return time; 117 } 118 inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) 119 { 120 return lhs._interval > rhs._interval; 121 } 122 inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) 123 { 124 return lhs._interval <= rhs._interval; 125 } 126 inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) 127 { 128 return lhs._interval <= rhs._interval; 129 } 130 inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) 131 { 132 return lhs._interval >= rhs._interval; 133 } 134 135 inline TickTime TickTime::Now() 136 { 137 TickTime result; 138 #if _WIN32 139 // TODO(wu): Remove QueryPerformanceCounter implementation. 140 #ifdef USE_QUERY_PERFORMANCE_COUNTER 141 // QueryPerformanceCounter returns the value from the TSC which is 142 // incremented at the CPU frequency. The algorithm used requires 143 // the CPU frequency to be constant. Technology like speed stepping 144 // which has variable CPU frequency will therefore yield unpredictable, 145 // incorrect time estimations. 146 LARGE_INTEGER qpcnt; 147 QueryPerformanceCounter(&qpcnt); 148 result._ticks = qpcnt.QuadPart; 149 #else 150 static volatile LONG lastTimeGetTime = 0; 151 static volatile WebRtc_Word64 numWrapTimeGetTime = 0; 152 volatile LONG* lastTimeGetTimePtr = &lastTimeGetTime; 153 DWORD now = timeGetTime(); 154 // Atomically update the last gotten time 155 DWORD old = InterlockedExchange(lastTimeGetTimePtr, now); 156 if(now < old) 157 { 158 // If now is earlier than old, there may have been a race between 159 // threads. 160 // 0x0fffffff ~3.1 days, the code will not take that long to execute 161 // so it must have been a wrap around. 162 if(old > 0xf0000000 && now < 0x0fffffff) 163 { 164 numWrapTimeGetTime++; 165 } 166 } 167 result._ticks = now + (numWrapTimeGetTime<<32); 168 #endif 169 #elif defined(WEBRTC_LINUX) 170 struct timespec ts; 171 // TODO(wu): Remove CLOCK_REALTIME implementation. 172 #ifdef WEBRTC_CLOCK_TYPE_REALTIME 173 clock_gettime(CLOCK_REALTIME, &ts); 174 #else 175 clock_gettime(CLOCK_MONOTONIC, &ts); 176 #endif 177 result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec); 178 #elif defined(WEBRTC_MAC) 179 static mach_timebase_info_data_t timebase; 180 if (timebase.denom == 0) { 181 // Get the timebase if this is the first time we run. 182 // Recommended by Apple's QA1398. 183 kern_return_t retval = mach_timebase_info(&timebase); 184 if (retval != KERN_SUCCESS) { 185 // TODO(wu): Implement CHECK similar to chrome for all the platforms. 186 // Then replace this with a CHECK(retval == KERN_SUCCESS); 187 asm("int3"); 188 } 189 } 190 // Use timebase to convert absolute time tick units into nanoseconds. 191 result._ticks = mach_absolute_time() * timebase.numer / timebase.denom; 192 #else 193 struct timeval tv; 194 gettimeofday(&tv, NULL); 195 result._ticks = 1000000LL * static_cast<WebRtc_Word64>(tv.tv_sec) + static_cast<WebRtc_Word64>(tv.tv_usec); 196 #endif 197 return result; 198 } 199 200 inline WebRtc_Word64 TickTime::MillisecondTimestamp() 201 { 202 TickTime now = TickTime::Now(); 203 #if _WIN32 204 #ifdef USE_QUERY_PERFORMANCE_COUNTER 205 LARGE_INTEGER qpfreq; 206 QueryPerformanceFrequency(&qpfreq); 207 return (now._ticks * 1000) / qpfreq.QuadPart; 208 #else 209 return now._ticks; 210 #endif 211 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 212 return now._ticks / 1000000LL; 213 #else 214 return now._ticks / 1000LL; 215 #endif 216 } 217 218 inline WebRtc_Word64 TickTime::MicrosecondTimestamp() 219 { 220 TickTime now = TickTime::Now(); 221 222 #if _WIN32 223 #ifdef USE_QUERY_PERFORMANCE_COUNTER 224 LARGE_INTEGER qpfreq; 225 QueryPerformanceFrequency(&qpfreq); 226 return (now._ticks * 1000) / (qpfreq.QuadPart/1000); 227 #else 228 return now._ticks *1000LL; 229 #endif 230 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 231 return now._ticks / 1000LL; 232 #else 233 return now._ticks; 234 #endif 235 } 236 237 inline WebRtc_Word64 TickTime::Ticks() const 238 { 239 return _ticks; 240 } 241 242 inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms) 243 { 244 #if _WIN32 245 #ifdef USE_QUERY_PERFORMANCE_COUNTER 246 LARGE_INTEGER qpfreq; 247 QueryPerformanceFrequency(&qpfreq); 248 return (qpfreq.QuadPart * ms) / 1000; 249 #else 250 return ms; 251 #endif 252 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 253 return ms * 1000000LL; 254 #else 255 return ms * 1000LL; 256 #endif 257 } 258 259 inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks) 260 { 261 #if _WIN32 262 #ifdef USE_QUERY_PERFORMANCE_COUNTER 263 LARGE_INTEGER qpfreq; 264 QueryPerformanceFrequency(&qpfreq); 265 return (ticks * 1000) / qpfreq.QuadPart; 266 #else 267 return ticks; 268 #endif 269 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 270 return ticks / 1000000LL; 271 #else 272 return ticks / 1000LL; 273 #endif 274 } 275 276 inline TickTime& TickTime::operator+=(const WebRtc_Word64& ticks) 277 { 278 _ticks += ticks; 279 return *this; 280 } 281 282 inline TickInterval::TickInterval() : _interval(0) 283 { 284 } 285 286 inline TickInterval::TickInterval(const WebRtc_Word64 interval) 287 : _interval(interval) 288 { 289 } 290 291 inline WebRtc_Word64 TickInterval::Milliseconds() const 292 { 293 #if _WIN32 294 #ifdef USE_QUERY_PERFORMANCE_COUNTER 295 LARGE_INTEGER qpfreq; 296 QueryPerformanceFrequency(&qpfreq); 297 return (_interval * 1000) / qpfreq.QuadPart; 298 #else 299 // _interval is in ms 300 return _interval; 301 #endif 302 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 303 // _interval is in ns 304 return _interval / 1000000; 305 #else 306 // _interval is usecs 307 return _interval / 1000; 308 #endif 309 } 310 311 inline WebRtc_Word64 TickInterval::Microseconds() const 312 { 313 #if _WIN32 314 #ifdef USE_QUERY_PERFORMANCE_COUNTER 315 LARGE_INTEGER qpfreq; 316 QueryPerformanceFrequency(&qpfreq); 317 return (_interval * 1000000) / qpfreq.QuadPart; 318 #else 319 // _interval is in ms 320 return _interval *1000LL; 321 #endif 322 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) 323 // _interval is in ns 324 return _interval / 1000; 325 #else 326 // _interval is usecs 327 return _interval; 328 #endif 329 } 330 331 inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) 332 { 333 _interval += rhs._interval; 334 return *this; 335 } 336 337 inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) 338 { 339 _interval -= rhs._interval; 340 return *this; 341 } 342 } // namespace webrtc 343 344 #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ 345