OLD | NEW |
---|---|
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/child/scheduler_helper.h" | 5 #include "components/scheduler/child/scheduler_helper.h" |
6 | 6 |
7 #include "base/synchronization/waitable_event.h" | |
7 #include "base/trace_event/trace_event.h" | 8 #include "base/trace_event/trace_event.h" |
8 #include "base/trace_event/trace_event_argument.h" | 9 #include "base/trace_event/trace_event_argument.h" |
9 #include "components/scheduler/child/nestable_single_thread_task_runner.h" | 10 #include "components/scheduler/child/nestable_single_thread_task_runner.h" |
10 #include "components/scheduler/child/time_source.h" | 11 #include "components/scheduler/child/time_source.h" |
11 | 12 |
12 namespace scheduler { | 13 namespace scheduler { |
13 | 14 |
14 SchedulerHelper::SchedulerHelper( | 15 SchedulerHelper::SchedulerHelper( |
15 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, | 16 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, |
16 SchedulerHelperDelegate* scheduler_helper_delegate, | 17 SchedulerHelperDelegate* scheduler_helper_delegate, |
17 const char* tracing_category, | 18 const char* tracing_category, |
18 const char* disabled_by_default_tracing_category, | 19 const char* disabled_by_default_tracing_category, |
19 const char* idle_period_tracing_name, | 20 const char* idle_period_tracing_name, |
20 size_t total_task_queue_count, | 21 size_t total_task_queue_count, |
21 base::TimeDelta required_quiescence_duration_before_long_idle_period) | 22 base::TimeDelta required_quiescence_duration_before_long_idle_period) |
22 : task_queue_selector_(new PrioritizingTaskQueueSelector()), | 23 : task_queue_selector_(new PrioritizingTaskQueueSelector()), |
23 task_queue_manager_( | 24 task_queue_manager_( |
24 new TaskQueueManager(total_task_queue_count, | 25 new TaskQueueManager(total_task_queue_count, |
25 main_task_runner, | 26 main_task_runner, |
26 task_queue_selector_.get(), | 27 task_queue_selector_.get(), |
27 disabled_by_default_tracing_category)), | 28 disabled_by_default_tracing_category)), |
28 idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), | 29 idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), |
29 scheduler_helper_delegate_(scheduler_helper_delegate), | 30 scheduler_helper_delegate_(scheduler_helper_delegate), |
30 control_task_runner_( | 31 control_task_runner_( |
31 task_queue_manager_->TaskRunnerForQueue(QueueId::CONTROL_TASK_QUEUE)), | 32 task_queue_manager_->TaskRunnerForQueue(QueueId::CONTROL_TASK_QUEUE)), |
32 control_task_after_wakeup_runner_(task_queue_manager_->TaskRunnerForQueue( | 33 control_task_after_wakeup_runner_(task_queue_manager_->TaskRunnerForQueue( |
33 QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE)), | 34 QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE)), |
34 default_task_runner_( | 35 default_task_runner_( |
35 task_queue_manager_->TaskRunnerForQueue(QueueId::DEFAULT_TASK_QUEUE)), | 36 task_queue_manager_->TaskRunnerForQueue(QueueId::DEFAULT_TASK_QUEUE)), |
37 shutdown_task_runner_(task_queue_manager_->TaskRunnerForQueue( | |
38 QueueId::SHUTDOWN_TASK_QUEUE)), | |
39 total_task_queue_count_(total_task_queue_count), | |
40 in_preshutdown_(false), | |
36 quiescence_monitored_task_queue_mask_( | 41 quiescence_monitored_task_queue_mask_( |
37 ((1ull << total_task_queue_count) - 1ull) & | 42 ((1ull << total_task_queue_count) - 1ull) & |
38 ~(1ull << QueueId::IDLE_TASK_QUEUE) & | 43 ~(1ull << QueueId::IDLE_TASK_QUEUE) & |
39 ~(1ull << QueueId::CONTROL_TASK_QUEUE) & | 44 ~(1ull << QueueId::CONTROL_TASK_QUEUE) & |
40 ~(1ull << QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE)), | 45 ~(1ull << QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE)), |
41 required_quiescence_duration_before_long_idle_period_( | 46 required_quiescence_duration_before_long_idle_period_( |
42 required_quiescence_duration_before_long_idle_period), | 47 required_quiescence_duration_before_long_idle_period), |
43 time_source_(new TimeSource), | 48 time_source_(new TimeSource), |
44 tracing_category_(tracing_category), | 49 tracing_category_(tracing_category), |
45 disabled_by_default_tracing_category_( | 50 disabled_by_default_tracing_category_( |
(...skipping 10 matching lines...) Expand all Loading... | |
56 enable_next_long_idle_period_after_wakeup_closure_.Reset(base::Bind( | 61 enable_next_long_idle_period_after_wakeup_closure_.Reset(base::Bind( |
57 &SchedulerHelper::EnableLongIdlePeriodAfterWakeup, weak_scheduler_ptr_)); | 62 &SchedulerHelper::EnableLongIdlePeriodAfterWakeup, weak_scheduler_ptr_)); |
58 | 63 |
59 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( | 64 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
60 task_queue_manager_->TaskRunnerForQueue(QueueId::IDLE_TASK_QUEUE), | 65 task_queue_manager_->TaskRunnerForQueue(QueueId::IDLE_TASK_QUEUE), |
61 control_task_after_wakeup_runner_, | 66 control_task_after_wakeup_runner_, |
62 base::Bind(&SchedulerHelper::CurrentIdleTaskDeadlineCallback, | 67 base::Bind(&SchedulerHelper::CurrentIdleTaskDeadlineCallback, |
63 weak_scheduler_ptr_), | 68 weak_scheduler_ptr_), |
64 tracing_category)); | 69 tracing_category)); |
65 | 70 |
66 task_queue_selector_->SetQueuePriority( | 71 SetQueuePriority(QueueId::CONTROL_TASK_QUEUE, |
67 QueueId::CONTROL_TASK_QUEUE, | 72 PrioritizingTaskQueueSelector::CONTROL_PRIORITY); |
68 PrioritizingTaskQueueSelector::CONTROL_PRIORITY); | |
69 | 73 |
70 task_queue_selector_->SetQueuePriority( | 74 SetQueuePriority(QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE, |
71 QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE, | 75 PrioritizingTaskQueueSelector::CONTROL_PRIORITY); |
72 PrioritizingTaskQueueSelector::CONTROL_PRIORITY); | |
73 task_queue_manager_->SetPumpPolicy( | 76 task_queue_manager_->SetPumpPolicy( |
74 QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE, | 77 QueueId::CONTROL_TASK_AFTER_WAKEUP_QUEUE, |
75 TaskQueueManager::PumpPolicy::AFTER_WAKEUP); | 78 TaskQueueManager::PumpPolicy::AFTER_WAKEUP); |
76 | 79 |
77 task_queue_selector_->DisableQueue(QueueId::IDLE_TASK_QUEUE); | 80 DisableQueue(QueueId::IDLE_TASK_QUEUE); |
78 task_queue_manager_->SetPumpPolicy(QueueId::IDLE_TASK_QUEUE, | 81 task_queue_manager_->SetPumpPolicy(QueueId::IDLE_TASK_QUEUE, |
79 TaskQueueManager::PumpPolicy::MANUAL); | 82 TaskQueueManager::PumpPolicy::MANUAL); |
80 | 83 |
81 for (size_t i = 0; i < TASK_QUEUE_COUNT; i++) { | 84 for (size_t i = 0; i < TASK_QUEUE_COUNT; i++) { |
82 task_queue_manager_->SetQueueName( | 85 task_queue_manager_->SetQueueName( |
83 i, TaskQueueIdToString(static_cast<QueueId>(i))); | 86 i, TaskQueueIdToString(static_cast<QueueId>(i))); |
84 } | 87 } |
85 | 88 |
86 // TODO(skyostil): Increase this to 4 (crbug.com/444764). | 89 // TODO(skyostil): Increase this to 4 (crbug.com/444764). |
87 task_queue_manager_->SetWorkBatchSize(1); | 90 task_queue_manager_->SetWorkBatchSize(1); |
88 } | 91 } |
89 | 92 |
90 SchedulerHelper::~SchedulerHelper() { | 93 SchedulerHelper::~SchedulerHelper() { |
91 } | 94 } |
92 | 95 |
93 SchedulerHelper::SchedulerHelperDelegate::SchedulerHelperDelegate() { | 96 SchedulerHelper::SchedulerHelperDelegate::SchedulerHelperDelegate() { |
94 } | 97 } |
95 | 98 |
96 SchedulerHelper::SchedulerHelperDelegate::~SchedulerHelperDelegate() { | 99 SchedulerHelper::SchedulerHelperDelegate::~SchedulerHelperDelegate() { |
97 } | 100 } |
98 | 101 |
102 void SchedulerHelper::PreShutdown() { | |
103 CheckOnValidThread(); | |
104 DCHECK(!in_preshutdown_); | |
105 TRACE_EVENT0(disabled_by_default_tracing_category_, "PreShutdown"); | |
106 // Disable everything except the control and shutdown task queues. | |
107 for (size_t i = 0; i < total_task_queue_count_; i++) { | |
108 if (i == CONTROL_TASK_QUEUE || i == SHUTDOWN_TASK_QUEUE) | |
rmcilroy
2015/04/28 09:51:09
I'm wondering whether we even need the control tas
Sami
2015/04/28 11:52:46
I thought Alex originally made kept the control qu
| |
109 continue; | |
110 DisableQueue(i); | |
111 } | |
112 // Ensure that the queues don't get re-enabled. | |
113 in_preshutdown_ = true; | |
114 } | |
115 | |
99 void SchedulerHelper::Shutdown() { | 116 void SchedulerHelper::Shutdown() { |
100 CheckOnValidThread(); | 117 CheckOnValidThread(); |
101 task_queue_manager_.reset(); | 118 task_queue_manager_.reset(); |
102 } | 119 } |
103 | 120 |
104 scoped_refptr<base::SingleThreadTaskRunner> | 121 scoped_refptr<base::SingleThreadTaskRunner> |
105 SchedulerHelper::DefaultTaskRunner() { | 122 SchedulerHelper::DefaultTaskRunner() { |
106 CheckOnValidThread(); | 123 CheckOnValidThread(); |
107 return default_task_runner_; | 124 return default_task_runner_; |
108 } | 125 } |
109 | 126 |
110 scoped_refptr<SingleThreadIdleTaskRunner> SchedulerHelper::IdleTaskRunner() { | 127 scoped_refptr<SingleThreadIdleTaskRunner> SchedulerHelper::IdleTaskRunner() { |
111 CheckOnValidThread(); | 128 CheckOnValidThread(); |
112 return idle_task_runner_; | 129 return idle_task_runner_; |
113 } | 130 } |
114 | 131 |
115 scoped_refptr<base::SingleThreadTaskRunner> | 132 scoped_refptr<base::SingleThreadTaskRunner> |
133 SchedulerHelper::ShutdownTaskRunner() { | |
134 return shutdown_task_runner_; | |
135 } | |
136 | |
137 scoped_refptr<base::SingleThreadTaskRunner> | |
116 SchedulerHelper::ControlTaskRunner() { | 138 SchedulerHelper::ControlTaskRunner() { |
117 return control_task_runner_; | 139 return control_task_runner_; |
118 } | 140 } |
119 | 141 |
120 void SchedulerHelper::CurrentIdleTaskDeadlineCallback( | 142 void SchedulerHelper::CurrentIdleTaskDeadlineCallback( |
121 base::TimeTicks* deadline_out) const { | 143 base::TimeTicks* deadline_out) const { |
122 CheckOnValidThread(); | 144 CheckOnValidThread(); |
123 *deadline_out = idle_period_deadline_; | 145 *deadline_out = idle_period_deadline_; |
124 } | 146 } |
125 | 147 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 | 269 |
248 void SchedulerHelper::StartIdlePeriod(IdlePeriodState new_state, | 270 void SchedulerHelper::StartIdlePeriod(IdlePeriodState new_state, |
249 base::TimeTicks now, | 271 base::TimeTicks now, |
250 base::TimeTicks idle_period_deadline, | 272 base::TimeTicks idle_period_deadline, |
251 bool post_end_idle_period) { | 273 bool post_end_idle_period) { |
252 DCHECK_GT(idle_period_deadline, now); | 274 DCHECK_GT(idle_period_deadline, now); |
253 TRACE_EVENT_ASYNC_BEGIN0(tracing_category_, idle_period_tracing_name_, this); | 275 TRACE_EVENT_ASYNC_BEGIN0(tracing_category_, idle_period_tracing_name_, this); |
254 CheckOnValidThread(); | 276 CheckOnValidThread(); |
255 DCHECK(IsInIdlePeriod(new_state)); | 277 DCHECK(IsInIdlePeriod(new_state)); |
256 | 278 |
257 task_queue_selector_->EnableQueue( | 279 EnableQueue(QueueId::IDLE_TASK_QUEUE, |
258 QueueId::IDLE_TASK_QUEUE, | 280 PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY); |
259 PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY); | |
260 task_queue_manager_->PumpQueue(QueueId::IDLE_TASK_QUEUE); | 281 task_queue_manager_->PumpQueue(QueueId::IDLE_TASK_QUEUE); |
261 idle_period_state_ = new_state; | 282 idle_period_state_ = new_state; |
262 | 283 |
263 idle_period_deadline_ = idle_period_deadline; | 284 idle_period_deadline_ = idle_period_deadline; |
264 if (post_end_idle_period) { | 285 if (post_end_idle_period) { |
265 control_task_runner_->PostDelayedTask(FROM_HERE, | 286 control_task_runner_->PostDelayedTask(FROM_HERE, |
266 end_idle_period_closure_.callback(), | 287 end_idle_period_closure_.callback(), |
267 idle_period_deadline_ - now); | 288 idle_period_deadline_ - now); |
268 } | 289 } |
269 } | 290 } |
(...skipping 16 matching lines...) Expand all Loading... | |
286 TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); | 307 TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); |
287 if (is_tracing && !idle_period_deadline_.is_null() && | 308 if (is_tracing && !idle_period_deadline_.is_null() && |
288 base::TimeTicks::Now() > idle_period_deadline_) { | 309 base::TimeTicks::Now() > idle_period_deadline_) { |
289 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( | 310 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( |
290 tracing_category_, idle_period_tracing_name_, this, "DeadlineOverrun", | 311 tracing_category_, idle_period_tracing_name_, this, "DeadlineOverrun", |
291 idle_period_deadline_.ToInternalValue()); | 312 idle_period_deadline_.ToInternalValue()); |
292 } | 313 } |
293 TRACE_EVENT_ASYNC_END0(tracing_category_, idle_period_tracing_name_, this); | 314 TRACE_EVENT_ASYNC_END0(tracing_category_, idle_period_tracing_name_, this); |
294 } | 315 } |
295 | 316 |
296 task_queue_selector_->DisableQueue(QueueId::IDLE_TASK_QUEUE); | 317 DisableQueue(QueueId::IDLE_TASK_QUEUE); |
297 idle_period_state_ = IdlePeriodState::NOT_IN_IDLE_PERIOD; | 318 idle_period_state_ = IdlePeriodState::NOT_IN_IDLE_PERIOD; |
298 idle_period_deadline_ = base::TimeTicks(); | 319 idle_period_deadline_ = base::TimeTicks(); |
299 } | 320 } |
300 | 321 |
301 // static | 322 // static |
302 bool SchedulerHelper::IsInIdlePeriod(IdlePeriodState state) { | 323 bool SchedulerHelper::IsInIdlePeriod(IdlePeriodState state) { |
303 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; | 324 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; |
304 } | 325 } |
305 | 326 |
306 bool SchedulerHelper::CanExceedIdleDeadlineIfRequired() const { | 327 bool SchedulerHelper::CanExceedIdleDeadlineIfRequired() const { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 | 369 |
349 bool SchedulerHelper::IsQueueEmpty(size_t queue_index) const { | 370 bool SchedulerHelper::IsQueueEmpty(size_t queue_index) const { |
350 CheckOnValidThread(); | 371 CheckOnValidThread(); |
351 return task_queue_manager_->IsQueueEmpty(queue_index); | 372 return task_queue_manager_->IsQueueEmpty(queue_index); |
352 } | 373 } |
353 | 374 |
354 void SchedulerHelper::SetQueuePriority( | 375 void SchedulerHelper::SetQueuePriority( |
355 size_t queue_index, | 376 size_t queue_index, |
356 PrioritizingTaskQueueSelector::QueuePriority priority) { | 377 PrioritizingTaskQueueSelector::QueuePriority priority) { |
357 CheckOnValidThread(); | 378 CheckOnValidThread(); |
379 if (in_preshutdown_) | |
380 return; | |
358 return task_queue_selector_->SetQueuePriority(queue_index, priority); | 381 return task_queue_selector_->SetQueuePriority(queue_index, priority); |
359 } | 382 } |
360 | 383 |
361 void SchedulerHelper::EnableQueue( | 384 void SchedulerHelper::EnableQueue( |
362 size_t queue_index, | 385 size_t queue_index, |
363 PrioritizingTaskQueueSelector::QueuePriority priority) { | 386 PrioritizingTaskQueueSelector::QueuePriority priority) { |
364 CheckOnValidThread(); | 387 CheckOnValidThread(); |
388 if (in_preshutdown_) | |
389 return; | |
365 task_queue_selector_->EnableQueue(queue_index, priority); | 390 task_queue_selector_->EnableQueue(queue_index, priority); |
366 } | 391 } |
367 | 392 |
368 void SchedulerHelper::DisableQueue(size_t queue_index) { | 393 void SchedulerHelper::DisableQueue(size_t queue_index) { |
369 CheckOnValidThread(); | 394 CheckOnValidThread(); |
395 if (in_preshutdown_) | |
396 return; | |
370 task_queue_selector_->DisableQueue(queue_index); | 397 task_queue_selector_->DisableQueue(queue_index); |
371 } | 398 } |
372 | 399 |
373 bool SchedulerHelper::IsQueueEnabled(size_t queue_index) const { | 400 bool SchedulerHelper::IsQueueEnabled(size_t queue_index) const { |
374 CheckOnValidThread(); | 401 CheckOnValidThread(); |
375 return task_queue_selector_->IsQueueEnabled(queue_index); | 402 return task_queue_selector_->IsQueueEnabled(queue_index); |
376 } | 403 } |
377 | 404 |
378 // static | 405 // static |
379 const char* SchedulerHelper::TaskQueueIdToString(QueueId queue_id) { | 406 const char* SchedulerHelper::TaskQueueIdToString(QueueId queue_id) { |
380 switch (queue_id) { | 407 switch (queue_id) { |
381 case DEFAULT_TASK_QUEUE: | 408 case DEFAULT_TASK_QUEUE: |
382 return "default_tq"; | 409 return "default_tq"; |
383 case IDLE_TASK_QUEUE: | 410 case IDLE_TASK_QUEUE: |
384 return "idle_tq"; | 411 return "idle_tq"; |
412 case SHUTDOWN_TASK_QUEUE: | |
413 return "shutdown_tq"; | |
385 case CONTROL_TASK_QUEUE: | 414 case CONTROL_TASK_QUEUE: |
386 return "control_tq"; | 415 return "control_tq"; |
387 case CONTROL_TASK_AFTER_WAKEUP_QUEUE: | 416 case CONTROL_TASK_AFTER_WAKEUP_QUEUE: |
388 return "control_after_wakeup_tq"; | 417 return "control_after_wakeup_tq"; |
389 default: | 418 default: |
390 NOTREACHED(); | 419 NOTREACHED(); |
391 return nullptr; | 420 return nullptr; |
392 } | 421 } |
393 } | 422 } |
394 | 423 |
(...skipping 25 matching lines...) Expand all Loading... | |
420 } | 449 } |
421 | 450 |
422 void SchedulerHelper::RemoveTaskObserver( | 451 void SchedulerHelper::RemoveTaskObserver( |
423 base::MessageLoop::TaskObserver* task_observer) { | 452 base::MessageLoop::TaskObserver* task_observer) { |
424 CheckOnValidThread(); | 453 CheckOnValidThread(); |
425 if (task_queue_manager_) | 454 if (task_queue_manager_) |
426 task_queue_manager_->RemoveTaskObserver(task_observer); | 455 task_queue_manager_->RemoveTaskObserver(task_observer); |
427 } | 456 } |
428 | 457 |
429 } // namespace scheduler | 458 } // namespace scheduler |
OLD | NEW |