diff options
author | cpu <cpu@chromium.org> | 2014-09-04 21:30:05 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-05 04:31:21 +0000 |
commit | 3365a510b17169457292bdb6144cc8b95fb7ea34 (patch) | |
tree | e96c71aa4396413eb66e13066c7b1921545d093a /base | |
parent | eba92949d768e9905fd45e5b10bef8f9f1d21d08 (diff) | |
download | chromium_src-3365a510b17169457292bdb6144cc8b95fb7ea34.zip chromium_src-3365a510b17169457292bdb6144cc8b95fb7ea34.tar.gz chromium_src-3365a510b17169457292bdb6144cc8b95fb7ea34.tar.bz2 |
fix for high resolution timer on windows.
The CLs here
https://codereview.chromium.org/489793003
and here
https://codereview.chromium.org/395913006
In isolation look correct but taken together cause a overflow or underflow
bug. Basically the message loop was calling Time::ActivateHighResolutionTimer(false)
all the time (or very often) so the g_high_res_timer_count was underflowing
or overflowing.
Now messageloop only calls ActivateHighResolutionTimer in a balanced way.
This can make the base_unittests fail as well with
--gtest_filter=MessageLoopTest.HighResolutionTimer
BUG=153139
TEST=included, see bug for manual testing.
Review URL: https://codereview.chromium.org/541203002
Cr-Commit-Position: refs/heads/master@{#293434}
Diffstat (limited to 'base')
-rw-r--r-- | base/message_loop/message_loop.cc | 7 | ||||
-rw-r--r-- | base/message_loop/message_loop_unittest.cc | 2 | ||||
-rw-r--r-- | base/time/time_win.cc | 15 |
3 files changed, 16 insertions, 8 deletions
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 16b999c..c01e542 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc @@ -616,8 +616,11 @@ bool MessageLoop::DoIdleWork() { // _if_ triggered by the timer happens with good resolution. If we don't // do this the default resolution is 15ms which might not be acceptable // for some tasks. - in_high_res_mode_ = pending_high_res_tasks_ > 0; - Time::ActivateHighResolutionTimer(in_high_res_mode_); + bool high_res = pending_high_res_tasks_ > 0; + if (high_res != in_high_res_mode_) { + in_high_res_mode_ = high_res; + Time::ActivateHighResolutionTimer(in_high_res_mode_); + } #endif return false; } diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index 866c20b..0a6e817 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc @@ -726,6 +726,7 @@ TEST(MessageLoopTest, WaitForIO) { TEST(MessageLoopTest, HighResolutionTimer) { MessageLoop loop; + Time::EnableHighResolutionTimer(true); const TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5); const TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100); @@ -744,6 +745,7 @@ TEST(MessageLoopTest, HighResolutionTimer) { EXPECT_FALSE(loop.HasHighResolutionTasks()); loop.Run(); EXPECT_FALSE(loop.HasHighResolutionTasks()); + Time::EnableHighResolutionTimer(false); } #endif // defined(OS_WIN) diff --git a/base/time/time_win.cc b/base/time/time_win.cc index 492b54a..2586cb3 100644 --- a/base/time/time_win.cc +++ b/base/time/time_win.cc @@ -92,7 +92,7 @@ const int kMinTimerIntervalLowResMs = 4; // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. bool g_high_res_timer_enabled = false; // How many times the high resolution timer has been called. -int g_high_res_timer_count = 0; +uint32_t g_high_res_timer_count = 0; // The lock to control access to the above two variables. base::LazyInstance<base::Lock>::Leaky g_high_res_lock = LAZY_INSTANCE_INITIALIZER; @@ -197,17 +197,20 @@ bool Time::ActivateHighResolutionTimer(bool activating) { // We only do work on the transition from zero to one or one to zero so we // can easily undo the effect (if necessary) when EnableHighResolutionTimer is // called. + const uint32_t max = std::numeric_limits<uint32_t>::max(); + base::AutoLock lock(g_high_res_lock.Get()); UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs : kMinTimerIntervalLowResMs; - int high_res_count = - activating ? ++g_high_res_timer_count : --g_high_res_timer_count; - if (activating) { - if (high_res_count == 1) + DCHECK(g_high_res_timer_count != max); + ++g_high_res_timer_count; + if (g_high_res_timer_count == 1) timeBeginPeriod(period); } else { - if (high_res_count == 0) + DCHECK(g_high_res_timer_count != 0); + --g_high_res_timer_count; + if (g_high_res_timer_count == 0) timeEndPeriod(period); } return (period == kMinTimerIntervalHighResMs); |