| 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 shutdown task queue. |
| 107 for (size_t i = 0; i < total_task_queue_count_; i++) { |
| 108 if (i == SHUTDOWN_TASK_QUEUE) |
| 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 |