summaryrefslogtreecommitdiffstats
path: root/base/time_win.cc
diff options
context:
space:
mode:
authordeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-02 12:08:36 +0000
committerdeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-02 12:08:36 +0000
commit87b3252371835a19ace756ef4fbdfb9c6eee5778 (patch)
tree7f364f73e07a900c6a4232ace569138a5644fc65 /base/time_win.cc
parenta89d97fdbea8bf1e246f2adf33819342f684d944 (diff)
downloadchromium_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.cc125
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);
}
+