Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: components/scheduler/renderer/throttling_helper.cc

Issue 2028433004: Fix a bug with throttling and timer queue suspension (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make sure this works in general. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/scheduler/renderer/throttling_helper.h" 5 #include "components/scheduler/renderer/throttling_helper.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "components/scheduler/base/real_time_domain.h" 8 #include "components/scheduler/base/real_time_domain.h"
9 #include "components/scheduler/child/scheduler_tqm_delegate.h" 9 #include "components/scheduler/child/scheduler_tqm_delegate.h"
10 #include "components/scheduler/renderer/renderer_scheduler_impl.h" 10 #include "components/scheduler/renderer/renderer_scheduler_impl.h"
(...skipping 25 matching lines...) Expand all
36 // before unregistering the time domain. 36 // before unregistering the time domain.
37 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) { 37 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
38 TaskQueue* task_queue = map_entry.first; 38 TaskQueue* task_queue = map_entry.first;
39 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 39 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
40 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO); 40 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
41 } 41 }
42 42
43 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get()); 43 renderer_scheduler_->UnregisterTimeDomain(time_domain_.get());
44 } 44 }
45 45
46 void ThrottlingHelper::SetQueueEnabled(TaskQueue* task_queue, bool enabled) {
47 TaskQueueMap::iterator find_it = throttled_queues_.find(task_queue);
48
49 if (find_it == throttled_queues_.end()) {
50 task_queue->SetQueueEnabled(enabled);
51 return;
52 }
53
54 find_it->second.enabled = enabled;
55
56 if (!enabled)
Sami 2016/05/31 18:11:04 Maybe add a comment why we don't want to enable th
alex clarke (OOO till 29th) 2016/06/02 13:51:05 Done.
57 task_queue->SetQueueEnabled(false);
58 }
59
46 void ThrottlingHelper::IncreaseThrottleRefCount(TaskQueue* task_queue) { 60 void ThrottlingHelper::IncreaseThrottleRefCount(TaskQueue* task_queue) {
47 DCHECK_NE(task_queue, task_runner_.get()); 61 DCHECK_NE(task_queue, task_runner_.get());
48 62
49 std::pair<TaskQueueMap::iterator, bool> insert_result = 63 std::pair<TaskQueueMap::iterator, bool> insert_result =
50 throttled_queues_.insert(std::make_pair(task_queue, 1)); 64 throttled_queues_.insert(std::make_pair(
65 task_queue, Metadata(1, task_queue->IsQueueEnabled())));
51 66
52 if (insert_result.second) { 67 if (insert_result.second) {
53 // The insert was succesful so we need to throttle the queue. 68 // The insert was succesful so we need to throttle the queue.
54 task_queue->SetTimeDomain(time_domain_.get()); 69 task_queue->SetTimeDomain(time_domain_.get());
55 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); 70 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL);
56 task_queue->SetQueueEnabled(false); 71 task_queue->SetQueueEnabled(false);
57 72
58 if (!task_queue->IsEmpty()) { 73 if (!task_queue->IsEmpty()) {
59 if (task_queue->HasPendingImmediateWork()) { 74 if (task_queue->HasPendingImmediateWork()) {
60 OnTimeDomainHasImmediateWork(); 75 OnTimeDomainHasImmediateWork();
61 } else { 76 } else {
62 OnTimeDomainHasDelayedWork(); 77 OnTimeDomainHasDelayedWork();
63 } 78 }
64 } 79 }
65 } else { 80 } else {
66 // An entry already existed in the map so we need to increment the refcount. 81 // An entry already existed in the map so we need to increment the refcount.
67 insert_result.first->second++; 82 insert_result.first->second.throttling_ref_count++;
68 } 83 }
69 } 84 }
70 85
71 void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) { 86 void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) {
72 TaskQueueMap::iterator iter = throttled_queues_.find(task_queue); 87 TaskQueueMap::iterator iter = throttled_queues_.find(task_queue);
73 88
74 if (iter != throttled_queues_.end() && --iter->second == 0) { 89 if (iter != throttled_queues_.end() &&
90 --iter->second.throttling_ref_count == 0) {
91 bool enabled = iter->second.enabled;
75 // The refcount has become zero, we need to unthrottle the queue. 92 // The refcount has become zero, we need to unthrottle the queue.
76 throttled_queues_.erase(iter); 93 throttled_queues_.erase(iter);
77 94
78 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 95 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
79 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO); 96 task_queue->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO);
80 task_queue->SetQueueEnabled(true); 97 task_queue->SetQueueEnabled(enabled);
81 } 98 }
82 } 99 }
83 100
84 void ThrottlingHelper::UnregisterTaskQueue(TaskQueue* task_queue) { 101 void ThrottlingHelper::UnregisterTaskQueue(TaskQueue* task_queue) {
85 throttled_queues_.erase(task_queue); 102 throttled_queues_.erase(task_queue);
86 } 103 }
87 104
88 void ThrottlingHelper::OnTimeDomainHasImmediateWork() { 105 void ThrottlingHelper::OnTimeDomainHasImmediateWork() {
89 // Forward to the main thread if called from another thread. 106 // Forward to the main thread if called from another thread.
90 if (!task_runner_->RunsTasksOnCurrentThread()) { 107 if (!task_runner_->RunsTasksOnCurrentThread()) {
(...skipping 22 matching lines...) Expand all
113 TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks"); 130 TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks");
114 pending_pump_throttled_tasks_runtime_ = base::TimeTicks(); 131 pending_pump_throttled_tasks_runtime_ = base::TimeTicks();
115 132
116 base::TimeTicks now = tick_clock_->NowTicks(); 133 base::TimeTicks now = tick_clock_->NowTicks();
117 time_domain_->AdvanceTo(now); 134 time_domain_->AdvanceTo(now);
118 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) { 135 for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
119 TaskQueue* task_queue = map_entry.first; 136 TaskQueue* task_queue = map_entry.first;
120 if (task_queue->IsEmpty()) 137 if (task_queue->IsEmpty())
121 continue; 138 continue;
122 139
123 task_queue->SetQueueEnabled(true); 140 task_queue->SetQueueEnabled(map_entry.second.enabled);
Sami 2016/05/31 18:11:04 Mind adding a DCHECK here that makes sure the enab
alex clarke (OOO till 29th) 2016/06/02 13:51:05 This in principle is a good idea, but due to the w
124 task_queue->PumpQueue(false); 141 task_queue->PumpQueue(false);
125 } 142 }
126 // Make sure NextScheduledRunTime gives us an up-to date result. 143 // Make sure NextScheduledRunTime gives us an up-to date result.
127 time_domain_->ClearExpiredWakeups(); 144 time_domain_->ClearExpiredWakeups();
128 145
129 base::TimeTicks next_scheduled_delayed_task; 146 base::TimeTicks next_scheduled_delayed_task;
130 // Maybe schedule a call to ThrottlingHelper::PumpThrottledTasks if there is 147 // Maybe schedule a call to ThrottlingHelper::PumpThrottledTasks if there is
131 // a pending delayed task. NOTE posting a non-delayed task in the future will 148 // a pending delayed task. NOTE posting a non-delayed task in the future will
132 // result in ThrottlingHelper::OnTimeDomainHasImmediateWork being called. 149 // result in ThrottlingHelper::OnTimeDomainHasImmediateWork being called.
133 if (time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task)) { 150 if (time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task)) {
(...skipping 29 matching lines...) Expand all
163 180
164 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_ - now; 181 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_ - now;
165 TRACE_EVENT1(tracing_category_, 182 TRACE_EVENT1(tracing_category_,
166 "ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked", 183 "ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked",
167 "delay_till_next_pump_ms", delay.InMilliseconds()); 184 "delay_till_next_pump_ms", delay.InMilliseconds());
168 task_runner_->PostDelayedTask( 185 task_runner_->PostDelayedTask(
169 from_here, suspend_timers_when_backgrounded_closure_.callback(), delay); 186 from_here, suspend_timers_when_backgrounded_closure_.callback(), delay);
170 } 187 }
171 188
172 } // namespace scheduler 189 } // namespace scheduler
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698