Index: components/scheduler/child/idle_helper.cc |
diff --git a/components/scheduler/child/idle_helper.cc b/components/scheduler/child/idle_helper.cc |
deleted file mode 100644 |
index 0f6c82f6ac862f60b84045be223a6dbcbdc8a80b..0000000000000000000000000000000000000000 |
--- a/components/scheduler/child/idle_helper.cc |
+++ /dev/null |
@@ -1,486 +0,0 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "components/scheduler/child/idle_helper.h" |
- |
-#include "base/time/time.h" |
-#include "base/trace_event/trace_event.h" |
-#include "base/trace_event/trace_event_argument.h" |
-#include "components/scheduler/base/real_time_domain.h" |
-#include "components/scheduler/base/task_queue.h" |
-#include "components/scheduler/base/task_queue_manager.h" |
-#include "components/scheduler/child/scheduler_helper.h" |
-#include "components/scheduler/child/scheduler_tqm_delegate.h" |
- |
-namespace scheduler { |
- |
-IdleHelper::IdleHelper( |
- SchedulerHelper* helper, |
- Delegate* delegate, |
- const char* tracing_category, |
- const char* disabled_by_default_tracing_category, |
- const char* idle_period_tracing_name, |
- base::TimeDelta required_quiescence_duration_before_long_idle_period) |
- : helper_(helper), |
- delegate_(delegate), |
- idle_queue_( |
- helper_->NewTaskQueue(TaskQueue::Spec("idle_tq").SetPumpPolicy( |
- TaskQueue::PumpPolicy::MANUAL))), |
- state_(helper, |
- delegate, |
- tracing_category, |
- disabled_by_default_tracing_category, |
- idle_period_tracing_name), |
- required_quiescence_duration_before_long_idle_period_( |
- required_quiescence_duration_before_long_idle_period), |
- disabled_by_default_tracing_category_( |
- disabled_by_default_tracing_category), |
- weak_factory_(this) { |
- weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr(); |
- enable_next_long_idle_period_closure_.Reset( |
- base::Bind(&IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_)); |
- on_idle_task_posted_closure_.Reset(base::Bind( |
- &IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_)); |
- |
- idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
- idle_queue_, helper_->ControlAfterWakeUpTaskRunner(), this, |
- tracing_category)); |
- |
- idle_queue_->SetQueueEnabled(false); |
- idle_queue_->SetQueuePriority(TaskQueue::BEST_EFFORT_PRIORITY); |
- |
- helper_->AddTaskObserver(this); |
-} |
- |
-IdleHelper::~IdleHelper() { |
- helper_->RemoveTaskObserver(this); |
-} |
- |
-IdleHelper::Delegate::Delegate() { |
-} |
- |
-IdleHelper::Delegate::~Delegate() { |
-} |
- |
-scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() { |
- helper_->CheckOnValidThread(); |
- return idle_task_runner_; |
-} |
- |
-IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState( |
- const base::TimeTicks now, |
- base::TimeDelta* next_long_idle_period_delay_out) { |
- helper_->CheckOnValidThread(); |
- |
- if (!delegate_->CanEnterLongIdlePeriod(now, |
- next_long_idle_period_delay_out)) { |
- return IdlePeriodState::NOT_IN_IDLE_PERIOD; |
- } |
- |
- base::TimeTicks next_pending_delayed_task; |
- base::TimeDelta max_long_idle_period_duration = |
- base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis); |
- base::TimeDelta long_idle_period_duration; |
- if (helper_->real_time_domain()->NextScheduledRunTime( |
- &next_pending_delayed_task)) { |
- // Limit the idle period duration to be before the next pending task. |
- long_idle_period_duration = std::min(next_pending_delayed_task - now, |
- max_long_idle_period_duration); |
- } else { |
- long_idle_period_duration = max_long_idle_period_duration; |
- } |
- |
- if (long_idle_period_duration >= |
- base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) { |
- *next_long_idle_period_delay_out = long_idle_period_duration; |
- if (!idle_queue_->HasPendingImmediateWork()) { |
- return IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED; |
- } else if (long_idle_period_duration == max_long_idle_period_duration) { |
- return IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE; |
- } else { |
- return IdlePeriodState::IN_LONG_IDLE_PERIOD; |
- } |
- } else { |
- // If we can't start the idle period yet then try again after wakeup. |
- *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds( |
- kRetryEnableLongIdlePeriodDelayMillis); |
- return IdlePeriodState::NOT_IN_IDLE_PERIOD; |
- } |
-} |
- |
-bool IdleHelper::ShouldWaitForQuiescence() { |
- helper_->CheckOnValidThread(); |
- |
- if (helper_->IsShutdown()) |
- return false; |
- |
- if (required_quiescence_duration_before_long_idle_period_ == |
- base::TimeDelta()) |
- return false; |
- |
- bool system_is_quiescent = helper_->GetAndClearSystemIsQuiescentBit(); |
- TRACE_EVENT1(disabled_by_default_tracing_category_, "ShouldWaitForQuiescence", |
- "system_is_quiescent", system_is_quiescent); |
- return !system_is_quiescent; |
-} |
- |
-void IdleHelper::EnableLongIdlePeriod() { |
- TRACE_EVENT0(disabled_by_default_tracing_category_, "EnableLongIdlePeriod"); |
- helper_->CheckOnValidThread(); |
- if (helper_->IsShutdown()) |
- return; |
- |
- // End any previous idle period. |
- EndIdlePeriod(); |
- |
- if (ShouldWaitForQuiescence()) { |
- helper_->ControlTaskRunner()->PostDelayedTask( |
- FROM_HERE, enable_next_long_idle_period_closure_.callback(), |
- required_quiescence_duration_before_long_idle_period_); |
- delegate_->IsNotQuiescent(); |
- return; |
- } |
- |
- base::TimeTicks now(helper_->scheduler_tqm_delegate()->NowTicks()); |
- base::TimeDelta next_long_idle_period_delay; |
- IdlePeriodState new_idle_period_state = |
- ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay); |
- if (IsInIdlePeriod(new_idle_period_state)) { |
- StartIdlePeriod(new_idle_period_state, now, |
- now + next_long_idle_period_delay); |
- } else { |
- // Otherwise wait for the next long idle period delay before trying again. |
- helper_->ControlTaskRunner()->PostDelayedTask( |
- FROM_HERE, enable_next_long_idle_period_closure_.callback(), |
- next_long_idle_period_delay); |
- } |
-} |
- |
-void IdleHelper::StartIdlePeriod(IdlePeriodState new_state, |
- base::TimeTicks now, |
- base::TimeTicks idle_period_deadline) { |
- DCHECK_GT(idle_period_deadline, now); |
- helper_->CheckOnValidThread(); |
- DCHECK(IsInIdlePeriod(new_state)); |
- |
- base::TimeDelta idle_period_duration(idle_period_deadline - now); |
- if (idle_period_duration < |
- base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) { |
- TRACE_EVENT1(disabled_by_default_tracing_category_, |
- "NotStartingIdlePeriodBecauseDeadlineIsTooClose", |
- "idle_period_duration_ms", |
- idle_period_duration.InMillisecondsF()); |
- return; |
- } |
- |
- TRACE_EVENT0(disabled_by_default_tracing_category_, "StartIdlePeriod"); |
- idle_queue_->SetQueueEnabled(true); |
- LazyNow lazy_now(now); |
- idle_queue_->PumpQueue(&lazy_now, true); |
- |
- state_.UpdateState(new_state, idle_period_deadline, now); |
-} |
- |
-void IdleHelper::EndIdlePeriod() { |
- helper_->CheckOnValidThread(); |
- TRACE_EVENT0(disabled_by_default_tracing_category_, "EndIdlePeriod"); |
- |
- enable_next_long_idle_period_closure_.Cancel(); |
- on_idle_task_posted_closure_.Cancel(); |
- |
- // If we weren't already within an idle period then early-out. |
- if (!IsInIdlePeriod(state_.idle_period_state())) |
- return; |
- |
- idle_queue_->SetQueueEnabled(false); |
- state_.UpdateState(IdlePeriodState::NOT_IN_IDLE_PERIOD, base::TimeTicks(), |
- base::TimeTicks()); |
-} |
- |
-void IdleHelper::WillProcessTask(const base::PendingTask& pending_task) { |
-} |
- |
-void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) { |
- helper_->CheckOnValidThread(); |
- TRACE_EVENT0(disabled_by_default_tracing_category_, "DidProcessTask"); |
- if (IsInIdlePeriod(state_.idle_period_state()) && |
- state_.idle_period_state() != |
- IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED && |
- helper_->scheduler_tqm_delegate()->NowTicks() >= |
- state_.idle_period_deadline()) { |
- // If the idle period deadline has now been reached, either end the idle |
- // period or trigger a new long-idle period. |
- if (IsInLongIdlePeriod(state_.idle_period_state())) { |
- EnableLongIdlePeriod(); |
- } else { |
- DCHECK(IdlePeriodState::IN_SHORT_IDLE_PERIOD == |
- state_.idle_period_state()); |
- EndIdlePeriod(); |
- } |
- } |
-} |
- |
-void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() { |
- helper_->CheckOnValidThread(); |
- DCHECK(IsInLongIdlePeriod(state_.idle_period_state())); |
- TRACE_EVENT0(disabled_by_default_tracing_category_, |
- "UpdateLongIdlePeriodStateAfterIdleTask"); |
- |
- if (!idle_queue_->HasPendingImmediateWork()) { |
- // If there are no more idle tasks then pause long idle period ticks until a |
- // new idle task is posted. |
- state_.UpdateState(IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED, |
- state_.idle_period_deadline(), base::TimeTicks()); |
- } else if (idle_queue_->NeedsPumping()) { |
- // If there is still idle work to do then just start the next idle period. |
- base::TimeDelta next_long_idle_period_delay; |
- if (state_.idle_period_state() == |
- IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE) { |
- // If we are in a max deadline long idle period then start the next |
- // idle period immediately. |
- next_long_idle_period_delay = base::TimeDelta(); |
- } else { |
- // Otherwise ensure that we kick the scheduler at the right time to |
- // initiate the next idle period. |
- next_long_idle_period_delay = std::max( |
- base::TimeDelta(), state_.idle_period_deadline() - |
- helper_->scheduler_tqm_delegate()->NowTicks()); |
- } |
- if (next_long_idle_period_delay.is_zero()) { |
- EnableLongIdlePeriod(); |
- } else { |
- helper_->ControlTaskRunner()->PostDelayedTask( |
- FROM_HERE, enable_next_long_idle_period_closure_.callback(), |
- next_long_idle_period_delay); |
- } |
- } |
-} |
- |
-base::TimeTicks IdleHelper::CurrentIdleTaskDeadline() const { |
- helper_->CheckOnValidThread(); |
- return state_.idle_period_deadline(); |
-} |
- |
-void IdleHelper::OnIdleTaskPosted() { |
- TRACE_EVENT0(disabled_by_default_tracing_category_, "OnIdleTaskPosted"); |
- if (idle_task_runner_->RunsTasksOnCurrentThread()) { |
- OnIdleTaskPostedOnMainThread(); |
- } else { |
- helper_->ControlTaskRunner()->PostTask( |
- FROM_HERE, on_idle_task_posted_closure_.callback()); |
- } |
-} |
- |
-void IdleHelper::OnIdleTaskPostedOnMainThread() { |
- TRACE_EVENT0(disabled_by_default_tracing_category_, |
- "OnIdleTaskPostedOnMainThread"); |
- if (state_.idle_period_state() == |
- IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED) { |
- // Restart long idle period ticks. |
- helper_->ControlTaskRunner()->PostTask( |
- FROM_HERE, enable_next_long_idle_period_closure_.callback()); |
- } |
-} |
- |
-base::TimeTicks IdleHelper::WillProcessIdleTask() { |
- helper_->CheckOnValidThread(); |
- state_.TraceIdleIdleTaskStart(); |
- return CurrentIdleTaskDeadline(); |
-} |
- |
-void IdleHelper::DidProcessIdleTask() { |
- helper_->CheckOnValidThread(); |
- state_.TraceIdleIdleTaskEnd(); |
- if (IsInLongIdlePeriod(state_.idle_period_state())) { |
- UpdateLongIdlePeriodStateAfterIdleTask(); |
- } |
-} |
- |
-// static |
-bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) { |
- return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; |
-} |
- |
-// static |
-bool IdleHelper::IsInLongIdlePeriod(IdlePeriodState state) { |
- return state == IdlePeriodState::IN_LONG_IDLE_PERIOD || |
- state == IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE || |
- state == IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED; |
-} |
- |
-bool IdleHelper::CanExceedIdleDeadlineIfRequired() const { |
- TRACE_EVENT0(disabled_by_default_tracing_category_, |
- "CanExceedIdleDeadlineIfRequired"); |
- helper_->CheckOnValidThread(); |
- return state_.idle_period_state() == |
- IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE; |
-} |
- |
-IdleHelper::IdlePeriodState IdleHelper::SchedulerIdlePeriodState() const { |
- return state_.idle_period_state(); |
-} |
- |
-IdleHelper::State::State(SchedulerHelper* helper, |
- Delegate* delegate, |
- const char* tracing_category, |
- const char* disabled_by_default_tracing_category, |
- const char* idle_period_tracing_name) |
- : helper_(helper), |
- delegate_(delegate), |
- idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), |
- idle_period_trace_event_started_(false), |
- running_idle_task_for_tracing_(false), |
- tracing_category_(tracing_category), |
- disabled_by_default_tracing_category_( |
- disabled_by_default_tracing_category), |
- idle_period_tracing_name_(idle_period_tracing_name) { |
-} |
- |
-IdleHelper::State::~State() { |
-} |
- |
-IdleHelper::IdlePeriodState IdleHelper::State::idle_period_state() const { |
- helper_->CheckOnValidThread(); |
- return idle_period_state_; |
-} |
- |
-base::TimeTicks IdleHelper::State::idle_period_deadline() const { |
- helper_->CheckOnValidThread(); |
- return idle_period_deadline_; |
-} |
- |
-void IdleHelper::State::UpdateState(IdlePeriodState new_state, |
- base::TimeTicks new_deadline, |
- base::TimeTicks optional_now) { |
- IdlePeriodState old_idle_period_state = idle_period_state_; |
- |
- helper_->CheckOnValidThread(); |
- if (new_state == idle_period_state_) { |
- DCHECK_EQ(new_deadline, idle_period_deadline_); |
- return; |
- } |
- |
- bool is_tracing; |
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); |
- if (is_tracing) { |
- base::TimeTicks now(optional_now.is_null() |
- ? helper_->scheduler_tqm_delegate()->NowTicks() |
- : optional_now); |
- TraceEventIdlePeriodStateChange( |
- new_state, running_idle_task_for_tracing_, idle_period_deadline_, now); |
- } |
- |
- idle_period_state_ = new_state; |
- idle_period_deadline_ = new_deadline; |
- |
- // Inform the delegate if we are starting or ending an idle period. |
- if (IsInIdlePeriod(new_state) && !IsInIdlePeriod(old_idle_period_state)) { |
- delegate_->OnIdlePeriodStarted(); |
- } else if (!IsInIdlePeriod(new_state) && |
- IsInIdlePeriod(old_idle_period_state)) { |
- delegate_->OnIdlePeriodEnded(); |
- } |
-} |
- |
-void IdleHelper::State::TraceIdleIdleTaskStart() { |
- helper_->CheckOnValidThread(); |
- |
- bool is_tracing; |
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); |
- if (is_tracing) { |
- TraceEventIdlePeriodStateChange( |
- idle_period_state_, true, idle_period_deadline_, |
- base::TimeTicks::Now()); |
- } |
-} |
- |
-void IdleHelper::State::TraceIdleIdleTaskEnd() { |
- helper_->CheckOnValidThread(); |
- |
- bool is_tracing; |
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); |
- if (is_tracing) { |
- TraceEventIdlePeriodStateChange( |
- idle_period_state_, false, idle_period_deadline_, |
- base::TimeTicks::Now()); |
- } |
-} |
- |
-void IdleHelper::State::TraceEventIdlePeriodStateChange( |
- IdlePeriodState new_state, |
- bool new_running_idle_task, |
- base::TimeTicks new_deadline, |
- base::TimeTicks now) { |
- TRACE_EVENT2(disabled_by_default_tracing_category_, "SetIdlePeriodState", |
- "old_state", |
- IdleHelper::IdlePeriodStateToString(idle_period_state_), |
- "new_state", IdleHelper::IdlePeriodStateToString(new_state)); |
- |
- if (idle_period_trace_event_started_ && running_idle_task_for_tracing_ && |
- !new_running_idle_task) { |
- running_idle_task_for_tracing_ = false; |
- if (!idle_period_deadline_.is_null() && now > idle_period_deadline_) { |
- TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( |
- tracing_category_, idle_period_tracing_name_, this, |
- "DeadlineOverrun", |
- std::max(idle_period_deadline_, |
- last_idle_task_trace_time_).ToInternalValue()); |
- } |
- } |
- |
- if (IsInIdlePeriod(new_state)) { |
- if (!idle_period_trace_event_started_) { |
- idle_period_trace_event_started_ = true; |
- TRACE_EVENT_ASYNC_BEGIN1( |
- tracing_category_, idle_period_tracing_name_, this, |
- "idle_period_length_ms", (new_deadline - now).ToInternalValue()); |
- } |
- |
- if (new_running_idle_task) { |
- last_idle_task_trace_time_ = now; |
- running_idle_task_for_tracing_ = true; |
- TRACE_EVENT_ASYNC_STEP_INTO0( |
- tracing_category_, idle_period_tracing_name_, this, |
- "RunningIdleTask"); |
- } else if (new_state == IdlePeriodState::IN_SHORT_IDLE_PERIOD) { |
- TRACE_EVENT_ASYNC_STEP_INTO0( |
- tracing_category_, idle_period_tracing_name_, this, |
- "ShortIdlePeriod"); |
- } else if (IsInLongIdlePeriod(new_state) && |
- new_state != IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED) { |
- TRACE_EVENT_ASYNC_STEP_INTO0( |
- tracing_category_, idle_period_tracing_name_, this, |
- "LongIdlePeriod"); |
- } else if (new_state == IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED) { |
- TRACE_EVENT_ASYNC_STEP_INTO0( |
- tracing_category_, idle_period_tracing_name_, this, |
- "LongIdlePeriodPaused"); |
- } |
- } else if (idle_period_trace_event_started_) { |
- idle_period_trace_event_started_ = false; |
- TRACE_EVENT_ASYNC_END0(tracing_category_, idle_period_tracing_name_, this); |
- } |
-} |
- |
-// static |
-const char* IdleHelper::IdlePeriodStateToString( |
- IdlePeriodState idle_period_state) { |
- switch (idle_period_state) { |
- case IdlePeriodState::NOT_IN_IDLE_PERIOD: |
- return "not_in_idle_period"; |
- case IdlePeriodState::IN_SHORT_IDLE_PERIOD: |
- return "in_short_idle_period"; |
- case IdlePeriodState::IN_LONG_IDLE_PERIOD: |
- return "in_long_idle_period"; |
- case IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE: |
- return "in_long_idle_period_with_max_deadline"; |
- case IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED: |
- return "in_long_idle_period_paused"; |
- default: |
- NOTREACHED(); |
- return nullptr; |
- } |
-} |
- |
-} // namespace scheduler |