summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorcpu <cpu@chromium.org>2014-09-04 21:30:05 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-05 04:31:21 +0000
commit3365a510b17169457292bdb6144cc8b95fb7ea34 (patch)
treee96c71aa4396413eb66e13066c7b1921545d093a /base
parenteba92949d768e9905fd45e5b10bef8f9f1d21d08 (diff)
downloadchromium_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.cc7
-rw-r--r--base/message_loop/message_loop_unittest.cc2
-rw-r--r--base/time/time_win.cc15
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);