2 * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Google Inc. All rights reserved.
4 * Copyright (C) 2007-2009 Torch Mobile, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "CurrentTime.h"
37 #include <mach/mach_time.h>
41 // Windows is first since we want to use hires timers, despite USE(CF)
43 // If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
44 #undef WIN32_LEAN_AND_MEAN
51 #include <wx/datetime.h>
63 #include <QElapsedTimer>
68 #if !PLATFORM(CHROMIUM)
72 // Number of 100 nanosecond between January 1, 1601 and January 1, 1970.
73 static const ULONGLONG epochBias = 116444736000000000ULL;
74 static const double hundredsOfNanosecondsPerMillisecond = 10000;
76 static double lowResUTCTime()
81 GetCurrentFT(&fileTime);
83 GetSystemTimeAsFileTime(&fileTime);
86 // As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a
87 // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can
88 // prevent alignment faults on 64-bit Windows).
90 ULARGE_INTEGER dateTime;
91 memcpy(&dateTime, &fileTime, sizeof(dateTime));
93 // Windows file times are in 100s of nanoseconds.
94 return (dateTime.QuadPart - epochBias) / hundredsOfNanosecondsPerMillisecond;
97 #if USE(QUERY_PERFORMANCE_COUNTER)
99 static LARGE_INTEGER qpcFrequency;
100 static bool syncedTime;
102 static double highResUpTime()
104 // We use QPC, but only after sanity checking its result, due to bugs:
105 // http://support.microsoft.com/kb/274323
106 // http://support.microsoft.com/kb/895980
107 // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)."
109 static LARGE_INTEGER qpcLast;
110 static DWORD tickCountLast;
114 QueryPerformanceCounter(&qpc);
115 DWORD tickCount = GetTickCount();
118 __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart;
119 __int64 tickCountElapsed;
120 if (tickCount >= tickCountLast)
121 tickCountElapsed = (tickCount - tickCountLast);
124 __int64 tickCountLarge = tickCount + 0x100000000ULL;
126 __int64 tickCountLarge = tickCount + 0x100000000I64;
128 tickCountElapsed = tickCountLarge - tickCountLast;
131 // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms.
132 // (500ms value is from http://support.microsoft.com/kb/274323)
133 __int64 diff = tickCountElapsed - qpcElapsed;
134 if (diff > 500 || diff < -500)
140 tickCountLast = tickCount;
142 return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart);
145 static bool qpcAvailable()
147 static bool available;
153 available = QueryPerformanceFrequency(&qpcFrequency);
160 // Use a combination of ftime and QueryPerformanceCounter.
161 // ftime returns the information we want, but doesn't have sufficient resolution.
162 // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals.
163 // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter
164 // by itself, adding the delta to the saved ftime. We periodically re-sync to correct for drift.
165 static double syncLowResUTCTime;
166 static double syncHighResUpTime;
167 static double lastUTCTime;
169 double lowResTime = lowResUTCTime();
172 return lowResTime / 1000.0;
174 double highResTime = highResUpTime();
177 timeBeginPeriod(1); // increase time resolution around low-res time getter
178 syncLowResUTCTime = lowResTime = lowResUTCTime();
179 timeEndPeriod(1); // restore time resolution
180 syncHighResUpTime = highResTime;
184 double highResElapsed = highResTime - syncHighResUpTime;
185 double utc = syncLowResUTCTime + highResElapsed;
187 // force a clock re-sync if we've drifted
188 double lowResElapsed = lowResTime - syncLowResUTCTime;
189 const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy
190 if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec)
193 // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur)
194 const double backwardTimeLimit = 2000.0;
195 if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit)
196 return lastUTCTime / 1000.0;
205 static bool init = false;
206 static double lastTime;
207 static DWORD lastTickCount;
209 lastTime = lowResUTCTime();
210 lastTickCount = GetTickCount();
215 DWORD tickCountNow = GetTickCount();
216 DWORD elapsed = tickCountNow - lastTickCount;
217 double timeNow = lastTime + (double)elapsed / 1000.;
218 if (elapsed >= 0x7FFFFFFF) {
220 lastTickCount = tickCountNow;
225 #endif // USE(QUERY_PERFORMANCE_COUNTER)
229 // Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
230 // better accuracy compared with Windows implementation of g_get_current_time:
231 // (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
232 // Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
236 g_get_current_time(&now);
237 return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
244 wxDateTime now = wxDateTime::UNow();
245 return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
252 return ecore_time_unix_get();
259 struct timespec time;
260 if (clock_gettime(CLOCK_REALTIME, &time))
262 return time.tv_sec + time.tv_nsec / 1.0e9;
270 gettimeofday(&now, 0);
271 return now.tv_sec + now.tv_usec / 1000000.0;
278 double monotonicallyIncreasingTime()
280 // Based on listing #2 from Apple QA 1398.
281 static mach_timebase_info_data_t timebaseInfo;
282 if (!timebaseInfo.denom) {
283 kern_return_t kr = mach_timebase_info(&timebaseInfo);
284 ASSERT_UNUSED(kr, kr == KERN_SUCCESS);
286 return (mach_absolute_time() * timebaseInfo.numer) / (1.0e9 * timebaseInfo.denom);
291 double monotonicallyIncreasingTime()
293 return ecore_time_get();
298 double monotonicallyIncreasingTime()
300 return static_cast<double>(g_get_monotonic_time() / 1000000.0);
305 double monotonicallyIncreasingTime()
307 ASSERT(QElapsedTimer::isMonotonic());
308 static QElapsedTimer timer;
309 return timer.nsecsElapsed() / 1.0e9;
314 double monotonicallyIncreasingTime()
316 struct timespec time;
317 if (clock_gettime(CLOCK_MONOTONIC, &time))
319 return time.tv_sec + time.tv_nsec / 1.0e9;
324 double monotonicallyIncreasingTime()
326 static double lastTime = 0;
327 double currentTimeNow = currentTime();
328 if (currentTimeNow < lastTime)
330 lastTime = currentTimeNow;
331 return currentTimeNow;
336 #endif // !PLATFORM(CHROMIUM)
338 void getLocalTime(const time_t* localTime, struct tm* localTM)
340 #if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) || OS(WINCE)
341 *localTM = *localtime(localTime);
343 localtime_s(localTM, localTime);
345 localtime_r(localTime, localTM);
349 void getCurrentLocalTime(struct tm* localTM)
351 time_t localTime = time(0);
352 getLocalTime(&localTime, localTM);