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