xref: /aosp_15_r20/external/libchrome/base/task_scheduler/task_tracker.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/task_tracker.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <limits>
8*635a8641SAndroid Build Coastguard Worker #include <string>
9*635a8641SAndroid Build Coastguard Worker #include <vector>
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/base_switches.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/callback.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/command_line.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/json/json_writer.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/sequence_token.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/condition_variable.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/threading/sequence_local_storage_map.h"
21*635a8641SAndroid Build Coastguard Worker #include "base/threading/sequenced_task_runner_handle.h"
22*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
23*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_task_runner_handle.h"
24*635a8641SAndroid Build Coastguard Worker #include "base/time/time.h"
25*635a8641SAndroid Build Coastguard Worker #include "base/trace_event/trace_event.h"
26*635a8641SAndroid Build Coastguard Worker #include "base/values.h"
27*635a8641SAndroid Build Coastguard Worker 
28*635a8641SAndroid Build Coastguard Worker namespace base {
29*635a8641SAndroid Build Coastguard Worker namespace internal {
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker namespace {
32*635a8641SAndroid Build Coastguard Worker 
33*635a8641SAndroid Build Coastguard Worker constexpr char kParallelExecutionMode[] = "parallel";
34*635a8641SAndroid Build Coastguard Worker constexpr char kSequencedExecutionMode[] = "sequenced";
35*635a8641SAndroid Build Coastguard Worker constexpr char kSingleThreadExecutionMode[] = "single thread";
36*635a8641SAndroid Build Coastguard Worker 
37*635a8641SAndroid Build Coastguard Worker // An immutable copy of a scheduler task's info required by tracing.
38*635a8641SAndroid Build Coastguard Worker class TaskTracingInfo : public trace_event::ConvertableToTraceFormat {
39*635a8641SAndroid Build Coastguard Worker  public:
TaskTracingInfo(const TaskTraits & task_traits,const char * execution_mode,const SequenceToken & sequence_token)40*635a8641SAndroid Build Coastguard Worker   TaskTracingInfo(const TaskTraits& task_traits,
41*635a8641SAndroid Build Coastguard Worker                   const char* execution_mode,
42*635a8641SAndroid Build Coastguard Worker                   const SequenceToken& sequence_token)
43*635a8641SAndroid Build Coastguard Worker       : task_traits_(task_traits),
44*635a8641SAndroid Build Coastguard Worker         execution_mode_(execution_mode),
45*635a8641SAndroid Build Coastguard Worker         sequence_token_(sequence_token) {}
46*635a8641SAndroid Build Coastguard Worker 
47*635a8641SAndroid Build Coastguard Worker   // trace_event::ConvertableToTraceFormat implementation.
48*635a8641SAndroid Build Coastguard Worker   void AppendAsTraceFormat(std::string* out) const override;
49*635a8641SAndroid Build Coastguard Worker 
50*635a8641SAndroid Build Coastguard Worker  private:
51*635a8641SAndroid Build Coastguard Worker   const TaskTraits task_traits_;
52*635a8641SAndroid Build Coastguard Worker   const char* const execution_mode_;
53*635a8641SAndroid Build Coastguard Worker   const SequenceToken sequence_token_;
54*635a8641SAndroid Build Coastguard Worker 
55*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(TaskTracingInfo);
56*635a8641SAndroid Build Coastguard Worker };
57*635a8641SAndroid Build Coastguard Worker 
AppendAsTraceFormat(std::string * out) const58*635a8641SAndroid Build Coastguard Worker void TaskTracingInfo::AppendAsTraceFormat(std::string* out) const {
59*635a8641SAndroid Build Coastguard Worker   DictionaryValue dict;
60*635a8641SAndroid Build Coastguard Worker 
61*635a8641SAndroid Build Coastguard Worker   dict.SetString("task_priority",
62*635a8641SAndroid Build Coastguard Worker                  base::TaskPriorityToString(task_traits_.priority()));
63*635a8641SAndroid Build Coastguard Worker   dict.SetString("execution_mode", execution_mode_);
64*635a8641SAndroid Build Coastguard Worker   if (execution_mode_ != kParallelExecutionMode)
65*635a8641SAndroid Build Coastguard Worker     dict.SetInteger("sequence_token", sequence_token_.ToInternalValue());
66*635a8641SAndroid Build Coastguard Worker 
67*635a8641SAndroid Build Coastguard Worker   std::string tmp;
68*635a8641SAndroid Build Coastguard Worker   JSONWriter::Write(dict, &tmp);
69*635a8641SAndroid Build Coastguard Worker   out->append(tmp);
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker 
72*635a8641SAndroid Build Coastguard Worker // These name conveys that a Task is posted to/run by the task scheduler without
73*635a8641SAndroid Build Coastguard Worker // revealing its implementation details.
74*635a8641SAndroid Build Coastguard Worker constexpr char kQueueFunctionName[] = "TaskScheduler PostTask";
75*635a8641SAndroid Build Coastguard Worker constexpr char kRunFunctionName[] = "TaskScheduler RunTask";
76*635a8641SAndroid Build Coastguard Worker 
77*635a8641SAndroid Build Coastguard Worker constexpr char kTaskSchedulerFlowTracingCategory[] =
78*635a8641SAndroid Build Coastguard Worker     TRACE_DISABLED_BY_DEFAULT("task_scheduler.flow");
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker // Constructs a histogram to track latency which is logging to
81*635a8641SAndroid Build Coastguard Worker // "TaskScheduler.{histogram_name}.{histogram_label}.{task_type_suffix}".
GetLatencyHistogram(StringPiece histogram_name,StringPiece histogram_label,StringPiece task_type_suffix)82*635a8641SAndroid Build Coastguard Worker HistogramBase* GetLatencyHistogram(StringPiece histogram_name,
83*635a8641SAndroid Build Coastguard Worker                                    StringPiece histogram_label,
84*635a8641SAndroid Build Coastguard Worker                                    StringPiece task_type_suffix) {
85*635a8641SAndroid Build Coastguard Worker   DCHECK(!histogram_name.empty());
86*635a8641SAndroid Build Coastguard Worker   DCHECK(!histogram_label.empty());
87*635a8641SAndroid Build Coastguard Worker   DCHECK(!task_type_suffix.empty());
88*635a8641SAndroid Build Coastguard Worker   // Mimics the UMA_HISTOGRAM_HIGH_RESOLUTION_CUSTOM_TIMES macro. The minimums
89*635a8641SAndroid Build Coastguard Worker   // and maximums were chosen to place the 1ms mark at around the 70% range
90*635a8641SAndroid Build Coastguard Worker   // coverage for buckets giving us good info for tasks that have a latency
91*635a8641SAndroid Build Coastguard Worker   // below 1ms (most of them) and enough info to assess how bad the latency is
92*635a8641SAndroid Build Coastguard Worker   // for tasks that exceed this threshold.
93*635a8641SAndroid Build Coastguard Worker   const std::string histogram = JoinString(
94*635a8641SAndroid Build Coastguard Worker       {"TaskScheduler", histogram_name, histogram_label, task_type_suffix},
95*635a8641SAndroid Build Coastguard Worker       ".");
96*635a8641SAndroid Build Coastguard Worker   return Histogram::FactoryMicrosecondsTimeGet(
97*635a8641SAndroid Build Coastguard Worker       histogram, TimeDelta::FromMicroseconds(1),
98*635a8641SAndroid Build Coastguard Worker       TimeDelta::FromMilliseconds(20), 50,
99*635a8641SAndroid Build Coastguard Worker       HistogramBase::kUmaTargetedHistogramFlag);
100*635a8641SAndroid Build Coastguard Worker }
101*635a8641SAndroid Build Coastguard Worker 
102*635a8641SAndroid Build Coastguard Worker // Upper bound for the
103*635a8641SAndroid Build Coastguard Worker // TaskScheduler.BlockShutdownTasksPostedDuringShutdown histogram.
104*635a8641SAndroid Build Coastguard Worker constexpr HistogramBase::Sample kMaxBlockShutdownTasksPostedDuringShutdown =
105*635a8641SAndroid Build Coastguard Worker     1000;
106*635a8641SAndroid Build Coastguard Worker 
RecordNumBlockShutdownTasksPostedDuringShutdown(HistogramBase::Sample value)107*635a8641SAndroid Build Coastguard Worker void RecordNumBlockShutdownTasksPostedDuringShutdown(
108*635a8641SAndroid Build Coastguard Worker     HistogramBase::Sample value) {
109*635a8641SAndroid Build Coastguard Worker   UMA_HISTOGRAM_CUSTOM_COUNTS(
110*635a8641SAndroid Build Coastguard Worker       "TaskScheduler.BlockShutdownTasksPostedDuringShutdown", value, 1,
111*635a8641SAndroid Build Coastguard Worker       kMaxBlockShutdownTasksPostedDuringShutdown, 50);
112*635a8641SAndroid Build Coastguard Worker }
113*635a8641SAndroid Build Coastguard Worker 
114*635a8641SAndroid Build Coastguard Worker // Returns the maximum number of TaskPriority::BACKGROUND sequences that can be
115*635a8641SAndroid Build Coastguard Worker // scheduled concurrently based on command line flags.
GetMaxNumScheduledBackgroundSequences()116*635a8641SAndroid Build Coastguard Worker int GetMaxNumScheduledBackgroundSequences() {
117*635a8641SAndroid Build Coastguard Worker   // The CommandLine might not be initialized if TaskScheduler is initialized
118*635a8641SAndroid Build Coastguard Worker   // in a dynamic library which doesn't have access to argc/argv.
119*635a8641SAndroid Build Coastguard Worker   if (CommandLine::InitializedForCurrentProcess() &&
120*635a8641SAndroid Build Coastguard Worker       CommandLine::ForCurrentProcess()->HasSwitch(
121*635a8641SAndroid Build Coastguard Worker           switches::kDisableBackgroundTasks)) {
122*635a8641SAndroid Build Coastguard Worker     return 0;
123*635a8641SAndroid Build Coastguard Worker   }
124*635a8641SAndroid Build Coastguard Worker   return std::numeric_limits<int>::max();
125*635a8641SAndroid Build Coastguard Worker }
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker }  // namespace
128*635a8641SAndroid Build Coastguard Worker 
129*635a8641SAndroid Build Coastguard Worker // Atomic internal state used by TaskTracker. Sequential consistency shouldn't
130*635a8641SAndroid Build Coastguard Worker // be assumed from these calls (i.e. a thread reading
131*635a8641SAndroid Build Coastguard Worker // |HasShutdownStarted() == true| isn't guaranteed to see all writes made before
132*635a8641SAndroid Build Coastguard Worker // |StartShutdown()| on the thread that invoked it).
133*635a8641SAndroid Build Coastguard Worker class TaskTracker::State {
134*635a8641SAndroid Build Coastguard Worker  public:
135*635a8641SAndroid Build Coastguard Worker   State() = default;
136*635a8641SAndroid Build Coastguard Worker 
137*635a8641SAndroid Build Coastguard Worker   // Sets a flag indicating that shutdown has started. Returns true if there are
138*635a8641SAndroid Build Coastguard Worker   // tasks blocking shutdown. Can only be called once.
StartShutdown()139*635a8641SAndroid Build Coastguard Worker   bool StartShutdown() {
140*635a8641SAndroid Build Coastguard Worker     const auto new_value =
141*635a8641SAndroid Build Coastguard Worker         subtle::NoBarrier_AtomicIncrement(&bits_, kShutdownHasStartedMask);
142*635a8641SAndroid Build Coastguard Worker 
143*635a8641SAndroid Build Coastguard Worker     // Check that the "shutdown has started" bit isn't zero. This would happen
144*635a8641SAndroid Build Coastguard Worker     // if it was incremented twice.
145*635a8641SAndroid Build Coastguard Worker     DCHECK(new_value & kShutdownHasStartedMask);
146*635a8641SAndroid Build Coastguard Worker 
147*635a8641SAndroid Build Coastguard Worker     const auto num_tasks_blocking_shutdown =
148*635a8641SAndroid Build Coastguard Worker         new_value >> kNumTasksBlockingShutdownBitOffset;
149*635a8641SAndroid Build Coastguard Worker     return num_tasks_blocking_shutdown != 0;
150*635a8641SAndroid Build Coastguard Worker   }
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker   // Returns true if shutdown has started.
HasShutdownStarted() const153*635a8641SAndroid Build Coastguard Worker   bool HasShutdownStarted() const {
154*635a8641SAndroid Build Coastguard Worker     return subtle::NoBarrier_Load(&bits_) & kShutdownHasStartedMask;
155*635a8641SAndroid Build Coastguard Worker   }
156*635a8641SAndroid Build Coastguard Worker 
157*635a8641SAndroid Build Coastguard Worker   // Returns true if there are tasks blocking shutdown.
AreTasksBlockingShutdown() const158*635a8641SAndroid Build Coastguard Worker   bool AreTasksBlockingShutdown() const {
159*635a8641SAndroid Build Coastguard Worker     const auto num_tasks_blocking_shutdown =
160*635a8641SAndroid Build Coastguard Worker         subtle::NoBarrier_Load(&bits_) >> kNumTasksBlockingShutdownBitOffset;
161*635a8641SAndroid Build Coastguard Worker     DCHECK_GE(num_tasks_blocking_shutdown, 0);
162*635a8641SAndroid Build Coastguard Worker     return num_tasks_blocking_shutdown != 0;
163*635a8641SAndroid Build Coastguard Worker   }
164*635a8641SAndroid Build Coastguard Worker 
165*635a8641SAndroid Build Coastguard Worker   // Increments the number of tasks blocking shutdown. Returns true if shutdown
166*635a8641SAndroid Build Coastguard Worker   // has started.
IncrementNumTasksBlockingShutdown()167*635a8641SAndroid Build Coastguard Worker   bool IncrementNumTasksBlockingShutdown() {
168*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
169*635a8641SAndroid Build Coastguard Worker     // Verify that no overflow will occur.
170*635a8641SAndroid Build Coastguard Worker     const auto num_tasks_blocking_shutdown =
171*635a8641SAndroid Build Coastguard Worker         subtle::NoBarrier_Load(&bits_) >> kNumTasksBlockingShutdownBitOffset;
172*635a8641SAndroid Build Coastguard Worker     DCHECK_LT(num_tasks_blocking_shutdown,
173*635a8641SAndroid Build Coastguard Worker               std::numeric_limits<subtle::Atomic32>::max() -
174*635a8641SAndroid Build Coastguard Worker                   kNumTasksBlockingShutdownIncrement);
175*635a8641SAndroid Build Coastguard Worker #endif
176*635a8641SAndroid Build Coastguard Worker 
177*635a8641SAndroid Build Coastguard Worker     const auto new_bits = subtle::NoBarrier_AtomicIncrement(
178*635a8641SAndroid Build Coastguard Worker         &bits_, kNumTasksBlockingShutdownIncrement);
179*635a8641SAndroid Build Coastguard Worker     return new_bits & kShutdownHasStartedMask;
180*635a8641SAndroid Build Coastguard Worker   }
181*635a8641SAndroid Build Coastguard Worker 
182*635a8641SAndroid Build Coastguard Worker   // Decrements the number of tasks blocking shutdown. Returns true if shutdown
183*635a8641SAndroid Build Coastguard Worker   // has started and the number of tasks blocking shutdown becomes zero.
DecrementNumTasksBlockingShutdown()184*635a8641SAndroid Build Coastguard Worker   bool DecrementNumTasksBlockingShutdown() {
185*635a8641SAndroid Build Coastguard Worker     const auto new_bits = subtle::NoBarrier_AtomicIncrement(
186*635a8641SAndroid Build Coastguard Worker         &bits_, -kNumTasksBlockingShutdownIncrement);
187*635a8641SAndroid Build Coastguard Worker     const bool shutdown_has_started = new_bits & kShutdownHasStartedMask;
188*635a8641SAndroid Build Coastguard Worker     const auto num_tasks_blocking_shutdown =
189*635a8641SAndroid Build Coastguard Worker         new_bits >> kNumTasksBlockingShutdownBitOffset;
190*635a8641SAndroid Build Coastguard Worker     DCHECK_GE(num_tasks_blocking_shutdown, 0);
191*635a8641SAndroid Build Coastguard Worker     return shutdown_has_started && num_tasks_blocking_shutdown == 0;
192*635a8641SAndroid Build Coastguard Worker   }
193*635a8641SAndroid Build Coastguard Worker 
194*635a8641SAndroid Build Coastguard Worker  private:
195*635a8641SAndroid Build Coastguard Worker   static constexpr subtle::Atomic32 kShutdownHasStartedMask = 1;
196*635a8641SAndroid Build Coastguard Worker   static constexpr subtle::Atomic32 kNumTasksBlockingShutdownBitOffset = 1;
197*635a8641SAndroid Build Coastguard Worker   static constexpr subtle::Atomic32 kNumTasksBlockingShutdownIncrement =
198*635a8641SAndroid Build Coastguard Worker       1 << kNumTasksBlockingShutdownBitOffset;
199*635a8641SAndroid Build Coastguard Worker 
200*635a8641SAndroid Build Coastguard Worker   // The LSB indicates whether shutdown has started. The other bits count the
201*635a8641SAndroid Build Coastguard Worker   // number of tasks blocking shutdown.
202*635a8641SAndroid Build Coastguard Worker   // No barriers are required to read/write |bits_| as this class is only used
203*635a8641SAndroid Build Coastguard Worker   // as an atomic state checker, it doesn't provide sequential consistency
204*635a8641SAndroid Build Coastguard Worker   // guarantees w.r.t. external state. Sequencing of the TaskTracker::State
205*635a8641SAndroid Build Coastguard Worker   // operations themselves is guaranteed by the AtomicIncrement RMW (read-
206*635a8641SAndroid Build Coastguard Worker   // modify-write) semantics however. For example, if two threads are racing to
207*635a8641SAndroid Build Coastguard Worker   // call IncrementNumTasksBlockingShutdown() and StartShutdown() respectively,
208*635a8641SAndroid Build Coastguard Worker   // either the first thread will win and the StartShutdown() call will see the
209*635a8641SAndroid Build Coastguard Worker   // blocking task or the second thread will win and
210*635a8641SAndroid Build Coastguard Worker   // IncrementNumTasksBlockingShutdown() will know that shutdown has started.
211*635a8641SAndroid Build Coastguard Worker   subtle::Atomic32 bits_ = 0;
212*635a8641SAndroid Build Coastguard Worker 
213*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(State);
214*635a8641SAndroid Build Coastguard Worker };
215*635a8641SAndroid Build Coastguard Worker 
216*635a8641SAndroid Build Coastguard Worker struct TaskTracker::PreemptedBackgroundSequence {
217*635a8641SAndroid Build Coastguard Worker   PreemptedBackgroundSequence() = default;
PreemptedBackgroundSequencebase::internal::TaskTracker::PreemptedBackgroundSequence218*635a8641SAndroid Build Coastguard Worker   PreemptedBackgroundSequence(scoped_refptr<Sequence> sequence_in,
219*635a8641SAndroid Build Coastguard Worker                               TimeTicks next_task_sequenced_time_in,
220*635a8641SAndroid Build Coastguard Worker                               CanScheduleSequenceObserver* observer_in)
221*635a8641SAndroid Build Coastguard Worker       : sequence(std::move(sequence_in)),
222*635a8641SAndroid Build Coastguard Worker         next_task_sequenced_time(next_task_sequenced_time_in),
223*635a8641SAndroid Build Coastguard Worker         observer(observer_in) {}
224*635a8641SAndroid Build Coastguard Worker   PreemptedBackgroundSequence(PreemptedBackgroundSequence&& other) = default;
225*635a8641SAndroid Build Coastguard Worker   ~PreemptedBackgroundSequence() = default;
226*635a8641SAndroid Build Coastguard Worker   PreemptedBackgroundSequence& operator=(PreemptedBackgroundSequence&& other) =
227*635a8641SAndroid Build Coastguard Worker       default;
operator <base::internal::TaskTracker::PreemptedBackgroundSequence228*635a8641SAndroid Build Coastguard Worker   bool operator<(const PreemptedBackgroundSequence& other) const {
229*635a8641SAndroid Build Coastguard Worker     return next_task_sequenced_time < other.next_task_sequenced_time;
230*635a8641SAndroid Build Coastguard Worker   }
operator >base::internal::TaskTracker::PreemptedBackgroundSequence231*635a8641SAndroid Build Coastguard Worker   bool operator>(const PreemptedBackgroundSequence& other) const {
232*635a8641SAndroid Build Coastguard Worker     return next_task_sequenced_time > other.next_task_sequenced_time;
233*635a8641SAndroid Build Coastguard Worker   }
234*635a8641SAndroid Build Coastguard Worker 
235*635a8641SAndroid Build Coastguard Worker   // A background sequence waiting to be scheduled.
236*635a8641SAndroid Build Coastguard Worker   scoped_refptr<Sequence> sequence;
237*635a8641SAndroid Build Coastguard Worker 
238*635a8641SAndroid Build Coastguard Worker   // The sequenced time of the next task in |sequence|.
239*635a8641SAndroid Build Coastguard Worker   TimeTicks next_task_sequenced_time;
240*635a8641SAndroid Build Coastguard Worker 
241*635a8641SAndroid Build Coastguard Worker   // An observer to notify when |sequence| can be scheduled.
242*635a8641SAndroid Build Coastguard Worker   CanScheduleSequenceObserver* observer = nullptr;
243*635a8641SAndroid Build Coastguard Worker 
244*635a8641SAndroid Build Coastguard Worker  private:
245*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(PreemptedBackgroundSequence);
246*635a8641SAndroid Build Coastguard Worker };
247*635a8641SAndroid Build Coastguard Worker 
TaskTracker(StringPiece histogram_label)248*635a8641SAndroid Build Coastguard Worker TaskTracker::TaskTracker(StringPiece histogram_label)
249*635a8641SAndroid Build Coastguard Worker     : TaskTracker(histogram_label, GetMaxNumScheduledBackgroundSequences()) {}
250*635a8641SAndroid Build Coastguard Worker 
TaskTracker(StringPiece histogram_label,int max_num_scheduled_background_sequences)251*635a8641SAndroid Build Coastguard Worker TaskTracker::TaskTracker(StringPiece histogram_label,
252*635a8641SAndroid Build Coastguard Worker                          int max_num_scheduled_background_sequences)
253*635a8641SAndroid Build Coastguard Worker     : state_(new State),
254*635a8641SAndroid Build Coastguard Worker       flush_cv_(flush_lock_.CreateConditionVariable()),
255*635a8641SAndroid Build Coastguard Worker       shutdown_lock_(&flush_lock_),
256*635a8641SAndroid Build Coastguard Worker       max_num_scheduled_background_sequences_(
257*635a8641SAndroid Build Coastguard Worker           max_num_scheduled_background_sequences),
258*635a8641SAndroid Build Coastguard Worker       task_latency_histograms_{
259*635a8641SAndroid Build Coastguard Worker           {GetLatencyHistogram("TaskLatencyMicroseconds",
260*635a8641SAndroid Build Coastguard Worker                                histogram_label,
261*635a8641SAndroid Build Coastguard Worker                                "BackgroundTaskPriority"),
262*635a8641SAndroid Build Coastguard Worker            GetLatencyHistogram("TaskLatencyMicroseconds",
263*635a8641SAndroid Build Coastguard Worker                                histogram_label,
264*635a8641SAndroid Build Coastguard Worker                                "BackgroundTaskPriority_MayBlock")},
265*635a8641SAndroid Build Coastguard Worker           {GetLatencyHistogram("TaskLatencyMicroseconds",
266*635a8641SAndroid Build Coastguard Worker                                histogram_label,
267*635a8641SAndroid Build Coastguard Worker                                "UserVisibleTaskPriority"),
268*635a8641SAndroid Build Coastguard Worker            GetLatencyHistogram("TaskLatencyMicroseconds",
269*635a8641SAndroid Build Coastguard Worker                                histogram_label,
270*635a8641SAndroid Build Coastguard Worker                                "UserVisibleTaskPriority_MayBlock")},
271*635a8641SAndroid Build Coastguard Worker           {GetLatencyHistogram("TaskLatencyMicroseconds",
272*635a8641SAndroid Build Coastguard Worker                                histogram_label,
273*635a8641SAndroid Build Coastguard Worker                                "UserBlockingTaskPriority"),
274*635a8641SAndroid Build Coastguard Worker            GetLatencyHistogram("TaskLatencyMicroseconds",
275*635a8641SAndroid Build Coastguard Worker                                histogram_label,
276*635a8641SAndroid Build Coastguard Worker                                "UserBlockingTaskPriority_MayBlock")}},
277*635a8641SAndroid Build Coastguard Worker       heartbeat_latency_histograms_{
278*635a8641SAndroid Build Coastguard Worker           {GetLatencyHistogram("HeartbeatLatencyMicroseconds",
279*635a8641SAndroid Build Coastguard Worker                                histogram_label,
280*635a8641SAndroid Build Coastguard Worker                                "BackgroundTaskPriority"),
281*635a8641SAndroid Build Coastguard Worker            GetLatencyHistogram("HeartbeatLatencyMicroseconds",
282*635a8641SAndroid Build Coastguard Worker                                histogram_label,
283*635a8641SAndroid Build Coastguard Worker                                "BackgroundTaskPriority_MayBlock")},
284*635a8641SAndroid Build Coastguard Worker           {GetLatencyHistogram("HeartbeatLatencyMicroseconds",
285*635a8641SAndroid Build Coastguard Worker                                histogram_label,
286*635a8641SAndroid Build Coastguard Worker                                "UserVisibleTaskPriority"),
287*635a8641SAndroid Build Coastguard Worker            GetLatencyHistogram("HeartbeatLatencyMicroseconds",
288*635a8641SAndroid Build Coastguard Worker                                histogram_label,
289*635a8641SAndroid Build Coastguard Worker                                "UserVisibleTaskPriority_MayBlock")},
290*635a8641SAndroid Build Coastguard Worker           {GetLatencyHistogram("HeartbeatLatencyMicroseconds",
291*635a8641SAndroid Build Coastguard Worker                                histogram_label,
292*635a8641SAndroid Build Coastguard Worker                                "UserBlockingTaskPriority"),
293*635a8641SAndroid Build Coastguard Worker            GetLatencyHistogram("HeartbeatLatencyMicroseconds",
294*635a8641SAndroid Build Coastguard Worker                                histogram_label,
295*635a8641SAndroid Build Coastguard Worker                                "UserBlockingTaskPriority_MayBlock")}},
296*635a8641SAndroid Build Coastguard Worker       tracked_ref_factory_(this) {
297*635a8641SAndroid Build Coastguard Worker   // Confirm that all |task_latency_histograms_| have been initialized above.
298*635a8641SAndroid Build Coastguard Worker   DCHECK(*(&task_latency_histograms_[static_cast<int>(TaskPriority::HIGHEST) +
299*635a8641SAndroid Build Coastguard Worker                                      1][0] -
300*635a8641SAndroid Build Coastguard Worker            1));
301*635a8641SAndroid Build Coastguard Worker }
302*635a8641SAndroid Build Coastguard Worker 
303*635a8641SAndroid Build Coastguard Worker TaskTracker::~TaskTracker() = default;
304*635a8641SAndroid Build Coastguard Worker 
Shutdown()305*635a8641SAndroid Build Coastguard Worker void TaskTracker::Shutdown() {
306*635a8641SAndroid Build Coastguard Worker   PerformShutdown();
307*635a8641SAndroid Build Coastguard Worker   DCHECK(IsShutdownComplete());
308*635a8641SAndroid Build Coastguard Worker 
309*635a8641SAndroid Build Coastguard Worker   // Unblock FlushForTesting() and perform the FlushAsyncForTesting callback
310*635a8641SAndroid Build Coastguard Worker   // when shutdown completes.
311*635a8641SAndroid Build Coastguard Worker   {
312*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(flush_lock_);
313*635a8641SAndroid Build Coastguard Worker     flush_cv_->Signal();
314*635a8641SAndroid Build Coastguard Worker   }
315*635a8641SAndroid Build Coastguard Worker   CallFlushCallbackForTesting();
316*635a8641SAndroid Build Coastguard Worker }
317*635a8641SAndroid Build Coastguard Worker 
FlushForTesting()318*635a8641SAndroid Build Coastguard Worker void TaskTracker::FlushForTesting() {
319*635a8641SAndroid Build Coastguard Worker   AutoSchedulerLock auto_lock(flush_lock_);
320*635a8641SAndroid Build Coastguard Worker   while (subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) != 0 &&
321*635a8641SAndroid Build Coastguard Worker          !IsShutdownComplete()) {
322*635a8641SAndroid Build Coastguard Worker     flush_cv_->Wait();
323*635a8641SAndroid Build Coastguard Worker   }
324*635a8641SAndroid Build Coastguard Worker }
325*635a8641SAndroid Build Coastguard Worker 
FlushAsyncForTesting(OnceClosure flush_callback)326*635a8641SAndroid Build Coastguard Worker void TaskTracker::FlushAsyncForTesting(OnceClosure flush_callback) {
327*635a8641SAndroid Build Coastguard Worker   DCHECK(flush_callback);
328*635a8641SAndroid Build Coastguard Worker   {
329*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(flush_lock_);
330*635a8641SAndroid Build Coastguard Worker     DCHECK(!flush_callback_for_testing_)
331*635a8641SAndroid Build Coastguard Worker         << "Only one FlushAsyncForTesting() may be pending at any time.";
332*635a8641SAndroid Build Coastguard Worker     flush_callback_for_testing_ = std::move(flush_callback);
333*635a8641SAndroid Build Coastguard Worker   }
334*635a8641SAndroid Build Coastguard Worker 
335*635a8641SAndroid Build Coastguard Worker   if (subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) == 0 ||
336*635a8641SAndroid Build Coastguard Worker       IsShutdownComplete()) {
337*635a8641SAndroid Build Coastguard Worker     CallFlushCallbackForTesting();
338*635a8641SAndroid Build Coastguard Worker   }
339*635a8641SAndroid Build Coastguard Worker }
340*635a8641SAndroid Build Coastguard Worker 
WillPostTask(Task * task)341*635a8641SAndroid Build Coastguard Worker bool TaskTracker::WillPostTask(Task* task) {
342*635a8641SAndroid Build Coastguard Worker   DCHECK(task->task);
343*635a8641SAndroid Build Coastguard Worker 
344*635a8641SAndroid Build Coastguard Worker   if (!BeforePostTask(task->traits.shutdown_behavior()))
345*635a8641SAndroid Build Coastguard Worker     return false;
346*635a8641SAndroid Build Coastguard Worker 
347*635a8641SAndroid Build Coastguard Worker   if (task->delayed_run_time.is_null())
348*635a8641SAndroid Build Coastguard Worker     subtle::NoBarrier_AtomicIncrement(&num_incomplete_undelayed_tasks_, 1);
349*635a8641SAndroid Build Coastguard Worker 
350*635a8641SAndroid Build Coastguard Worker   {
351*635a8641SAndroid Build Coastguard Worker     TRACE_EVENT_WITH_FLOW0(
352*635a8641SAndroid Build Coastguard Worker         kTaskSchedulerFlowTracingCategory, kQueueFunctionName,
353*635a8641SAndroid Build Coastguard Worker         TRACE_ID_MANGLE(task_annotator_.GetTaskTraceID(*task)),
354*635a8641SAndroid Build Coastguard Worker         TRACE_EVENT_FLAG_FLOW_OUT);
355*635a8641SAndroid Build Coastguard Worker   }
356*635a8641SAndroid Build Coastguard Worker 
357*635a8641SAndroid Build Coastguard Worker   task_annotator_.WillQueueTask(nullptr, task);
358*635a8641SAndroid Build Coastguard Worker 
359*635a8641SAndroid Build Coastguard Worker   return true;
360*635a8641SAndroid Build Coastguard Worker }
361*635a8641SAndroid Build Coastguard Worker 
WillScheduleSequence(scoped_refptr<Sequence> sequence,CanScheduleSequenceObserver * observer)362*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> TaskTracker::WillScheduleSequence(
363*635a8641SAndroid Build Coastguard Worker     scoped_refptr<Sequence> sequence,
364*635a8641SAndroid Build Coastguard Worker     CanScheduleSequenceObserver* observer) {
365*635a8641SAndroid Build Coastguard Worker   const SequenceSortKey sort_key = sequence->GetSortKey();
366*635a8641SAndroid Build Coastguard Worker 
367*635a8641SAndroid Build Coastguard Worker   // A foreground sequence can always be scheduled.
368*635a8641SAndroid Build Coastguard Worker   if (sort_key.priority() != TaskPriority::BACKGROUND)
369*635a8641SAndroid Build Coastguard Worker     return sequence;
370*635a8641SAndroid Build Coastguard Worker 
371*635a8641SAndroid Build Coastguard Worker   // It is convenient not to have to specify an observer when scheduling
372*635a8641SAndroid Build Coastguard Worker   // foreground sequences in tests.
373*635a8641SAndroid Build Coastguard Worker   DCHECK(observer);
374*635a8641SAndroid Build Coastguard Worker 
375*635a8641SAndroid Build Coastguard Worker   AutoSchedulerLock auto_lock(background_lock_);
376*635a8641SAndroid Build Coastguard Worker 
377*635a8641SAndroid Build Coastguard Worker   if (num_scheduled_background_sequences_ <
378*635a8641SAndroid Build Coastguard Worker       max_num_scheduled_background_sequences_) {
379*635a8641SAndroid Build Coastguard Worker     ++num_scheduled_background_sequences_;
380*635a8641SAndroid Build Coastguard Worker     return sequence;
381*635a8641SAndroid Build Coastguard Worker   }
382*635a8641SAndroid Build Coastguard Worker 
383*635a8641SAndroid Build Coastguard Worker   preempted_background_sequences_.emplace(
384*635a8641SAndroid Build Coastguard Worker       std::move(sequence), sort_key.next_task_sequenced_time(), observer);
385*635a8641SAndroid Build Coastguard Worker   return nullptr;
386*635a8641SAndroid Build Coastguard Worker }
387*635a8641SAndroid Build Coastguard Worker 
RunAndPopNextTask(scoped_refptr<Sequence> sequence,CanScheduleSequenceObserver * observer)388*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> TaskTracker::RunAndPopNextTask(
389*635a8641SAndroid Build Coastguard Worker     scoped_refptr<Sequence> sequence,
390*635a8641SAndroid Build Coastguard Worker     CanScheduleSequenceObserver* observer) {
391*635a8641SAndroid Build Coastguard Worker   DCHECK(sequence);
392*635a8641SAndroid Build Coastguard Worker 
393*635a8641SAndroid Build Coastguard Worker   // Run the next task in |sequence|.
394*635a8641SAndroid Build Coastguard Worker   Optional<Task> task = sequence->TakeTask();
395*635a8641SAndroid Build Coastguard Worker   // TODO(fdoray): Support TakeTask() returning null. https://crbug.com/783309
396*635a8641SAndroid Build Coastguard Worker   DCHECK(task);
397*635a8641SAndroid Build Coastguard Worker 
398*635a8641SAndroid Build Coastguard Worker   const TaskShutdownBehavior shutdown_behavior =
399*635a8641SAndroid Build Coastguard Worker       task->traits.shutdown_behavior();
400*635a8641SAndroid Build Coastguard Worker   const TaskPriority task_priority = task->traits.priority();
401*635a8641SAndroid Build Coastguard Worker   const bool can_run_task = BeforeRunTask(shutdown_behavior);
402*635a8641SAndroid Build Coastguard Worker   const bool is_delayed = !task->delayed_run_time.is_null();
403*635a8641SAndroid Build Coastguard Worker 
404*635a8641SAndroid Build Coastguard Worker   RunOrSkipTask(std::move(task.value()), sequence.get(), can_run_task);
405*635a8641SAndroid Build Coastguard Worker   if (can_run_task)
406*635a8641SAndroid Build Coastguard Worker     AfterRunTask(shutdown_behavior);
407*635a8641SAndroid Build Coastguard Worker 
408*635a8641SAndroid Build Coastguard Worker   if (!is_delayed)
409*635a8641SAndroid Build Coastguard Worker     DecrementNumIncompleteUndelayedTasks();
410*635a8641SAndroid Build Coastguard Worker 
411*635a8641SAndroid Build Coastguard Worker   const bool sequence_is_empty_after_pop = sequence->Pop();
412*635a8641SAndroid Build Coastguard Worker 
413*635a8641SAndroid Build Coastguard Worker   // Never reschedule a Sequence emptied by Pop(). The contract is such that
414*635a8641SAndroid Build Coastguard Worker   // next poster to make it non-empty is responsible to schedule it.
415*635a8641SAndroid Build Coastguard Worker   if (sequence_is_empty_after_pop)
416*635a8641SAndroid Build Coastguard Worker     sequence = nullptr;
417*635a8641SAndroid Build Coastguard Worker 
418*635a8641SAndroid Build Coastguard Worker   if (task_priority == TaskPriority::BACKGROUND) {
419*635a8641SAndroid Build Coastguard Worker     // Allow |sequence| to be rescheduled only if its next task is set to run
420*635a8641SAndroid Build Coastguard Worker     // earlier than the earliest currently preempted sequence
421*635a8641SAndroid Build Coastguard Worker     return ManageBackgroundSequencesAfterRunningTask(std::move(sequence),
422*635a8641SAndroid Build Coastguard Worker                                                      observer);
423*635a8641SAndroid Build Coastguard Worker   }
424*635a8641SAndroid Build Coastguard Worker 
425*635a8641SAndroid Build Coastguard Worker   return sequence;
426*635a8641SAndroid Build Coastguard Worker }
427*635a8641SAndroid Build Coastguard Worker 
HasShutdownStarted() const428*635a8641SAndroid Build Coastguard Worker bool TaskTracker::HasShutdownStarted() const {
429*635a8641SAndroid Build Coastguard Worker   return state_->HasShutdownStarted();
430*635a8641SAndroid Build Coastguard Worker }
431*635a8641SAndroid Build Coastguard Worker 
IsShutdownComplete() const432*635a8641SAndroid Build Coastguard Worker bool TaskTracker::IsShutdownComplete() const {
433*635a8641SAndroid Build Coastguard Worker   AutoSchedulerLock auto_lock(shutdown_lock_);
434*635a8641SAndroid Build Coastguard Worker   return shutdown_event_ && shutdown_event_->IsSignaled();
435*635a8641SAndroid Build Coastguard Worker }
436*635a8641SAndroid Build Coastguard Worker 
SetHasShutdownStartedForTesting()437*635a8641SAndroid Build Coastguard Worker void TaskTracker::SetHasShutdownStartedForTesting() {
438*635a8641SAndroid Build Coastguard Worker   AutoSchedulerLock auto_lock(shutdown_lock_);
439*635a8641SAndroid Build Coastguard Worker 
440*635a8641SAndroid Build Coastguard Worker   // Create a dummy |shutdown_event_| to satisfy TaskTracker's expectation of
441*635a8641SAndroid Build Coastguard Worker   // its existence during shutdown (e.g. in OnBlockingShutdownTasksComplete()).
442*635a8641SAndroid Build Coastguard Worker   shutdown_event_ = std::make_unique<WaitableEvent>();
443*635a8641SAndroid Build Coastguard Worker 
444*635a8641SAndroid Build Coastguard Worker   state_->StartShutdown();
445*635a8641SAndroid Build Coastguard Worker }
446*635a8641SAndroid Build Coastguard Worker 
RecordLatencyHistogram(LatencyHistogramType latency_histogram_type,TaskTraits task_traits,TimeTicks posted_time) const447*635a8641SAndroid Build Coastguard Worker void TaskTracker::RecordLatencyHistogram(
448*635a8641SAndroid Build Coastguard Worker     LatencyHistogramType latency_histogram_type,
449*635a8641SAndroid Build Coastguard Worker     TaskTraits task_traits,
450*635a8641SAndroid Build Coastguard Worker     TimeTicks posted_time) const {
451*635a8641SAndroid Build Coastguard Worker   const TimeDelta task_latency = TimeTicks::Now() - posted_time;
452*635a8641SAndroid Build Coastguard Worker 
453*635a8641SAndroid Build Coastguard Worker   DCHECK(latency_histogram_type == LatencyHistogramType::TASK_LATENCY ||
454*635a8641SAndroid Build Coastguard Worker          latency_histogram_type == LatencyHistogramType::HEARTBEAT_LATENCY);
455*635a8641SAndroid Build Coastguard Worker   const auto& histograms =
456*635a8641SAndroid Build Coastguard Worker       latency_histogram_type == LatencyHistogramType::TASK_LATENCY
457*635a8641SAndroid Build Coastguard Worker           ? task_latency_histograms_
458*635a8641SAndroid Build Coastguard Worker           : heartbeat_latency_histograms_;
459*635a8641SAndroid Build Coastguard Worker   histograms[static_cast<int>(task_traits.priority())]
460*635a8641SAndroid Build Coastguard Worker             [task_traits.may_block() || task_traits.with_base_sync_primitives()
461*635a8641SAndroid Build Coastguard Worker                  ? 1
462*635a8641SAndroid Build Coastguard Worker                  : 0]
463*635a8641SAndroid Build Coastguard Worker                 ->AddTimeMicrosecondsGranularity(task_latency);
464*635a8641SAndroid Build Coastguard Worker }
465*635a8641SAndroid Build Coastguard Worker 
RunOrSkipTask(Task task,Sequence * sequence,bool can_run_task)466*635a8641SAndroid Build Coastguard Worker void TaskTracker::RunOrSkipTask(Task task,
467*635a8641SAndroid Build Coastguard Worker                                 Sequence* sequence,
468*635a8641SAndroid Build Coastguard Worker                                 bool can_run_task) {
469*635a8641SAndroid Build Coastguard Worker   RecordLatencyHistogram(LatencyHistogramType::TASK_LATENCY, task.traits,
470*635a8641SAndroid Build Coastguard Worker                          task.sequenced_time);
471*635a8641SAndroid Build Coastguard Worker 
472*635a8641SAndroid Build Coastguard Worker   const bool previous_singleton_allowed =
473*635a8641SAndroid Build Coastguard Worker       ThreadRestrictions::SetSingletonAllowed(
474*635a8641SAndroid Build Coastguard Worker           task.traits.shutdown_behavior() !=
475*635a8641SAndroid Build Coastguard Worker           TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
476*635a8641SAndroid Build Coastguard Worker   const bool previous_io_allowed =
477*635a8641SAndroid Build Coastguard Worker       ThreadRestrictions::SetIOAllowed(task.traits.may_block());
478*635a8641SAndroid Build Coastguard Worker   const bool previous_wait_allowed = ThreadRestrictions::SetWaitAllowed(
479*635a8641SAndroid Build Coastguard Worker       task.traits.with_base_sync_primitives());
480*635a8641SAndroid Build Coastguard Worker 
481*635a8641SAndroid Build Coastguard Worker   {
482*635a8641SAndroid Build Coastguard Worker     const SequenceToken& sequence_token = sequence->token();
483*635a8641SAndroid Build Coastguard Worker     DCHECK(sequence_token.IsValid());
484*635a8641SAndroid Build Coastguard Worker     ScopedSetSequenceTokenForCurrentThread
485*635a8641SAndroid Build Coastguard Worker         scoped_set_sequence_token_for_current_thread(sequence_token);
486*635a8641SAndroid Build Coastguard Worker     ScopedSetTaskPriorityForCurrentThread
487*635a8641SAndroid Build Coastguard Worker         scoped_set_task_priority_for_current_thread(task.traits.priority());
488*635a8641SAndroid Build Coastguard Worker     ScopedSetSequenceLocalStorageMapForCurrentThread
489*635a8641SAndroid Build Coastguard Worker         scoped_set_sequence_local_storage_map_for_current_thread(
490*635a8641SAndroid Build Coastguard Worker             sequence->sequence_local_storage());
491*635a8641SAndroid Build Coastguard Worker 
492*635a8641SAndroid Build Coastguard Worker     // Set up TaskRunnerHandle as expected for the scope of the task.
493*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<SequencedTaskRunnerHandle> sequenced_task_runner_handle;
494*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<ThreadTaskRunnerHandle> single_thread_task_runner_handle;
495*635a8641SAndroid Build Coastguard Worker     DCHECK(!task.sequenced_task_runner_ref ||
496*635a8641SAndroid Build Coastguard Worker            !task.single_thread_task_runner_ref);
497*635a8641SAndroid Build Coastguard Worker     if (task.sequenced_task_runner_ref) {
498*635a8641SAndroid Build Coastguard Worker       sequenced_task_runner_handle.reset(
499*635a8641SAndroid Build Coastguard Worker           new SequencedTaskRunnerHandle(task.sequenced_task_runner_ref));
500*635a8641SAndroid Build Coastguard Worker     } else if (task.single_thread_task_runner_ref) {
501*635a8641SAndroid Build Coastguard Worker       single_thread_task_runner_handle.reset(
502*635a8641SAndroid Build Coastguard Worker           new ThreadTaskRunnerHandle(task.single_thread_task_runner_ref));
503*635a8641SAndroid Build Coastguard Worker     }
504*635a8641SAndroid Build Coastguard Worker 
505*635a8641SAndroid Build Coastguard Worker     if (can_run_task) {
506*635a8641SAndroid Build Coastguard Worker       TRACE_TASK_EXECUTION(kRunFunctionName, task);
507*635a8641SAndroid Build Coastguard Worker 
508*635a8641SAndroid Build Coastguard Worker       const char* const execution_mode =
509*635a8641SAndroid Build Coastguard Worker           task.single_thread_task_runner_ref
510*635a8641SAndroid Build Coastguard Worker               ? kSingleThreadExecutionMode
511*635a8641SAndroid Build Coastguard Worker               : (task.sequenced_task_runner_ref ? kSequencedExecutionMode
512*635a8641SAndroid Build Coastguard Worker                                                 : kParallelExecutionMode);
513*635a8641SAndroid Build Coastguard Worker       // TODO(gab): In a better world this would be tacked on as an extra arg
514*635a8641SAndroid Build Coastguard Worker       // to the trace event generated above. This is not possible however until
515*635a8641SAndroid Build Coastguard Worker       // http://crbug.com/652692 is resolved.
516*635a8641SAndroid Build Coastguard Worker       TRACE_EVENT1("task_scheduler", "TaskTracker::RunTask", "task_info",
517*635a8641SAndroid Build Coastguard Worker                    std::make_unique<TaskTracingInfo>(
518*635a8641SAndroid Build Coastguard Worker                        task.traits, execution_mode, sequence_token));
519*635a8641SAndroid Build Coastguard Worker 
520*635a8641SAndroid Build Coastguard Worker       {
521*635a8641SAndroid Build Coastguard Worker         // Put this in its own scope so it preceeds rather than overlaps with
522*635a8641SAndroid Build Coastguard Worker         // RunTask() in the trace view.
523*635a8641SAndroid Build Coastguard Worker         TRACE_EVENT_WITH_FLOW0(
524*635a8641SAndroid Build Coastguard Worker             kTaskSchedulerFlowTracingCategory, kQueueFunctionName,
525*635a8641SAndroid Build Coastguard Worker             TRACE_ID_MANGLE(task_annotator_.GetTaskTraceID(task)),
526*635a8641SAndroid Build Coastguard Worker             TRACE_EVENT_FLAG_FLOW_IN);
527*635a8641SAndroid Build Coastguard Worker       }
528*635a8641SAndroid Build Coastguard Worker 
529*635a8641SAndroid Build Coastguard Worker       task_annotator_.RunTask(nullptr, &task);
530*635a8641SAndroid Build Coastguard Worker     }
531*635a8641SAndroid Build Coastguard Worker 
532*635a8641SAndroid Build Coastguard Worker     // Make sure the arguments bound to the callback are deleted within the
533*635a8641SAndroid Build Coastguard Worker     // scope in which the callback runs.
534*635a8641SAndroid Build Coastguard Worker     task.task = OnceClosure();
535*635a8641SAndroid Build Coastguard Worker   }
536*635a8641SAndroid Build Coastguard Worker 
537*635a8641SAndroid Build Coastguard Worker   ThreadRestrictions::SetWaitAllowed(previous_wait_allowed);
538*635a8641SAndroid Build Coastguard Worker   ThreadRestrictions::SetIOAllowed(previous_io_allowed);
539*635a8641SAndroid Build Coastguard Worker   ThreadRestrictions::SetSingletonAllowed(previous_singleton_allowed);
540*635a8641SAndroid Build Coastguard Worker }
541*635a8641SAndroid Build Coastguard Worker 
PerformShutdown()542*635a8641SAndroid Build Coastguard Worker void TaskTracker::PerformShutdown() {
543*635a8641SAndroid Build Coastguard Worker   {
544*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(shutdown_lock_);
545*635a8641SAndroid Build Coastguard Worker 
546*635a8641SAndroid Build Coastguard Worker     // This method can only be called once.
547*635a8641SAndroid Build Coastguard Worker     DCHECK(!shutdown_event_);
548*635a8641SAndroid Build Coastguard Worker     DCHECK(!num_block_shutdown_tasks_posted_during_shutdown_);
549*635a8641SAndroid Build Coastguard Worker     DCHECK(!state_->HasShutdownStarted());
550*635a8641SAndroid Build Coastguard Worker 
551*635a8641SAndroid Build Coastguard Worker     shutdown_event_ = std::make_unique<WaitableEvent>();
552*635a8641SAndroid Build Coastguard Worker 
553*635a8641SAndroid Build Coastguard Worker     const bool tasks_are_blocking_shutdown = state_->StartShutdown();
554*635a8641SAndroid Build Coastguard Worker 
555*635a8641SAndroid Build Coastguard Worker     // From now, if a thread causes the number of tasks blocking shutdown to
556*635a8641SAndroid Build Coastguard Worker     // become zero, it will call OnBlockingShutdownTasksComplete().
557*635a8641SAndroid Build Coastguard Worker 
558*635a8641SAndroid Build Coastguard Worker     if (!tasks_are_blocking_shutdown) {
559*635a8641SAndroid Build Coastguard Worker       // If another thread posts a BLOCK_SHUTDOWN task at this moment, it will
560*635a8641SAndroid Build Coastguard Worker       // block until this method releases |shutdown_lock_|. Then, it will fail
561*635a8641SAndroid Build Coastguard Worker       // DCHECK(!shutdown_event_->IsSignaled()). This is the desired behavior
562*635a8641SAndroid Build Coastguard Worker       // because posting a BLOCK_SHUTDOWN task when TaskTracker::Shutdown() has
563*635a8641SAndroid Build Coastguard Worker       // started and no tasks are blocking shutdown isn't allowed.
564*635a8641SAndroid Build Coastguard Worker       shutdown_event_->Signal();
565*635a8641SAndroid Build Coastguard Worker       return;
566*635a8641SAndroid Build Coastguard Worker     }
567*635a8641SAndroid Build Coastguard Worker   }
568*635a8641SAndroid Build Coastguard Worker 
569*635a8641SAndroid Build Coastguard Worker   // Remove the cap on the maximum number of background sequences that can be
570*635a8641SAndroid Build Coastguard Worker   // scheduled concurrently. Done after starting shutdown to ensure that non-
571*635a8641SAndroid Build Coastguard Worker   // BLOCK_SHUTDOWN sequences don't get a chance to run and that BLOCK_SHUTDOWN
572*635a8641SAndroid Build Coastguard Worker   // sequences run on threads running with a normal priority.
573*635a8641SAndroid Build Coastguard Worker   SetMaxNumScheduledBackgroundSequences(std::numeric_limits<int>::max());
574*635a8641SAndroid Build Coastguard Worker 
575*635a8641SAndroid Build Coastguard Worker   // It is safe to access |shutdown_event_| without holding |lock_| because the
576*635a8641SAndroid Build Coastguard Worker   // pointer never changes after being set above.
577*635a8641SAndroid Build Coastguard Worker   {
578*635a8641SAndroid Build Coastguard Worker     base::ThreadRestrictions::ScopedAllowWait allow_wait;
579*635a8641SAndroid Build Coastguard Worker     shutdown_event_->Wait();
580*635a8641SAndroid Build Coastguard Worker   }
581*635a8641SAndroid Build Coastguard Worker 
582*635a8641SAndroid Build Coastguard Worker   {
583*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(shutdown_lock_);
584*635a8641SAndroid Build Coastguard Worker 
585*635a8641SAndroid Build Coastguard Worker     // Record TaskScheduler.BlockShutdownTasksPostedDuringShutdown if less than
586*635a8641SAndroid Build Coastguard Worker     // |kMaxBlockShutdownTasksPostedDuringShutdown| BLOCK_SHUTDOWN tasks were
587*635a8641SAndroid Build Coastguard Worker     // posted during shutdown. Otherwise, the histogram has already been
588*635a8641SAndroid Build Coastguard Worker     // recorded in BeforePostTask().
589*635a8641SAndroid Build Coastguard Worker     if (num_block_shutdown_tasks_posted_during_shutdown_ <
590*635a8641SAndroid Build Coastguard Worker         kMaxBlockShutdownTasksPostedDuringShutdown) {
591*635a8641SAndroid Build Coastguard Worker       RecordNumBlockShutdownTasksPostedDuringShutdown(
592*635a8641SAndroid Build Coastguard Worker           num_block_shutdown_tasks_posted_during_shutdown_);
593*635a8641SAndroid Build Coastguard Worker     }
594*635a8641SAndroid Build Coastguard Worker   }
595*635a8641SAndroid Build Coastguard Worker }
596*635a8641SAndroid Build Coastguard Worker 
SetMaxNumScheduledBackgroundSequences(int max_num_scheduled_background_sequences)597*635a8641SAndroid Build Coastguard Worker void TaskTracker::SetMaxNumScheduledBackgroundSequences(
598*635a8641SAndroid Build Coastguard Worker     int max_num_scheduled_background_sequences) {
599*635a8641SAndroid Build Coastguard Worker   std::vector<PreemptedBackgroundSequence> sequences_to_schedule;
600*635a8641SAndroid Build Coastguard Worker 
601*635a8641SAndroid Build Coastguard Worker   {
602*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(background_lock_);
603*635a8641SAndroid Build Coastguard Worker     max_num_scheduled_background_sequences_ =
604*635a8641SAndroid Build Coastguard Worker         max_num_scheduled_background_sequences;
605*635a8641SAndroid Build Coastguard Worker 
606*635a8641SAndroid Build Coastguard Worker     while (num_scheduled_background_sequences_ <
607*635a8641SAndroid Build Coastguard Worker                max_num_scheduled_background_sequences &&
608*635a8641SAndroid Build Coastguard Worker            !preempted_background_sequences_.empty()) {
609*635a8641SAndroid Build Coastguard Worker       sequences_to_schedule.push_back(
610*635a8641SAndroid Build Coastguard Worker           GetPreemptedBackgroundSequenceToScheduleLockRequired());
611*635a8641SAndroid Build Coastguard Worker     }
612*635a8641SAndroid Build Coastguard Worker   }
613*635a8641SAndroid Build Coastguard Worker 
614*635a8641SAndroid Build Coastguard Worker   for (auto& sequence_to_schedule : sequences_to_schedule)
615*635a8641SAndroid Build Coastguard Worker     SchedulePreemptedBackgroundSequence(std::move(sequence_to_schedule));
616*635a8641SAndroid Build Coastguard Worker }
617*635a8641SAndroid Build Coastguard Worker 
618*635a8641SAndroid Build Coastguard Worker TaskTracker::PreemptedBackgroundSequence
GetPreemptedBackgroundSequenceToScheduleLockRequired()619*635a8641SAndroid Build Coastguard Worker TaskTracker::GetPreemptedBackgroundSequenceToScheduleLockRequired() {
620*635a8641SAndroid Build Coastguard Worker   background_lock_.AssertAcquired();
621*635a8641SAndroid Build Coastguard Worker   DCHECK(!preempted_background_sequences_.empty());
622*635a8641SAndroid Build Coastguard Worker 
623*635a8641SAndroid Build Coastguard Worker   ++num_scheduled_background_sequences_;
624*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(num_scheduled_background_sequences_,
625*635a8641SAndroid Build Coastguard Worker             max_num_scheduled_background_sequences_);
626*635a8641SAndroid Build Coastguard Worker 
627*635a8641SAndroid Build Coastguard Worker   // The const_cast on top is okay since the PreemptedBackgroundSequence is
628*635a8641SAndroid Build Coastguard Worker   // transactionnaly being popped from |preempted_background_sequences_| right
629*635a8641SAndroid Build Coastguard Worker   // after and the move doesn't alter the sort order (a requirement for the
630*635a8641SAndroid Build Coastguard Worker   // Windows STL's consistency debug-checks for std::priority_queue::top()).
631*635a8641SAndroid Build Coastguard Worker   PreemptedBackgroundSequence popped_sequence =
632*635a8641SAndroid Build Coastguard Worker       std::move(const_cast<PreemptedBackgroundSequence&>(
633*635a8641SAndroid Build Coastguard Worker           preempted_background_sequences_.top()));
634*635a8641SAndroid Build Coastguard Worker   preempted_background_sequences_.pop();
635*635a8641SAndroid Build Coastguard Worker   return popped_sequence;
636*635a8641SAndroid Build Coastguard Worker }
637*635a8641SAndroid Build Coastguard Worker 
SchedulePreemptedBackgroundSequence(PreemptedBackgroundSequence sequence_to_schedule)638*635a8641SAndroid Build Coastguard Worker void TaskTracker::SchedulePreemptedBackgroundSequence(
639*635a8641SAndroid Build Coastguard Worker     PreemptedBackgroundSequence sequence_to_schedule) {
640*635a8641SAndroid Build Coastguard Worker   DCHECK(sequence_to_schedule.observer);
641*635a8641SAndroid Build Coastguard Worker   sequence_to_schedule.observer->OnCanScheduleSequence(
642*635a8641SAndroid Build Coastguard Worker       std::move(sequence_to_schedule.sequence));
643*635a8641SAndroid Build Coastguard Worker }
644*635a8641SAndroid Build Coastguard Worker 
645*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
IsPostingBlockShutdownTaskAfterShutdownAllowed()646*635a8641SAndroid Build Coastguard Worker bool TaskTracker::IsPostingBlockShutdownTaskAfterShutdownAllowed() {
647*635a8641SAndroid Build Coastguard Worker   return false;
648*635a8641SAndroid Build Coastguard Worker }
649*635a8641SAndroid Build Coastguard Worker #endif
650*635a8641SAndroid Build Coastguard Worker 
HasIncompleteUndelayedTasksForTesting() const651*635a8641SAndroid Build Coastguard Worker bool TaskTracker::HasIncompleteUndelayedTasksForTesting() const {
652*635a8641SAndroid Build Coastguard Worker   return subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) != 0;
653*635a8641SAndroid Build Coastguard Worker }
654*635a8641SAndroid Build Coastguard Worker 
BeforePostTask(TaskShutdownBehavior shutdown_behavior)655*635a8641SAndroid Build Coastguard Worker bool TaskTracker::BeforePostTask(TaskShutdownBehavior shutdown_behavior) {
656*635a8641SAndroid Build Coastguard Worker   if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
657*635a8641SAndroid Build Coastguard Worker     // BLOCK_SHUTDOWN tasks block shutdown between the moment they are posted
658*635a8641SAndroid Build Coastguard Worker     // and the moment they complete their execution.
659*635a8641SAndroid Build Coastguard Worker     const bool shutdown_started = state_->IncrementNumTasksBlockingShutdown();
660*635a8641SAndroid Build Coastguard Worker 
661*635a8641SAndroid Build Coastguard Worker     if (shutdown_started) {
662*635a8641SAndroid Build Coastguard Worker       AutoSchedulerLock auto_lock(shutdown_lock_);
663*635a8641SAndroid Build Coastguard Worker 
664*635a8641SAndroid Build Coastguard Worker       // A BLOCK_SHUTDOWN task posted after shutdown has completed is an
665*635a8641SAndroid Build Coastguard Worker       // ordering bug. This aims to catch those early.
666*635a8641SAndroid Build Coastguard Worker       DCHECK(shutdown_event_);
667*635a8641SAndroid Build Coastguard Worker       if (shutdown_event_->IsSignaled()) {
668*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
669*635a8641SAndroid Build Coastguard Worker // clang-format off
670*635a8641SAndroid Build Coastguard Worker         // TODO(robliao): http://crbug.com/698140. Since the service thread
671*635a8641SAndroid Build Coastguard Worker         // doesn't stop processing its own tasks at shutdown, we may still
672*635a8641SAndroid Build Coastguard Worker         // attempt to post a BLOCK_SHUTDOWN task in response to a
673*635a8641SAndroid Build Coastguard Worker         // FileDescriptorWatcher. Same is true for FilePathWatcher
674*635a8641SAndroid Build Coastguard Worker         // (http://crbug.com/728235). Until it's possible for such services to
675*635a8641SAndroid Build Coastguard Worker         // post to non-BLOCK_SHUTDOWN sequences which are themselves funneled to
676*635a8641SAndroid Build Coastguard Worker         // the main execution sequence (a future plan for the post_task.h API),
677*635a8641SAndroid Build Coastguard Worker         // this DCHECK will be flaky and must be disabled.
678*635a8641SAndroid Build Coastguard Worker         // DCHECK(IsPostingBlockShutdownTaskAfterShutdownAllowed());
679*635a8641SAndroid Build Coastguard Worker // clang-format on
680*635a8641SAndroid Build Coastguard Worker #endif
681*635a8641SAndroid Build Coastguard Worker         state_->DecrementNumTasksBlockingShutdown();
682*635a8641SAndroid Build Coastguard Worker         return false;
683*635a8641SAndroid Build Coastguard Worker       }
684*635a8641SAndroid Build Coastguard Worker 
685*635a8641SAndroid Build Coastguard Worker       ++num_block_shutdown_tasks_posted_during_shutdown_;
686*635a8641SAndroid Build Coastguard Worker 
687*635a8641SAndroid Build Coastguard Worker       if (num_block_shutdown_tasks_posted_during_shutdown_ ==
688*635a8641SAndroid Build Coastguard Worker           kMaxBlockShutdownTasksPostedDuringShutdown) {
689*635a8641SAndroid Build Coastguard Worker         // Record the TaskScheduler.BlockShutdownTasksPostedDuringShutdown
690*635a8641SAndroid Build Coastguard Worker         // histogram as soon as its upper bound is hit. That way, a value will
691*635a8641SAndroid Build Coastguard Worker         // be recorded even if an infinite number of BLOCK_SHUTDOWN tasks are
692*635a8641SAndroid Build Coastguard Worker         // posted, preventing shutdown to complete.
693*635a8641SAndroid Build Coastguard Worker         RecordNumBlockShutdownTasksPostedDuringShutdown(
694*635a8641SAndroid Build Coastguard Worker             num_block_shutdown_tasks_posted_during_shutdown_);
695*635a8641SAndroid Build Coastguard Worker       }
696*635a8641SAndroid Build Coastguard Worker     }
697*635a8641SAndroid Build Coastguard Worker 
698*635a8641SAndroid Build Coastguard Worker     return true;
699*635a8641SAndroid Build Coastguard Worker   }
700*635a8641SAndroid Build Coastguard Worker 
701*635a8641SAndroid Build Coastguard Worker   // A non BLOCK_SHUTDOWN task is allowed to be posted iff shutdown hasn't
702*635a8641SAndroid Build Coastguard Worker   // started.
703*635a8641SAndroid Build Coastguard Worker   return !state_->HasShutdownStarted();
704*635a8641SAndroid Build Coastguard Worker }
705*635a8641SAndroid Build Coastguard Worker 
BeforeRunTask(TaskShutdownBehavior shutdown_behavior)706*635a8641SAndroid Build Coastguard Worker bool TaskTracker::BeforeRunTask(TaskShutdownBehavior shutdown_behavior) {
707*635a8641SAndroid Build Coastguard Worker   switch (shutdown_behavior) {
708*635a8641SAndroid Build Coastguard Worker     case TaskShutdownBehavior::BLOCK_SHUTDOWN: {
709*635a8641SAndroid Build Coastguard Worker       // The number of tasks blocking shutdown has been incremented when the
710*635a8641SAndroid Build Coastguard Worker       // task was posted.
711*635a8641SAndroid Build Coastguard Worker       DCHECK(state_->AreTasksBlockingShutdown());
712*635a8641SAndroid Build Coastguard Worker 
713*635a8641SAndroid Build Coastguard Worker       // Trying to run a BLOCK_SHUTDOWN task after shutdown has completed is
714*635a8641SAndroid Build Coastguard Worker       // unexpected as it either shouldn't have been posted if shutdown
715*635a8641SAndroid Build Coastguard Worker       // completed or should be blocking shutdown if it was posted before it
716*635a8641SAndroid Build Coastguard Worker       // did.
717*635a8641SAndroid Build Coastguard Worker       DCHECK(!state_->HasShutdownStarted() || !IsShutdownComplete());
718*635a8641SAndroid Build Coastguard Worker 
719*635a8641SAndroid Build Coastguard Worker       return true;
720*635a8641SAndroid Build Coastguard Worker     }
721*635a8641SAndroid Build Coastguard Worker 
722*635a8641SAndroid Build Coastguard Worker     case TaskShutdownBehavior::SKIP_ON_SHUTDOWN: {
723*635a8641SAndroid Build Coastguard Worker       // SKIP_ON_SHUTDOWN tasks block shutdown while they are running.
724*635a8641SAndroid Build Coastguard Worker       const bool shutdown_started = state_->IncrementNumTasksBlockingShutdown();
725*635a8641SAndroid Build Coastguard Worker 
726*635a8641SAndroid Build Coastguard Worker       if (shutdown_started) {
727*635a8641SAndroid Build Coastguard Worker         // The SKIP_ON_SHUTDOWN task isn't allowed to run during shutdown.
728*635a8641SAndroid Build Coastguard Worker         // Decrement the number of tasks blocking shutdown that was wrongly
729*635a8641SAndroid Build Coastguard Worker         // incremented.
730*635a8641SAndroid Build Coastguard Worker         const bool shutdown_started_and_no_tasks_block_shutdown =
731*635a8641SAndroid Build Coastguard Worker             state_->DecrementNumTasksBlockingShutdown();
732*635a8641SAndroid Build Coastguard Worker         if (shutdown_started_and_no_tasks_block_shutdown)
733*635a8641SAndroid Build Coastguard Worker           OnBlockingShutdownTasksComplete();
734*635a8641SAndroid Build Coastguard Worker 
735*635a8641SAndroid Build Coastguard Worker         return false;
736*635a8641SAndroid Build Coastguard Worker       }
737*635a8641SAndroid Build Coastguard Worker 
738*635a8641SAndroid Build Coastguard Worker       return true;
739*635a8641SAndroid Build Coastguard Worker     }
740*635a8641SAndroid Build Coastguard Worker 
741*635a8641SAndroid Build Coastguard Worker     case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN: {
742*635a8641SAndroid Build Coastguard Worker       return !state_->HasShutdownStarted();
743*635a8641SAndroid Build Coastguard Worker     }
744*635a8641SAndroid Build Coastguard Worker   }
745*635a8641SAndroid Build Coastguard Worker 
746*635a8641SAndroid Build Coastguard Worker   NOTREACHED();
747*635a8641SAndroid Build Coastguard Worker   return false;
748*635a8641SAndroid Build Coastguard Worker }
749*635a8641SAndroid Build Coastguard Worker 
AfterRunTask(TaskShutdownBehavior shutdown_behavior)750*635a8641SAndroid Build Coastguard Worker void TaskTracker::AfterRunTask(TaskShutdownBehavior shutdown_behavior) {
751*635a8641SAndroid Build Coastguard Worker   if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN ||
752*635a8641SAndroid Build Coastguard Worker       shutdown_behavior == TaskShutdownBehavior::SKIP_ON_SHUTDOWN) {
753*635a8641SAndroid Build Coastguard Worker     const bool shutdown_started_and_no_tasks_block_shutdown =
754*635a8641SAndroid Build Coastguard Worker         state_->DecrementNumTasksBlockingShutdown();
755*635a8641SAndroid Build Coastguard Worker     if (shutdown_started_and_no_tasks_block_shutdown)
756*635a8641SAndroid Build Coastguard Worker       OnBlockingShutdownTasksComplete();
757*635a8641SAndroid Build Coastguard Worker   }
758*635a8641SAndroid Build Coastguard Worker }
759*635a8641SAndroid Build Coastguard Worker 
OnBlockingShutdownTasksComplete()760*635a8641SAndroid Build Coastguard Worker void TaskTracker::OnBlockingShutdownTasksComplete() {
761*635a8641SAndroid Build Coastguard Worker   AutoSchedulerLock auto_lock(shutdown_lock_);
762*635a8641SAndroid Build Coastguard Worker 
763*635a8641SAndroid Build Coastguard Worker   // This method can only be called after shutdown has started.
764*635a8641SAndroid Build Coastguard Worker   DCHECK(state_->HasShutdownStarted());
765*635a8641SAndroid Build Coastguard Worker   DCHECK(shutdown_event_);
766*635a8641SAndroid Build Coastguard Worker 
767*635a8641SAndroid Build Coastguard Worker   shutdown_event_->Signal();
768*635a8641SAndroid Build Coastguard Worker }
769*635a8641SAndroid Build Coastguard Worker 
DecrementNumIncompleteUndelayedTasks()770*635a8641SAndroid Build Coastguard Worker void TaskTracker::DecrementNumIncompleteUndelayedTasks() {
771*635a8641SAndroid Build Coastguard Worker   const auto new_num_incomplete_undelayed_tasks =
772*635a8641SAndroid Build Coastguard Worker       subtle::Barrier_AtomicIncrement(&num_incomplete_undelayed_tasks_, -1);
773*635a8641SAndroid Build Coastguard Worker   DCHECK_GE(new_num_incomplete_undelayed_tasks, 0);
774*635a8641SAndroid Build Coastguard Worker   if (new_num_incomplete_undelayed_tasks == 0) {
775*635a8641SAndroid Build Coastguard Worker     {
776*635a8641SAndroid Build Coastguard Worker       AutoSchedulerLock auto_lock(flush_lock_);
777*635a8641SAndroid Build Coastguard Worker       flush_cv_->Signal();
778*635a8641SAndroid Build Coastguard Worker     }
779*635a8641SAndroid Build Coastguard Worker     CallFlushCallbackForTesting();
780*635a8641SAndroid Build Coastguard Worker   }
781*635a8641SAndroid Build Coastguard Worker }
782*635a8641SAndroid Build Coastguard Worker 
ManageBackgroundSequencesAfterRunningTask(scoped_refptr<Sequence> just_ran_sequence,CanScheduleSequenceObserver * observer)783*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> TaskTracker::ManageBackgroundSequencesAfterRunningTask(
784*635a8641SAndroid Build Coastguard Worker     scoped_refptr<Sequence> just_ran_sequence,
785*635a8641SAndroid Build Coastguard Worker     CanScheduleSequenceObserver* observer) {
786*635a8641SAndroid Build Coastguard Worker   const TimeTicks next_task_sequenced_time =
787*635a8641SAndroid Build Coastguard Worker       just_ran_sequence
788*635a8641SAndroid Build Coastguard Worker           ? just_ran_sequence->GetSortKey().next_task_sequenced_time()
789*635a8641SAndroid Build Coastguard Worker           : TimeTicks();
790*635a8641SAndroid Build Coastguard Worker   PreemptedBackgroundSequence sequence_to_schedule;
791*635a8641SAndroid Build Coastguard Worker 
792*635a8641SAndroid Build Coastguard Worker   {
793*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(background_lock_);
794*635a8641SAndroid Build Coastguard Worker 
795*635a8641SAndroid Build Coastguard Worker     DCHECK(preempted_background_sequences_.empty() ||
796*635a8641SAndroid Build Coastguard Worker            num_scheduled_background_sequences_ ==
797*635a8641SAndroid Build Coastguard Worker                max_num_scheduled_background_sequences_);
798*635a8641SAndroid Build Coastguard Worker     --num_scheduled_background_sequences_;
799*635a8641SAndroid Build Coastguard Worker 
800*635a8641SAndroid Build Coastguard Worker     if (just_ran_sequence) {
801*635a8641SAndroid Build Coastguard Worker       if (preempted_background_sequences_.empty() ||
802*635a8641SAndroid Build Coastguard Worker           preempted_background_sequences_.top().next_task_sequenced_time >
803*635a8641SAndroid Build Coastguard Worker               next_task_sequenced_time) {
804*635a8641SAndroid Build Coastguard Worker         ++num_scheduled_background_sequences_;
805*635a8641SAndroid Build Coastguard Worker         return just_ran_sequence;
806*635a8641SAndroid Build Coastguard Worker       }
807*635a8641SAndroid Build Coastguard Worker 
808*635a8641SAndroid Build Coastguard Worker       preempted_background_sequences_.emplace(
809*635a8641SAndroid Build Coastguard Worker           std::move(just_ran_sequence), next_task_sequenced_time, observer);
810*635a8641SAndroid Build Coastguard Worker     }
811*635a8641SAndroid Build Coastguard Worker 
812*635a8641SAndroid Build Coastguard Worker     if (!preempted_background_sequences_.empty()) {
813*635a8641SAndroid Build Coastguard Worker       sequence_to_schedule =
814*635a8641SAndroid Build Coastguard Worker           GetPreemptedBackgroundSequenceToScheduleLockRequired();
815*635a8641SAndroid Build Coastguard Worker     }
816*635a8641SAndroid Build Coastguard Worker   }
817*635a8641SAndroid Build Coastguard Worker 
818*635a8641SAndroid Build Coastguard Worker   // |sequence_to_schedule.sequence| may be null if there was no preempted
819*635a8641SAndroid Build Coastguard Worker   // background sequence.
820*635a8641SAndroid Build Coastguard Worker   if (sequence_to_schedule.sequence)
821*635a8641SAndroid Build Coastguard Worker     SchedulePreemptedBackgroundSequence(std::move(sequence_to_schedule));
822*635a8641SAndroid Build Coastguard Worker 
823*635a8641SAndroid Build Coastguard Worker   return nullptr;
824*635a8641SAndroid Build Coastguard Worker }
825*635a8641SAndroid Build Coastguard Worker 
CallFlushCallbackForTesting()826*635a8641SAndroid Build Coastguard Worker void TaskTracker::CallFlushCallbackForTesting() {
827*635a8641SAndroid Build Coastguard Worker   OnceClosure flush_callback;
828*635a8641SAndroid Build Coastguard Worker   {
829*635a8641SAndroid Build Coastguard Worker     AutoSchedulerLock auto_lock(flush_lock_);
830*635a8641SAndroid Build Coastguard Worker     flush_callback = std::move(flush_callback_for_testing_);
831*635a8641SAndroid Build Coastguard Worker   }
832*635a8641SAndroid Build Coastguard Worker   if (flush_callback)
833*635a8641SAndroid Build Coastguard Worker     std::move(flush_callback).Run();
834*635a8641SAndroid Build Coastguard Worker }
835*635a8641SAndroid Build Coastguard Worker 
836*635a8641SAndroid Build Coastguard Worker }  // namespace internal
837*635a8641SAndroid Build Coastguard Worker }  // namespace base
838