1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/*
221939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2008 Google Inc. All rights reserved.
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2007-2009 Torch Mobile, Inc.
5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without
7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions are
8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * met:
9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Redistributions of source code must retain the above copyright
11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer.
12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Redistributions in binary form must reproduce the above
13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * copyright notice, this list of conditions and the following disclaimer
14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * in the documentation and/or other materials provided with the
15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * distribution.
16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Neither the name of Google Inc. nor the names of its
17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * contributors may be used to endorse or promote products derived from
18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * this software without specific prior written permission.
19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */
32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h"
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CurrentTime.h"
35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
36d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINDOWS)
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch// Windows is first since we want to use hires timers, despite USE(CF)
398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// being defined.
40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#undef WIN32_LEAN_AND_MEAN
42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <windows.h>
43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <math.h>
44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <stdint.h>
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <time.h>
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(QUERY_PERFORMANCE_COUNTER)
48d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINCE)
490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochextern "C" time_t mktime(struct tm *t);
500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <sys/timeb.h>
52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <sys/types.h>
530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(GTK)
578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <glib.h>
588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(WX)
598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <wx/datetime.h>
605e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#elif PLATFORM(BREWMP)
615e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#include <AEEStdLib.h>
6221939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <sys/time.h>
64635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
66cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#if PLATFORM(CHROMIUM)
67cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#error Chromium uses a different timer implementation
68cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#endif
69cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WTF {
71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
72635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectconst double msPerSecond = 1000.0;
73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
74d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINDOWS)
75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(QUERY_PERFORMANCE_COUNTER)
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic LARGE_INTEGER qpcFrequency;
79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool syncedTime;
80635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
81635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic double highResUpTime()
82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // We use QPC, but only after sanity checking its result, due to bugs:
84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // http://support.microsoft.com/kb/274323
85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // http://support.microsoft.com/kb/895980
86635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // 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)."
87635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static LARGE_INTEGER qpcLast;
89635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static DWORD tickCountLast;
90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static bool inited;
91635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
92635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    LARGE_INTEGER qpc;
93635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    QueryPerformanceCounter(&qpc);
94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DWORD tickCount = GetTickCount();
95635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
96635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (inited) {
97635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart;
98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        __int64 tickCountElapsed;
99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (tickCount >= tickCountLast)
100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            tickCountElapsed = (tickCount - tickCountLast);
101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        else {
102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if COMPILER(MINGW)
103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            __int64 tickCountLarge = tickCount + 0x100000000ULL;
104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else
105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            __int64 tickCountLarge = tickCount + 0x100000000I64;
106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            tickCountElapsed = tickCountLarge - tickCountLast;
108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms.
111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // (500ms value is from http://support.microsoft.com/kb/274323)
112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        __int64 diff = tickCountElapsed - qpcElapsed;
113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (diff > 500 || diff < -500)
114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            syncedTime = false;
115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    } else
116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        inited = true;
117635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    qpcLast = qpc;
119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tickCountLast = tickCount;
120635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart);
122635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
123635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic double lowResUTCTime()
125635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
126d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINCE)
127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    SYSTEMTIME systemTime;
128635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    GetSystemTime(&systemTime);
129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    struct tm tmtime;
130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_year = systemTime.wYear - 1900;
131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_mon = systemTime.wMonth - 1;
132635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_mday = systemTime.wDay;
133635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_wday = systemTime.wDayOfWeek;
134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_hour = systemTime.wHour;
135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_min = systemTime.wMinute;
136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    tmtime.tm_sec = systemTime.wSecond;
137635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    time_t timet = mktime(&tmtime);
138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return timet * msPerSecond + systemTime.wMilliseconds;
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
140635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    struct _timeb timebuffer;
141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    _ftime(&timebuffer);
142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return timebuffer.time * msPerSecond + timebuffer.millitm;
1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool qpcAvailable()
147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static bool available;
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static bool checked;
150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (checked)
152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return available;
153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
154635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    available = QueryPerformanceFrequency(&qpcFrequency);
155635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    checked = true;
156635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return available;
157635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectdouble currentTime()
160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Use a combination of ftime and QueryPerformanceCounter.
162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // ftime returns the information we want, but doesn't have sufficient resolution.
163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals.
164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter
165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // by itself, adding the delta to the saved ftime.  We periodically re-sync to correct for drift.
166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static double syncLowResUTCTime;
167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static double syncHighResUpTime;
168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static double lastUTCTime;
169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double lowResTime = lowResUTCTime();
171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!qpcAvailable())
173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return lowResTime / 1000.0;
174635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double highResTime = highResUpTime();
176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
177635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!syncedTime) {
178635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        timeBeginPeriod(1); // increase time resolution around low-res time getter
179635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        syncLowResUTCTime = lowResTime = lowResUTCTime();
180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        timeEndPeriod(1); // restore time resolution
181635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        syncHighResUpTime = highResTime;
182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        syncedTime = true;
183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double highResElapsed = highResTime - syncHighResUpTime;
186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double utc = syncLowResUTCTime + highResElapsed;
187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // force a clock re-sync if we've drifted
189635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double lowResElapsed = lowResTime - syncLowResUTCTime;
190635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy
191635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec)
192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        syncedTime = false;
193635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
194635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur)
195635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    const double backwardTimeLimit = 2000.0;
196635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit)
197635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return lastUTCTime / 1000.0;
198635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    lastUTCTime = utc;
199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return utc / 1000.0;
200635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic double currentSystemTime()
2050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    FILETIME ft;
2070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    GetCurrentFT(&ft);
2080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a
2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can
2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // prevent alignment faults on 64-bit Windows).
2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ULARGE_INTEGER t;
2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    memcpy(&t, &ft, sizeof(t));
2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Windows file times are in 100s of nanoseconds.
2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // To convert to seconds, we have to divide by 10,000,000, which is more quickly
2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // done by multiplying by 0.0000001.
2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Between January 1, 1601 and January 1, 1970, there were 369 complete years,
2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // of which 89 were leap years (1700, 1800, and 1900 were not leap years).
2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // That is a total of 134774 days, which is 11644473600 seconds.
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return t.QuadPart * 0.0000001 - 11644473600.0;
2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdouble currentTime()
2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static bool init = false;
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static double lastTime;
2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static DWORD lastTickCount;
2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!init) {
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lastTime = currentSystemTime();
2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lastTickCount = GetTickCount();
2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        init = true;
2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return lastTime;
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DWORD tickCountNow = GetTickCount();
2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DWORD elapsed = tickCountNow - lastTickCount;
2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    double timeNow = lastTime + (double)elapsed / 1000.;
2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (elapsed >= 0x7FFFFFFF) {
2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lastTime = timeNow;
2440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        lastTickCount = tickCountNow;
2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return timeNow;
2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif // USE(QUERY_PERFORMANCE_COUNTER)
2500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(GTK)
2528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// better accuracy compared with Windows implementation of g_get_current_time:
2558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
2578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiandouble currentTime()
2588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    GTimeVal now;
2608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    g_get_current_time(&now);
2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(WX)
2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiandouble currentTime()
2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    wxDateTime now = wxDateTime::UNow();
2698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2725e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#elif PLATFORM(BREWMP)
2735e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
2745e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block// GETUTCSECONDS returns the number of seconds since 1980/01/06 00:00:00 UTC,
2755e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block// and GETTIMEMS returns the number of milliseconds that have elapsed since the last
2765e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block// occurrence of 00:00:00 local time.
2775e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block// We can combine GETUTCSECONDS and GETTIMEMS to calculate the number of milliseconds
2785e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block// since 1970/01/01 00:00:00 UTC.
2795e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Blockdouble currentTime()
2805e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
2815e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // diffSeconds is the number of seconds from 1970/01/01 to 1980/01/06
2825e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    const unsigned diffSeconds = 315964800;
2835e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    return static_cast<double>(diffSeconds + GETUTCSECONDS() + ((GETTIMEMS() % 1000) / msPerSecond));
2845e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
2855e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
28621939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectdouble currentTime()
289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    struct timeval now;
29121939df44de1705786c545cd1bf519d47250322dBen Murdoch    gettimeofday(&now, 0);
29221939df44de1705786c545cd1bf519d47250322dBen Murdoch    return now.tv_sec + now.tv_usec / 1000000.0;
293635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} // namespace WTF
298