diff options
author | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-02 12:08:36 +0000 |
---|---|---|
committer | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-02 12:08:36 +0000 |
commit | 87b3252371835a19ace756ef4fbdfb9c6eee5778 (patch) | |
tree | 7f364f73e07a900c6a4232ace569138a5644fc65 /base/time_win.cc | |
parent | a89d97fdbea8bf1e246f2adf33819342f684d944 (diff) | |
download | chromium_src-87b3252371835a19ace756ef4fbdfb9c6eee5778.zip chromium_src-87b3252371835a19ace756ef4fbdfb9c6eee5778.tar.gz chromium_src-87b3252371835a19ace756ef4fbdfb9c6eee5778.tar.bz2 |
Revert part of r1633 Windows time changes, seems to have caused test failures?
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1635 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/time_win.cc')
-rw-r--r-- | base/time_win.cc | 125 |
1 files changed, 55 insertions, 70 deletions
diff --git a/base/time_win.cc b/base/time_win.cc index a919395..9d38993 100644 --- a/base/time_win.cc +++ b/base/time_win.cc @@ -7,11 +7,9 @@ #pragma comment(lib, "winmm.lib") #include <windows.h> #include <mmsystem.h> - #include "base/basictypes.h" #include "base/lock.h" #include "base/logging.h" -#include "base/singleton.h" namespace { @@ -124,39 +122,53 @@ void Time::Explode(bool is_local, Exploded* exploded) const { } // TimeTicks ------------------------------------------------------------------ -TimeTicks::TickFunction TimeTicks::tick_function_ = - reinterpret_cast<TickFunction>(&timeGetTime); -namespace { +TimeTicks::TickFunction TimeTicks::tick_function_= + reinterpret_cast<TickFunction>(&timeGetTime); -// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic -// because it returns the number of millisecond since Windows has started, which -// will roll over the 32-bit value every ~49 days. We try to track rollover -// ourselves, which works if TimeTicks::Now() is called at least every 49 days. -class NowSingleton { - public: - NowSingleton() - : rollover_(TimeDelta::FromMilliseconds(0)), - last_seen_(TimeTicks::tick_function_()) { } - - TimeDelta Now() { - AutoLock locked(lock_); - // We should hold the lock while calling tick_function_ to make sure that - // we keep our last_seen_ stay correctly in sync. - DWORD now = TimeTicks::tick_function_(); - if (now < last_seen_) - rollover_ += TimeDelta::FromMilliseconds(0x100000000I64); // ~49.7 days. - last_seen_ = now; - return TimeDelta::FromMilliseconds(now) + rollover_; +// static +TimeTicks TimeTicks::Now() { + // Uses the multimedia timers on Windows to get a higher resolution clock. + // timeGetTime() provides a resolution which is variable depending on + // hardware and system configuration. It can also be changed by other + // apps. This class does not attempt to change the resolution of the + // timer, because we don't want to affect other applications. + + // timeGetTime() should at least be accurate to ~5ms on all systems. + // timeGetTime() returns a 32-bit millisecond counter which has rollovers + // every ~49 days. + static DWORD last_tick_count = 0; + static int64 tick_rollover_accum = 0; + static Lock* tick_lock = NULL; // To protect during rollover periods. + + // Lazily create the lock we use. + if (!tick_lock) { + Lock* new_lock = new Lock; + if (InterlockedCompareExchangePointer( + reinterpret_cast<PVOID*>(&tick_lock), new_lock, NULL)) { + delete new_lock; + } } - private: - Lock lock_; // To protected last_seen_ and rollover_. - TimeDelta rollover_; // Accumulation of time lost do to rollover. - DWORD last_seen_; // The last timeGetTime value we saw, to detect rollover. + // Atomically protect the low and high 32bit values for time. + // In the future we may be able to optimize with + // InterlockedCompareExchange64, but that doesn't work on XP. + DWORD tick_count; + int64 rollover_count; + { + AutoLock lock(*tick_lock); + tick_count = tick_function_(); + if (tick_count < last_tick_count) + tick_rollover_accum += GG_INT64_C(0x100000000); + + last_tick_count = tick_count; + rollover_count = tick_rollover_accum; + } - DISALLOW_COPY_AND_ASSIGN(NowSingleton); -}; + // GetTickCount returns milliseconds, we want microseconds. + return TimeTicks((tick_count + rollover_count) * + Time::kMicrosecondsPerMillisecond); +} // Overview of time counters: // (1) CPU cycle counter. (Retrieved via RDTSC) @@ -186,50 +198,23 @@ class NowSingleton { // (3) System time. The system time provides a low-resolution (typically 10ms // to 55 milliseconds) time stamp but is comparatively less expensive to // retrieve and more reliable. -class UnreliableHighResNowSingleton { - public: - UnreliableHighResNowSingleton() : ticks_per_microsecond_(0) { - LARGE_INTEGER ticks_per_sec = {0}; - if (!QueryPerformanceFrequency(&ticks_per_sec)) - return; // Broken, we don't guarantee this function works. - ticks_per_microsecond_ = - ticks_per_sec.QuadPart / Time::kMicrosecondsPerSecond; - } - - bool IsBroken() { - return ticks_per_microsecond_ == 0; - } - - TimeDelta Now() { - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - return TimeDelta::FromMicroseconds(now.QuadPart / ticks_per_microsecond_); - } - - private: - // Cached clock frequency -> microseconds. This assumes that the clock - // frequency is faster than one microsecond (which is 1MHz, should be OK). - int64 ticks_per_microsecond_; // 0 indicates QPF failed and we're broken. - - DISALLOW_COPY_AND_ASSIGN(UnreliableHighResNowSingleton); -}; - -} // namespace - -// static -TimeTicks TimeTicks::Now() { - return TimeTicks() + Singleton<NowSingleton>::get()->Now(); -} // static TimeTicks TimeTicks::UnreliableHighResNow() { - UnreliableHighResNowSingleton* now = - Singleton<UnreliableHighResNowSingleton>::get(); + // Cached clock frequency -> microseconds. This assumes that the clock + // frequency is faster than one microsecond (which is 1MHz, should be OK). + static int64 ticks_per_microsecond = 0; - if (now->IsBroken()) { - NOTREACHED() << "QueryPerformanceCounter is broken."; - return TimeTicks(0); + if (ticks_per_microsecond == 0) { + LARGE_INTEGER ticks_per_sec = { 0, 0 }; + if (!QueryPerformanceFrequency(&ticks_per_sec)) + return TimeTicks(0); // Broken, we don't guarantee this function works. + ticks_per_microsecond = + ticks_per_sec.QuadPart / Time::kMicrosecondsPerSecond; } - return TimeTicks() + now->Now(); + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + return TimeTicks(now.QuadPart / ticks_per_microsecond); } + |