diff options
-rw-r--r-- | base/profiler/tracked_time.cc | 3 | ||||
-rw-r--r-- | base/test/test_suite.cc | 1 | ||||
-rw-r--r-- | base/threading/platform_thread_win.cc | 7 | ||||
-rw-r--r-- | base/time/time.h | 11 | ||||
-rw-r--r-- | base/time/time_win.cc | 48 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main_win.cc | 16 | ||||
-rw-r--r-- | content/app/content_main_runner.cc | 3 | ||||
-rw-r--r-- | content/browser/browser_child_process_host_impl.cc | 3 | ||||
-rw-r--r-- | content/browser/renderer_host/render_process_host_impl.cc | 3 | ||||
-rw-r--r-- | content/public/common/content_switches.cc | 5 | ||||
-rw-r--r-- | content/public/common/content_switches.h | 3 |
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[]; |