summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/profiler/tracked_time.cc3
-rw-r--r--base/test/test_suite.cc1
-rw-r--r--base/threading/platform_thread_win.cc7
-rw-r--r--base/time/time.h11
-rw-r--r--base/time/time_win.cc48
-rw-r--r--chrome/browser/chrome_browser_main_win.cc16
-rw-r--r--content/app/content_main_runner.cc3
-rw-r--r--content/browser/browser_child_process_host_impl.cc3
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc3
-rw-r--r--content/public/common/content_switches.cc5
-rw-r--r--content/public/common/content_switches.h3
11 files changed, 96 insertions, 7 deletions
diff --git a/base/profiler/tracked_time.cc b/base/profiler/tracked_time.cc
index 27d3358..7791c3a 100644
--- a/base/profiler/tracked_time.cc
+++ b/base/profiler/tracked_time.cc
@@ -55,8 +55,7 @@ TrackedTime TrackedTime::Now() {
// Use lock-free accessor to 32 bit time.
// Note that TimeTicks::Now() is built on this, so we have "compatible"
// times when we down-convert a TimeTicks sample.
- // TODO(jar): Surface this interface via something in base/time/time.h.
- return TrackedTime(static_cast<int32>(timeGetTime()));
+ return TrackedTime(base::TimeTicks::UnprotectedNow());
#else
// Posix has nice cheap 64 bit times, so we just down-convert it.
return TrackedTime(base::TimeTicks::Now());
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index ef3ee99..9d7c158 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -99,6 +99,7 @@ void TestSuite::PreInitialize(int argc, char** argv,
bool create_at_exit_manager) {
#if defined(OS_WIN)
testing::GTEST_FLAG(catch_exceptions) = false;
+ base::TimeTicks::SetNowIsHighResNowIfSupported();
#endif
base::EnableTerminationOnHeapCorruption();
initialized_command_line_ = CommandLine::Init(argc, argv);
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc
index cf1e0f6..e9752ba 100644
--- a/base/threading/platform_thread_win.cc
+++ b/base/threading/platform_thread_win.cc
@@ -135,7 +135,12 @@ void PlatformThread::YieldCurrentThread() {
// static
void PlatformThread::Sleep(TimeDelta duration) {
- ::Sleep(duration.InMillisecondsRoundedUp());
+ // When measured with a high resolution clock, Sleep() sometimes returns much
+ // too early. We may need to call it repeatedly to get the desired duration.
+ TimeTicks end = TimeTicks::Now() + duration;
+ TimeTicks now;
+ while ((now = TimeTicks::Now()) < end)
+ ::Sleep((end - now).InMillisecondsRoundedUp());
}
// static
diff --git a/base/time/time.h b/base/time/time.h
index eba6145..5d7033a 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -572,6 +572,17 @@ class BASE_EXPORT TimeTicks {
// Returns true if the high resolution clock is working on this system.
// This is only for testing.
static bool IsHighResClockWorking();
+
+ // Enable high resolution time for TimeTicks::Now(). This function will
+ // test for the availability of a working implementation of
+ // QueryPerformanceCounter(). If one is not available, this function does
+ // nothing and the resolution of Now() remains 1ms. Otherwise, all future
+ // calls to TimeTicks::Now() will have the higher resolution provided by QPC.
+ // Returns true if high resolution time was successfully enabled.
+ static bool SetNowIsHighResNowIfSupported();
+
+ // Returns a time value that is NOT rollover protected.
+ static TimeTicks UnprotectedNow();
#endif
// Returns true if this object has not been initialized.
diff --git a/base/time/time_win.cc b/base/time/time_win.cc
index 3680ee2a..f35f735 100644
--- a/base/time/time_win.cc
+++ b/base/time/time_win.cc
@@ -322,6 +322,12 @@ TimeDelta RolloverProtectedNow() {
return TimeDelta::FromMilliseconds(now + rollover_ms);
}
+bool IsBuggyAthlon(const base::CPU& cpu) {
+ // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
+ // unreliable. Fallback to low-res clock.
+ return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15;
+}
+
// Overview of time counters:
// (1) CPU cycle counter. (Retrieved via RDTSC)
// The CPU counter provides the highest resolution time stamp and is the least
@@ -398,10 +404,8 @@ class HighResNowSingleton {
skew_(0) {
InitializeClock();
- // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
- // unreliable. Fallback to low-res clock.
base::CPU cpu;
- if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15)
+ if (IsBuggyAthlon(cpu))
DisableHighResClock();
}
@@ -433,6 +437,24 @@ class HighResNowSingleton {
friend struct DefaultSingletonTraits<HighResNowSingleton>;
};
+TimeDelta HighResNowWrapper() {
+ return HighResNowSingleton::GetInstance()->Now();
+}
+
+typedef TimeDelta (*NowFunction)(void);
+NowFunction now_function = RolloverProtectedNow;
+
+bool CPUReliablySupportsHighResTime() {
+ base::CPU cpu;
+ if (!cpu.has_non_stop_time_stamp_counter())
+ return false;
+
+ if (IsBuggyAthlon(cpu))
+ return false;
+
+ return true;
+}
+
} // namespace
// static
@@ -447,8 +469,18 @@ TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
}
// static
+bool TimeTicks::SetNowIsHighResNowIfSupported() {
+ if (!CPUReliablySupportsHighResTime()) {
+ return false;
+ }
+
+ now_function = HighResNowWrapper;
+ return true;
+}
+
+// static
TimeTicks TimeTicks::Now() {
- return TimeTicks() + RolloverProtectedNow();
+ return TimeTicks() + now_function();
}
// static
@@ -483,6 +515,14 @@ bool TimeTicks::IsHighResClockWorking() {
return HighResNowSingleton::GetInstance()->IsUsingHighResClock();
}
+TimeTicks TimeTicks::UnprotectedNow() {
+ if (now_function == HighResNowWrapper) {
+ return Now();
+ } else {
+ return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime());
+ }
+}
+
// TimeDelta ------------------------------------------------------------------
// static
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index b9ef210..16a6452 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -30,6 +30,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_version_info.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/launcher_support/chrome_launcher_support.h"
#include "chrome/installer/util/browser_distribution.h"
@@ -141,11 +142,26 @@ int DoUninstallTasks(bool chrome_still_running) {
return result;
}
+void MaybeEnableHighResolutionTimeEverywhere() {
+ chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
+ bool user_enabled = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableHighResolutionTime);
+ if (user_enabled || channel == chrome::VersionInfo::CHANNEL_CANARY) {
+ bool is_enabled = base::TimeTicks::SetNowIsHighResNowIfSupported();
+ if (is_enabled && !user_enabled) {
+ // Ensure that all of the renderers will enable it too.
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableHighResolutionTime);
+ }
+ }
+}
+
// ChromeBrowserMainPartsWin ---------------------------------------------------
ChromeBrowserMainPartsWin::ChromeBrowserMainPartsWin(
const content::MainFunctionParams& parameters)
: ChromeBrowserMainParts(parameters) {
+ MaybeEnableHighResolutionTimeEverywhere();
if (base::win::IsMetroProcess()) {
typedef const wchar_t* (*GetMetroSwitches)(void);
GetMetroSwitches metro_switches_proc = reinterpret_cast<GetMetroSwitches>(
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 9fc34c2..7bfc37b 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -686,6 +686,9 @@ class ContentMainRunnerImpl : public ContentMainRunner {
MachBroker::ChildSendTaskPortToParent();
}
#elif defined(OS_WIN)
+ if (command_line.HasSwitch(switches::kEnableHighResolutionTime))
+ base::TimeTicks::SetNowIsHighResNowIfSupported();
+
// This must be done early enough since some helper functions like
// IsTouchEnabled, needed to load resources, may call into the theme dll.
EnableThemeSupportOnAllWindowStations();
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index f4598be..5cc9532 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -153,6 +153,9 @@ void BrowserChildProcessHostImpl::Launch(
#if defined(OS_POSIX)
switches::kChildCleanExit,
#endif
+#if defined(OS_WIN)
+ switches::kEnableHighResolutionTime,
+#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 0397f3d..07b6213 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -908,6 +908,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
switches::kEnableGpuBenchmarking,
+#if defined(OS_WIN)
+ switches::kEnableHighResolutionTime,
+#endif
switches::kEnableMP3StreamParser,
switches::kEnableMemoryBenchmarking,
switches::kEnableOverlayScrollbars,
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 7044813f..6e4682d 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -413,6 +413,11 @@ const char kEnableGpuClientTracing[] = "enable-gpu-client-tracing";
const char kEnableHighDpiCompositingForFixedPosition[] =
"enable-high-dpi-fixed-position-compositing";
+#if defined(OS_WIN)
+// Use high resolution timers for TimeTicks.
+const char kEnableHighResolutionTime[] = "enable-high-resolution-time";
+#endif
+
// Enable HTML Imports
extern const char kEnableHTMLImports[] = "enable-html-imports";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 381abdd..e0a0977 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -126,6 +126,9 @@ CONTENT_EXPORT extern const char kEnableGestureTapHighlight[];
extern const char kEnableGpuBenchmarking[];
extern const char kEnableGpuClientTracing[];
CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
+ #if defined(OS_WIN)
+extern const char kEnableHighResolutionTime[];
+#endif
extern const char kEnableHTMLImports[];
CONTENT_EXPORT extern const char kEnableInbandTextTracks[];
extern const char kEnableInputModeAttribute[];