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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc

Issue 2276353002: Remove after wakeup logic and replace PumpTask with Fences (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make TestLongIdlePeriodTimeline test quiescence again! Created 4 years, 3 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 "platform/scheduler/child/idle_helper.h" 5 #include "platform/scheduler/child/idle_helper.h"
6 6
7 #include "base/time/time.h" 7 #include "base/time/time.h"
8 #include "base/trace_event/trace_event.h" 8 #include "base/trace_event/trace_event.h"
9 #include "base/trace_event/trace_event_argument.h" 9 #include "base/trace_event/trace_event_argument.h"
10 #include "platform/scheduler/base/real_time_domain.h" 10 #include "platform/scheduler/base/real_time_domain.h"
11 #include "public/platform/scheduler/base/task_queue.h" 11 #include "public/platform/scheduler/base/task_queue.h"
12 #include "platform/scheduler/base/task_queue_manager.h" 12 #include "platform/scheduler/base/task_queue_manager.h"
13 #include "platform/scheduler/child/scheduler_helper.h" 13 #include "platform/scheduler/child/scheduler_helper.h"
14 #include "platform/scheduler/child/scheduler_tqm_delegate.h" 14 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
15 15
16 namespace blink { 16 namespace blink {
17 namespace scheduler { 17 namespace scheduler {
18 18
19 IdleHelper::IdleHelper( 19 IdleHelper::IdleHelper(
20 SchedulerHelper* helper, 20 SchedulerHelper* helper,
21 Delegate* delegate, 21 Delegate* delegate,
22 const char* tracing_category, 22 const char* tracing_category,
23 const char* disabled_by_default_tracing_category, 23 const char* disabled_by_default_tracing_category,
24 const char* idle_period_tracing_name, 24 const char* idle_period_tracing_name,
25 base::TimeDelta required_quiescence_duration_before_long_idle_period) 25 base::TimeDelta required_quiescence_duration_before_long_idle_period)
26 : helper_(helper), 26 : helper_(helper),
27 delegate_(delegate), 27 delegate_(delegate),
28 idle_queue_( 28 idle_queue_(helper_->NewTaskQueue(TaskQueue::Spec("idle_tq"))),
29 helper_->NewTaskQueue(TaskQueue::Spec("idle_tq").SetPumpPolicy( 29 non_nestable_idle_queue_(
30 TaskQueue::PumpPolicy::MANUAL))), 30 helper_->NewTaskQueue(TaskQueue::Spec("non_nestable_idle_tq"))),
31 state_(helper, 31 state_(helper,
32 delegate, 32 delegate,
33 tracing_category, 33 tracing_category,
34 disabled_by_default_tracing_category, 34 disabled_by_default_tracing_category,
35 idle_period_tracing_name), 35 idle_period_tracing_name),
36 required_quiescence_duration_before_long_idle_period_( 36 required_quiescence_duration_before_long_idle_period_(
37 required_quiescence_duration_before_long_idle_period), 37 required_quiescence_duration_before_long_idle_period),
38 disabled_by_default_tracing_category_( 38 disabled_by_default_tracing_category_(
39 disabled_by_default_tracing_category), 39 disabled_by_default_tracing_category),
40 weak_factory_(this) { 40 weak_factory_(this) {
41 weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr(); 41 weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr();
42 enable_next_long_idle_period_closure_.Reset( 42 enable_next_long_idle_period_closure_.Reset(
43 base::Bind(&IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_)); 43 base::Bind(&IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_));
44 on_idle_task_posted_closure_.Reset(base::Bind( 44 on_idle_task_posted_closure_.Reset(base::Bind(
45 &IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_)); 45 &IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_));
46 disable_idle_queue_closure_.Reset(
47 base::Bind(&IdleHelper::DisableIdleTaskQueueTask, weak_idle_helper_ptr_));
48 disable_non_nestable_idle_queue_closure_.Reset(base::Bind(
49 &IdleHelper::DisableNonNestableIdleTaskQueueTask, weak_idle_helper_ptr_));
46 50
47 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( 51 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner(
48 idle_queue_, helper_->ControlAfterWakeUpTaskRunner(), this, 52 idle_queue_, non_nestable_idle_queue_, this, tracing_category));
49 tracing_category));
50 53
51 idle_queue_->SetQueueEnabled(false); 54 idle_queue_->SetQueueEnabled(false);
52 idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY); 55 idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY);
56 non_nestable_idle_queue_->SetQueueEnabled(false);
57 non_nestable_idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY);
53 58
54 helper_->AddTaskObserver(this); 59 helper_->AddTaskObserver(this);
55 } 60 }
56 61
57 IdleHelper::~IdleHelper() { 62 IdleHelper::~IdleHelper() {
58 helper_->RemoveTaskObserver(this); 63 helper_->RemoveTaskObserver(this);
59 } 64 }
60 65
61 IdleHelper::Delegate::Delegate() {} 66 IdleHelper::Delegate::Delegate() {}
62 67
63 IdleHelper::Delegate::~Delegate() {} 68 IdleHelper::Delegate::~Delegate() {}
64 69
70 void IdleHelper::DisableIdleTaskQueueTask() {
71 idle_queue_->SetQueueEnabled(false);
72 if (IsInLongIdlePeriod(state_.idle_period_state())) {
73 UpdateLongIdlePeriodStateAfterIdleTask();
74 }
75 }
76
77 void IdleHelper::DisableNonNestableIdleTaskQueueTask() {
78 non_nestable_idle_queue_->SetQueueEnabled(false);
79 if (IsInLongIdlePeriod(state_.idle_period_state())) {
80 UpdateLongIdlePeriodStateAfterIdleTask();
81 }
82 }
83
65 scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() { 84 scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() {
66 helper_->CheckOnValidThread(); 85 helper_->CheckOnValidThread();
67 return idle_task_runner_; 86 return idle_task_runner_;
68 } 87 }
69 88
70 IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState( 89 IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState(
71 const base::TimeTicks now, 90 const base::TimeTicks now,
72 base::TimeDelta* next_long_idle_period_delay_out) { 91 base::TimeDelta* next_long_idle_period_delay_out) {
73 helper_->CheckOnValidThread(); 92 helper_->CheckOnValidThread();
74 93
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 127 }
109 } 128 }
110 129
111 bool IdleHelper::ShouldWaitForQuiescence() { 130 bool IdleHelper::ShouldWaitForQuiescence() {
112 helper_->CheckOnValidThread(); 131 helper_->CheckOnValidThread();
113 132
114 if (helper_->IsShutdown()) 133 if (helper_->IsShutdown())
115 return false; 134 return false;
116 135
117 if (required_quiescence_duration_before_long_idle_period_ == 136 if (required_quiescence_duration_before_long_idle_period_ ==
118 base::TimeDelta()) 137 base::TimeDelta()) {
119 return false; 138 return false;
139 }
120 140
121 bool system_is_quiescent = helper_->GetAndClearSystemIsQuiescentBit(); 141 bool system_is_quiescent = helper_->GetAndClearSystemIsQuiescentBit();
122 TRACE_EVENT1(disabled_by_default_tracing_category_, "ShouldWaitForQuiescence", 142 TRACE_EVENT1(disabled_by_default_tracing_category_, "ShouldWaitForQuiescence",
123 "system_is_quiescent", system_is_quiescent); 143 "system_is_quiescent", system_is_quiescent);
124 return !system_is_quiescent; 144 return !system_is_quiescent;
125 } 145 }
126 146
127 void IdleHelper::EnableLongIdlePeriod() { 147 void IdleHelper::EnableLongIdlePeriod() {
128 TRACE_EVENT0(disabled_by_default_tracing_category_, "EnableLongIdlePeriod"); 148 TRACE_EVENT0(disabled_by_default_tracing_category_, "EnableLongIdlePeriod");
129 helper_->CheckOnValidThread(); 149 helper_->CheckOnValidThread();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 if (idle_period_duration < 187 if (idle_period_duration <
168 base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) { 188 base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
169 TRACE_EVENT1(disabled_by_default_tracing_category_, 189 TRACE_EVENT1(disabled_by_default_tracing_category_,
170 "NotStartingIdlePeriodBecauseDeadlineIsTooClose", 190 "NotStartingIdlePeriodBecauseDeadlineIsTooClose",
171 "idle_period_duration_ms", 191 "idle_period_duration_ms",
172 idle_period_duration.InMillisecondsF()); 192 idle_period_duration.InMillisecondsF());
173 return; 193 return;
174 } 194 }
175 195
176 TRACE_EVENT0(disabled_by_default_tracing_category_, "StartIdlePeriod"); 196 TRACE_EVENT0(disabled_by_default_tracing_category_, "StartIdlePeriod");
177 idle_queue_->SetQueueEnabled(true); 197
178 LazyNow lazy_now(now); 198 // Make sure any idle tasks poster after this do not run until the next idle
179 idle_queue_->PumpQueue(&lazy_now, true); 199 // period. With nested message loops it's possible there are pending disable
200 // tasks, we don't want that so cancel them.
201 disable_idle_queue_closure_.Cancel();
202 disable_non_nestable_idle_queue_closure_.Cancel();
203 if (idle_queue_->HasPendingImmediateWork()) {
204 idle_queue_->PostTask(FROM_HERE, disable_idle_queue_closure_.callback());
Sami 2016/08/25 15:54:12 I wonder if this could have a failure mode where w
alex clarke (OOO till 29th) 2016/08/26 13:29:08 I've replaced this mechanism with something akin t
205 idle_queue_->SetQueueEnabled(true);
206 }
207 if (non_nestable_idle_queue_->HasPendingImmediateWork()) {
208 non_nestable_idle_queue_->PostNonNestableTask(
209 FROM_HERE, disable_non_nestable_idle_queue_closure_.callback());
210 non_nestable_idle_queue_->SetQueueEnabled(true);
211 }
180 212
181 state_.UpdateState(new_state, idle_period_deadline, now); 213 state_.UpdateState(new_state, idle_period_deadline, now);
182 } 214 }
183 215
184 void IdleHelper::EndIdlePeriod() { 216 void IdleHelper::EndIdlePeriod() {
185 helper_->CheckOnValidThread(); 217 helper_->CheckOnValidThread();
186 TRACE_EVENT0(disabled_by_default_tracing_category_, "EndIdlePeriod"); 218 TRACE_EVENT0(disabled_by_default_tracing_category_, "EndIdlePeriod");
187 219
188 enable_next_long_idle_period_closure_.Cancel(); 220 enable_next_long_idle_period_closure_.Cancel();
189 on_idle_task_posted_closure_.Cancel(); 221 on_idle_task_posted_closure_.Cancel();
190 222
191 // If we weren't already within an idle period then early-out. 223 // If we weren't already within an idle period then early-out.
192 if (!IsInIdlePeriod(state_.idle_period_state())) 224 if (!IsInIdlePeriod(state_.idle_period_state()))
193 return; 225 return;
194 226
227 // Cancel any pending calls to disable the idle queues in favor of disabling
228 // now.
229 disable_idle_queue_closure_.Cancel();
Sami 2016/08/25 15:54:13 This means we might not run UpdateLongIdlePeriodSt
alex clarke (OOO till 29th) 2016/08/26 13:29:08 Acknowledged.
230 disable_non_nestable_idle_queue_closure_.Cancel();
195 idle_queue_->SetQueueEnabled(false); 231 idle_queue_->SetQueueEnabled(false);
232 non_nestable_idle_queue_->SetQueueEnabled(false);
196 state_.UpdateState(IdlePeriodState::NOT_IN_IDLE_PERIOD, base::TimeTicks(), 233 state_.UpdateState(IdlePeriodState::NOT_IN_IDLE_PERIOD, base::TimeTicks(),
197 base::TimeTicks()); 234 base::TimeTicks());
198 } 235 }
199 236
200 void IdleHelper::WillProcessTask(const base::PendingTask& pending_task) {} 237 void IdleHelper::WillProcessTask(const base::PendingTask& pending_task) {}
201 238
202 void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) { 239 void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) {
203 helper_->CheckOnValidThread(); 240 helper_->CheckOnValidThread();
204 TRACE_EVENT0(disabled_by_default_tracing_category_, "DidProcessTask"); 241 TRACE_EVENT0(disabled_by_default_tracing_category_, "DidProcessTask");
205 if (IsInIdlePeriod(state_.idle_period_state()) && 242 if (IsInIdlePeriod(state_.idle_period_state()) &&
206 state_.idle_period_state() != 243 state_.idle_period_state() !=
207 IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED && 244 IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED &&
208 helper_->scheduler_tqm_delegate()->NowTicks() >= 245 helper_->scheduler_tqm_delegate()->NowTicks() >=
209 state_.idle_period_deadline()) { 246 state_.idle_period_deadline()) {
210 // If the idle period deadline has now been reached, either end the idle 247 // If the idle period deadline has now been reached, either end the idle
211 // period or trigger a new long-idle period. 248 // period or trigger a new long-idle period.
212 if (IsInLongIdlePeriod(state_.idle_period_state())) { 249 if (IsInLongIdlePeriod(state_.idle_period_state())) {
213 EnableLongIdlePeriod(); 250 EnableLongIdlePeriod();
214 } else { 251 } else {
215 DCHECK(IdlePeriodState::IN_SHORT_IDLE_PERIOD == 252 DCHECK(IdlePeriodState::IN_SHORT_IDLE_PERIOD ==
216 state_.idle_period_state()); 253 state_.idle_period_state());
217 EndIdlePeriod(); 254 EndIdlePeriod();
218 } 255 }
219 } 256 }
220 } 257 }
221 258
222 void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() { 259 void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() {
Sami 2016/08/25 15:54:13 This should probably be renamed since we no longer
alex clarke (OOO till 29th) 2016/08/26 13:29:08 Acknowledged.
223 helper_->CheckOnValidThread(); 260 helper_->CheckOnValidThread();
224 DCHECK(IsInLongIdlePeriod(state_.idle_period_state())); 261 DCHECK(IsInLongIdlePeriod(state_.idle_period_state()));
225 TRACE_EVENT0(disabled_by_default_tracing_category_, 262 TRACE_EVENT0(disabled_by_default_tracing_category_,
226 "UpdateLongIdlePeriodStateAfterIdleTask"); 263 "UpdateLongIdlePeriodStateAfterIdleTask");
227 264
228 if (!idle_queue_->HasPendingImmediateWork()) { 265 if (!idle_queue_->HasPendingImmediateWork()) {
229 // If there are no more idle tasks then pause long idle period ticks until a 266 // If there are no more idle tasks then pause long idle period ticks until a
230 // new idle task is posted. 267 // new idle task is posted.
231 state_.UpdateState(IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED, 268 state_.UpdateState(IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED,
232 state_.idle_period_deadline(), base::TimeTicks()); 269 state_.idle_period_deadline(), base::TimeTicks());
233 } else if (idle_queue_->NeedsPumping()) { 270 } else if (!idle_queue_->IsEmpty()) {
234 // If there is still idle work to do then just start the next idle period. 271 // If there is still idle work to do then just start the next idle period.
235 base::TimeDelta next_long_idle_period_delay; 272 base::TimeDelta next_long_idle_period_delay;
236 if (state_.idle_period_state() == 273 if (state_.idle_period_state() ==
237 IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE) { 274 IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE) {
238 // If we are in a max deadline long idle period then start the next 275 // If we are in a max deadline long idle period then start the next
239 // idle period immediately. 276 // idle period immediately.
240 next_long_idle_period_delay = base::TimeDelta(); 277 next_long_idle_period_delay = base::TimeDelta();
241 } else { 278 } else {
242 // Otherwise ensure that we kick the scheduler at the right time to 279 // Otherwise ensure that we kick the scheduler at the right time to
243 // initiate the next idle period. 280 // initiate the next idle period.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 320
284 base::TimeTicks IdleHelper::WillProcessIdleTask() { 321 base::TimeTicks IdleHelper::WillProcessIdleTask() {
285 helper_->CheckOnValidThread(); 322 helper_->CheckOnValidThread();
286 state_.TraceIdleIdleTaskStart(); 323 state_.TraceIdleIdleTaskStart();
287 return CurrentIdleTaskDeadline(); 324 return CurrentIdleTaskDeadline();
288 } 325 }
289 326
290 void IdleHelper::DidProcessIdleTask() { 327 void IdleHelper::DidProcessIdleTask() {
291 helper_->CheckOnValidThread(); 328 helper_->CheckOnValidThread();
292 state_.TraceIdleIdleTaskEnd(); 329 state_.TraceIdleIdleTaskEnd();
293 if (IsInLongIdlePeriod(state_.idle_period_state())) {
294 UpdateLongIdlePeriodStateAfterIdleTask();
295 }
296 } 330 }
297 331
298 // static 332 // static
299 bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) { 333 bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) {
300 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; 334 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD;
301 } 335 }
302 336
303 // static 337 // static
304 bool IdleHelper::IsInLongIdlePeriod(IdlePeriodState state) { 338 bool IdleHelper::IsInLongIdlePeriod(IdlePeriodState state) {
305 return state == IdlePeriodState::IN_LONG_IDLE_PERIOD || 339 return state == IdlePeriodState::IN_LONG_IDLE_PERIOD ||
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 case IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED: 503 case IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED:
470 return "in_long_idle_period_paused"; 504 return "in_long_idle_period_paused";
471 default: 505 default:
472 NOTREACHED(); 506 NOTREACHED();
473 return nullptr; 507 return nullptr;
474 } 508 }
475 } 509 }
476 510
477 } // namespace scheduler 511 } // namespace scheduler
478 } // namespace blink 512 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698