Home | History | Annotate | Download | only in sequence_manager
      1 // Copyright 2018 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/task/sequence_manager/sequence_manager_impl.h"
      6 
      7 #include <queue>
      8 #include <vector>
      9 
     10 #include "base/bind.h"
     11 #include "base/bit_cast.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/debug/crash_logging.h"
     14 #include "base/memory/ptr_util.h"
     15 #include "base/metrics/histogram_macros.h"
     16 #include "base/rand_util.h"
     17 #include "base/task/sequence_manager/real_time_domain.h"
     18 #include "base/task/sequence_manager/task_time_observer.h"
     19 #include "base/task/sequence_manager/thread_controller_impl.h"
     20 #include "base/task/sequence_manager/work_queue.h"
     21 #include "base/task/sequence_manager/work_queue_sets.h"
     22 #include "base/time/default_tick_clock.h"
     23 #include "base/time/tick_clock.h"
     24 #include "base/trace_event/trace_event.h"
     25 #include "build/build_config.h"
     26 
     27 namespace base {
     28 namespace sequence_manager {
     29 
     30 std::unique_ptr<SequenceManager> CreateSequenceManagerOnCurrentThread() {
     31   return internal::SequenceManagerImpl::CreateOnCurrentThread();
     32 }
     33 
     34 namespace internal {
     35 
     36 namespace {
     37 
     38 constexpr base::TimeDelta kLongTaskTraceEventThreshold =
     39     base::TimeDelta::FromMilliseconds(50);
     40 // Proportion of tasks which will record thread time for metrics.
     41 const double kTaskSamplingRateForRecordingCPUTime = 0.01;
     42 // Proprortion of SequenceManagers which will record thread time for each task,
     43 // enabling advanced metrics.
     44 const double kThreadSamplingRateForRecordingCPUTime = 0.0001;
     45 
     46 // Magic value to protect against memory corruption and bail out
     47 // early when detected.
     48 constexpr int kMemoryCorruptionSentinelValue = 0xdeadbeef;
     49 
     50 void SweepCanceledDelayedTasksInQueue(
     51     internal::TaskQueueImpl* queue,
     52     std::map<TimeDomain*, TimeTicks>* time_domain_now) {
     53   TimeDomain* time_domain = queue->GetTimeDomain();
     54   if (time_domain_now->find(time_domain) == time_domain_now->end())
     55     time_domain_now->insert(std::make_pair(time_domain, time_domain->Now()));
     56   queue->SweepCanceledDelayedTasks(time_domain_now->at(time_domain));
     57 }
     58 
     59 SequenceManager::MetricRecordingSettings InitializeMetricRecordingSettings() {
     60   bool cpu_time_recording_always_on =
     61       base::RandDouble() < kThreadSamplingRateForRecordingCPUTime;
     62   return SequenceManager::MetricRecordingSettings(
     63       cpu_time_recording_always_on, kTaskSamplingRateForRecordingCPUTime);
     64 }
     65 
     66 }  // namespace
     67 
     68 SequenceManagerImpl::SequenceManagerImpl(
     69     std::unique_ptr<internal::ThreadController> controller)
     70     : graceful_shutdown_helper_(new internal::GracefulQueueShutdownHelper()),
     71       controller_(std::move(controller)),
     72       metric_recording_settings_(InitializeMetricRecordingSettings()),
     73       memory_corruption_sentinel_(kMemoryCorruptionSentinelValue),
     74       weak_factory_(this) {
     75   // TODO(altimin): Create a sequence checker here.
     76   DCHECK(controller_->RunsTasksInCurrentSequence());
     77 
     78   TRACE_EVENT_WARMUP_CATEGORY("sequence_manager");
     79   TRACE_EVENT_WARMUP_CATEGORY(TRACE_DISABLED_BY_DEFAULT("sequence_manager"));
     80   TRACE_EVENT_WARMUP_CATEGORY(
     81       TRACE_DISABLED_BY_DEFAULT("sequence_manager.debug"));
     82   TRACE_EVENT_WARMUP_CATEGORY(
     83       TRACE_DISABLED_BY_DEFAULT("sequence_manager.verbose_snapshots"));
     84 
     85   TRACE_EVENT_OBJECT_CREATED_WITH_ID(
     86       TRACE_DISABLED_BY_DEFAULT("sequence_manager"), "SequenceManager", this);
     87   main_thread_only().selector.SetTaskQueueSelectorObserver(this);
     88 
     89   RegisterTimeDomain(main_thread_only().real_time_domain.get());
     90 
     91   controller_->SetSequencedTaskSource(this);
     92   controller_->AddNestingObserver(this);
     93 }
     94 
     95 SequenceManagerImpl::~SequenceManagerImpl() {
     96   TRACE_EVENT_OBJECT_DELETED_WITH_ID(
     97       TRACE_DISABLED_BY_DEFAULT("sequence_manager"), "SequenceManager", this);
     98 
     99   // TODO(altimin): restore default task runner automatically when
    100   // ThreadController is destroyed.
    101   controller_->RestoreDefaultTaskRunner();
    102 
    103   for (internal::TaskQueueImpl* queue : main_thread_only().active_queues) {
    104     main_thread_only().selector.RemoveQueue(queue);
    105     queue->UnregisterTaskQueue();
    106   }
    107 
    108   main_thread_only().active_queues.clear();
    109   main_thread_only().queues_to_gracefully_shutdown.clear();
    110 
    111   graceful_shutdown_helper_->OnSequenceManagerDeleted();
    112 
    113   main_thread_only().selector.SetTaskQueueSelectorObserver(nullptr);
    114   controller_->RemoveNestingObserver(this);
    115 }
    116 
    117 SequenceManagerImpl::AnyThread::AnyThread() = default;
    118 
    119 SequenceManagerImpl::AnyThread::~AnyThread() = default;
    120 
    121 SequenceManagerImpl::MainThreadOnly::MainThreadOnly()
    122     : random_generator(RandUint64()),
    123       uniform_distribution(0.0, 1.0),
    124       real_time_domain(new internal::RealTimeDomain()) {}
    125 
    126 SequenceManagerImpl::MainThreadOnly::~MainThreadOnly() = default;
    127 
    128 // static
    129 std::unique_ptr<SequenceManagerImpl>
    130 SequenceManagerImpl::CreateOnCurrentThread() {
    131   return WrapUnique(
    132       new SequenceManagerImpl(internal::ThreadControllerImpl::Create(
    133           MessageLoop::current(), DefaultTickClock::GetInstance())));
    134 }
    135 
    136 void SequenceManagerImpl::RegisterTimeDomain(TimeDomain* time_domain) {
    137   main_thread_only().time_domains.insert(time_domain);
    138   time_domain->OnRegisterWithSequenceManager(this);
    139 }
    140 
    141 void SequenceManagerImpl::UnregisterTimeDomain(TimeDomain* time_domain) {
    142   main_thread_only().time_domains.erase(time_domain);
    143 }
    144 
    145 TimeDomain* SequenceManagerImpl::GetRealTimeDomain() const {
    146   return main_thread_only().real_time_domain.get();
    147 }
    148 
    149 std::unique_ptr<internal::TaskQueueImpl>
    150 SequenceManagerImpl::CreateTaskQueueImpl(const TaskQueue::Spec& spec) {
    151   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    152   TimeDomain* time_domain = spec.time_domain
    153                                 ? spec.time_domain
    154                                 : main_thread_only().real_time_domain.get();
    155   DCHECK(main_thread_only().time_domains.find(time_domain) !=
    156          main_thread_only().time_domains.end());
    157   std::unique_ptr<internal::TaskQueueImpl> task_queue =
    158       std::make_unique<internal::TaskQueueImpl>(this, time_domain, spec);
    159   main_thread_only().active_queues.insert(task_queue.get());
    160   main_thread_only().selector.AddQueue(task_queue.get());
    161   return task_queue;
    162 }
    163 
    164 void SequenceManagerImpl::SetObserver(Observer* observer) {
    165   main_thread_only().observer = observer;
    166 }
    167 
    168 bool SequenceManagerImpl::AddToIncomingImmediateWorkList(
    169     internal::TaskQueueImpl* task_queue,
    170     internal::EnqueueOrder enqueue_order) {
    171   AutoLock lock(any_thread_lock_);
    172   // Check if |task_queue| is already in the linked list.
    173   if (task_queue->immediate_work_list_storage()->queue)
    174     return false;
    175 
    176   // Insert into the linked list.
    177   task_queue->immediate_work_list_storage()->queue = task_queue;
    178   task_queue->immediate_work_list_storage()->order = enqueue_order;
    179   task_queue->immediate_work_list_storage()->next =
    180       any_thread().incoming_immediate_work_list;
    181   any_thread().incoming_immediate_work_list =
    182       task_queue->immediate_work_list_storage();
    183   return true;
    184 }
    185 
    186 void SequenceManagerImpl::RemoveFromIncomingImmediateWorkList(
    187     internal::TaskQueueImpl* task_queue) {
    188   AutoLock lock(any_thread_lock_);
    189   internal::IncomingImmediateWorkList** prev =
    190       &any_thread().incoming_immediate_work_list;
    191   while (*prev) {
    192     if ((*prev)->queue == task_queue) {
    193       *prev = (*prev)->next;
    194       break;
    195     }
    196     prev = &(*prev)->next;
    197   }
    198 
    199   task_queue->immediate_work_list_storage()->next = nullptr;
    200   task_queue->immediate_work_list_storage()->queue = nullptr;
    201 }
    202 
    203 void SequenceManagerImpl::UnregisterTaskQueueImpl(
    204     std::unique_ptr<internal::TaskQueueImpl> task_queue) {
    205   TRACE_EVENT1("sequence_manager", "SequenceManagerImpl::UnregisterTaskQueue",
    206                "queue_name", task_queue->GetName());
    207   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    208 
    209   main_thread_only().selector.RemoveQueue(task_queue.get());
    210 
    211   // After UnregisterTaskQueue returns no new tasks can be posted.
    212   // It's important to call it first to avoid race condition between removing
    213   // the task queue from various lists here and adding it to the same lists
    214   // when posting a task.
    215   task_queue->UnregisterTaskQueue();
    216 
    217   // Remove |task_queue| from the linked list if present.
    218   // This is O(n).  We assume this will be a relatively infrequent operation.
    219   RemoveFromIncomingImmediateWorkList(task_queue.get());
    220 
    221   // Add |task_queue| to |main_thread_only().queues_to_delete| so we can prevent
    222   // it from being freed while any of our structures hold hold a raw pointer to
    223   // it.
    224   main_thread_only().active_queues.erase(task_queue.get());
    225   main_thread_only().queues_to_delete[task_queue.get()] = std::move(task_queue);
    226 }
    227 
    228 void SequenceManagerImpl::ReloadEmptyWorkQueues() {
    229   // There are two cases where a queue needs reloading.  First, it might be
    230   // completely empty and we've just posted a task (this method handles that
    231   // case). Secondly if the work queue becomes empty in when calling
    232   // WorkQueue::TakeTaskFromWorkQueue (handled there).
    233   for (internal::TaskQueueImpl* queue : main_thread_only().queues_to_reload) {
    234     queue->ReloadImmediateWorkQueueIfEmpty();
    235   }
    236 }
    237 
    238 void SequenceManagerImpl::WakeUpReadyDelayedQueues(LazyNow* lazy_now) {
    239   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    240                "SequenceManagerImpl::WakeUpReadyDelayedQueues");
    241 
    242   for (TimeDomain* time_domain : main_thread_only().time_domains) {
    243     if (time_domain == main_thread_only().real_time_domain.get()) {
    244       time_domain->WakeUpReadyDelayedQueues(lazy_now);
    245     } else {
    246       LazyNow time_domain_lazy_now = time_domain->CreateLazyNow();
    247       time_domain->WakeUpReadyDelayedQueues(&time_domain_lazy_now);
    248     }
    249   }
    250 }
    251 
    252 void SequenceManagerImpl::OnBeginNestedRunLoop() {
    253   main_thread_only().nesting_depth++;
    254   if (main_thread_only().observer)
    255     main_thread_only().observer->OnBeginNestedRunLoop();
    256 }
    257 
    258 void SequenceManagerImpl::OnExitNestedRunLoop() {
    259   main_thread_only().nesting_depth--;
    260   DCHECK_GE(main_thread_only().nesting_depth, 0);
    261   if (main_thread_only().nesting_depth == 0) {
    262     // While we were nested some non-nestable tasks may have been deferred.
    263     // We push them back onto the *front* of their original work queues,
    264     // that's why we iterate |non_nestable_task_queue| in FIFO order.
    265     while (!main_thread_only().non_nestable_task_queue.empty()) {
    266       internal::TaskQueueImpl::DeferredNonNestableTask& non_nestable_task =
    267           main_thread_only().non_nestable_task_queue.back();
    268       non_nestable_task.task_queue->RequeueDeferredNonNestableTask(
    269           std::move(non_nestable_task));
    270       main_thread_only().non_nestable_task_queue.pop_back();
    271     }
    272   }
    273   if (main_thread_only().observer)
    274     main_thread_only().observer->OnExitNestedRunLoop();
    275 }
    276 
    277 void SequenceManagerImpl::OnQueueHasIncomingImmediateWork(
    278     internal::TaskQueueImpl* queue,
    279     internal::EnqueueOrder enqueue_order,
    280     bool queue_is_blocked) {
    281   if (AddToIncomingImmediateWorkList(queue, enqueue_order) && !queue_is_blocked)
    282     controller_->ScheduleWork();
    283 }
    284 
    285 void SequenceManagerImpl::MaybeScheduleImmediateWork(
    286     const Location& from_here) {
    287   controller_->ScheduleWork();
    288 }
    289 
    290 void SequenceManagerImpl::SetNextDelayedDoWork(LazyNow* lazy_now,
    291                                                TimeTicks run_time) {
    292   controller_->SetNextDelayedDoWork(lazy_now, run_time);
    293 }
    294 
    295 Optional<PendingTask> SequenceManagerImpl::TakeTask() {
    296   CHECK(Validate());
    297 
    298   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    299   TRACE_EVENT0("sequence_manager", "SequenceManagerImpl::TakeTask");
    300 
    301   {
    302     AutoLock lock(any_thread_lock_);
    303     main_thread_only().queues_to_reload.clear();
    304 
    305     for (internal::IncomingImmediateWorkList* iter =
    306              any_thread().incoming_immediate_work_list;
    307          iter; iter = iter->next) {
    308       main_thread_only().queues_to_reload.push_back(iter->queue);
    309       iter->queue = nullptr;
    310     }
    311 
    312     any_thread().incoming_immediate_work_list = nullptr;
    313   }
    314 
    315   // It's important we call ReloadEmptyWorkQueues out side of the lock to
    316   // avoid a lock order inversion.
    317   ReloadEmptyWorkQueues();
    318   LazyNow lazy_now(controller_->GetClock());
    319   WakeUpReadyDelayedQueues(&lazy_now);
    320 
    321   while (true) {
    322     internal::WorkQueue* work_queue = nullptr;
    323     bool should_run =
    324         main_thread_only().selector.SelectWorkQueueToService(&work_queue);
    325     TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
    326         TRACE_DISABLED_BY_DEFAULT("sequence_manager.debug"), "SequenceManager",
    327         this, AsValueWithSelectorResult(should_run, work_queue));
    328 
    329     if (!should_run)
    330       return nullopt;
    331 
    332     // If the head task was canceled, remove it and run the selector again.
    333     if (work_queue->RemoveAllCanceledTasksFromFront())
    334       continue;
    335 
    336     if (work_queue->GetFrontTask()->nestable == Nestable::kNonNestable &&
    337         main_thread_only().nesting_depth > 0) {
    338       // Defer non-nestable work. NOTE these tasks can be arbitrarily delayed so
    339       // the additional delay should not be a problem.
    340       // Note because we don't delete queues while nested, it's perfectly OK to
    341       // store the raw pointer for |queue| here.
    342       internal::TaskQueueImpl::DeferredNonNestableTask deferred_task{
    343           work_queue->TakeTaskFromWorkQueue(), work_queue->task_queue(),
    344           work_queue->queue_type()};
    345       main_thread_only().non_nestable_task_queue.push_back(
    346           std::move(deferred_task));
    347       continue;
    348     }
    349 
    350     main_thread_only().task_execution_stack.emplace_back(
    351         work_queue->TakeTaskFromWorkQueue(), work_queue->task_queue(),
    352         InitializeTaskTiming(work_queue->task_queue()));
    353 
    354     UMA_HISTOGRAM_COUNTS_1000("TaskQueueManager.ActiveQueuesCount",
    355                               main_thread_only().active_queues.size());
    356 
    357     ExecutingTask& executing_task =
    358         *main_thread_only().task_execution_stack.rbegin();
    359     NotifyWillProcessTask(&executing_task, &lazy_now);
    360     return std::move(executing_task.pending_task);
    361   }
    362 }
    363 
    364 void SequenceManagerImpl::DidRunTask() {
    365   LazyNow lazy_now(controller_->GetClock());
    366   ExecutingTask& executing_task =
    367       *main_thread_only().task_execution_stack.rbegin();
    368   NotifyDidProcessTask(&executing_task, &lazy_now);
    369   main_thread_only().task_execution_stack.pop_back();
    370 
    371   if (main_thread_only().nesting_depth == 0)
    372     CleanUpQueues();
    373 }
    374 
    375 TimeDelta SequenceManagerImpl::DelayTillNextTask(LazyNow* lazy_now) {
    376   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    377 
    378   // If the selector has non-empty queues we trivially know there is immediate
    379   // work to be done.
    380   if (!main_thread_only().selector.AllEnabledWorkQueuesAreEmpty())
    381     return TimeDelta();
    382 
    383   // Its possible the selectors state is dirty because ReloadEmptyWorkQueues
    384   // hasn't been called yet. This check catches the case of fresh incoming work.
    385   {
    386     AutoLock lock(any_thread_lock_);
    387     for (const internal::IncomingImmediateWorkList* iter =
    388              any_thread().incoming_immediate_work_list;
    389          iter; iter = iter->next) {
    390       if (iter->queue->CouldTaskRun(iter->order))
    391         return TimeDelta();
    392     }
    393   }
    394 
    395   // Otherwise we need to find the shortest delay, if any.  NB we don't need to
    396   // call WakeUpReadyDelayedQueues because it's assumed DelayTillNextTask will
    397   // return TimeDelta>() if the delayed task is due to run now.
    398   TimeDelta delay_till_next_task = TimeDelta::Max();
    399   for (TimeDomain* time_domain : main_thread_only().time_domains) {
    400     Optional<TimeDelta> delay = time_domain->DelayTillNextTask(lazy_now);
    401     if (!delay)
    402       continue;
    403 
    404     if (*delay < delay_till_next_task)
    405       delay_till_next_task = *delay;
    406   }
    407   return delay_till_next_task;
    408 }
    409 
    410 void SequenceManagerImpl::WillQueueTask(
    411     internal::TaskQueueImpl::Task* pending_task) {
    412   controller_->WillQueueTask(pending_task);
    413 }
    414 
    415 TaskQueue::TaskTiming SequenceManagerImpl::InitializeTaskTiming(
    416     internal::TaskQueueImpl* task_queue) {
    417   bool records_wall_time =
    418       (task_queue->GetShouldNotifyObservers() &&
    419        main_thread_only().task_time_observers.might_have_observers()) ||
    420       task_queue->RequiresTaskTiming();
    421   bool records_thread_time = records_wall_time && ShouldRecordCPUTimeForTask();
    422   return TaskQueue::TaskTiming(records_wall_time, records_thread_time);
    423 }
    424 
    425 void SequenceManagerImpl::NotifyWillProcessTask(ExecutingTask* executing_task,
    426                                                 LazyNow* time_before_task) {
    427   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    428                "SequenceManagerImpl::NotifyWillProcessTaskObservers");
    429   if (executing_task->task_queue->GetQuiescenceMonitored())
    430     main_thread_only().task_was_run_on_quiescence_monitored_queue = true;
    431 
    432 #if !defined(OS_NACL)
    433   debug::SetCrashKeyString(
    434       main_thread_only().file_name_crash_key,
    435       executing_task->pending_task.posted_from.file_name());
    436   debug::SetCrashKeyString(
    437       main_thread_only().function_name_crash_key,
    438       executing_task->pending_task.posted_from.function_name());
    439 #endif  // OS_NACL
    440 
    441   executing_task->task_timing.RecordTaskStart(time_before_task);
    442 
    443   if (!executing_task->task_queue->GetShouldNotifyObservers())
    444     return;
    445 
    446   {
    447     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    448                  "SequenceManager.WillProcessTaskObservers");
    449     for (auto& observer : main_thread_only().task_observers)
    450       observer.WillProcessTask(executing_task->pending_task);
    451   }
    452 
    453   {
    454     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    455                  "SequenceManager.QueueNotifyWillProcessTask");
    456     executing_task->task_queue->NotifyWillProcessTask(
    457         executing_task->pending_task);
    458   }
    459 
    460   bool notify_time_observers =
    461       main_thread_only().task_time_observers.might_have_observers() ||
    462       executing_task->task_queue->RequiresTaskTiming();
    463 
    464   if (!notify_time_observers)
    465     return;
    466 
    467   if (main_thread_only().nesting_depth == 0) {
    468     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    469                  "SequenceManager.WillProcessTaskTimeObservers");
    470     for (auto& observer : main_thread_only().task_time_observers)
    471       observer.WillProcessTask(executing_task->task_timing.start_time());
    472   }
    473 
    474   {
    475     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    476                  "SequenceManager.QueueOnTaskStarted");
    477     executing_task->task_queue->OnTaskStarted(executing_task->pending_task,
    478                                               executing_task->task_timing);
    479   }
    480 }
    481 
    482 void SequenceManagerImpl::NotifyDidProcessTask(ExecutingTask* executing_task,
    483                                                LazyNow* time_after_task) {
    484   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    485                "SequenceManagerImpl::NotifyDidProcessTaskObservers");
    486 
    487   executing_task->task_timing.RecordTaskEnd(time_after_task);
    488 
    489   const TaskQueue::TaskTiming& task_timing = executing_task->task_timing;
    490 
    491   if (!executing_task->task_queue->GetShouldNotifyObservers())
    492     return;
    493 
    494   if (task_timing.has_wall_time() && main_thread_only().nesting_depth == 0) {
    495     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    496                  "SequenceManager.DidProcessTaskTimeObservers");
    497     for (auto& observer : main_thread_only().task_time_observers) {
    498       observer.DidProcessTask(task_timing.start_time(), task_timing.end_time());
    499     }
    500   }
    501 
    502   {
    503     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    504                  "SequenceManager.DidProcessTaskObservers");
    505     for (auto& observer : main_thread_only().task_observers)
    506       observer.DidProcessTask(executing_task->pending_task);
    507   }
    508 
    509   {
    510     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    511                  "SequenceManager.QueueNotifyDidProcessTask");
    512     executing_task->task_queue->NotifyDidProcessTask(
    513         executing_task->pending_task);
    514   }
    515 
    516   {
    517     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
    518                  "SequenceManager.QueueOnTaskCompleted");
    519     if (task_timing.has_wall_time())
    520       executing_task->task_queue->OnTaskCompleted(executing_task->pending_task,
    521                                                   task_timing);
    522   }
    523 
    524   // TODO(altimin): Move this back to blink.
    525   if (task_timing.has_wall_time() &&
    526       task_timing.wall_duration() > kLongTaskTraceEventThreshold &&
    527       main_thread_only().nesting_depth == 0) {
    528     TRACE_EVENT_INSTANT1("blink", "LongTask", TRACE_EVENT_SCOPE_THREAD,
    529                          "duration", task_timing.wall_duration().InSecondsF());
    530   }
    531 }
    532 
    533 void SequenceManagerImpl::SetWorkBatchSize(int work_batch_size) {
    534   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    535   DCHECK_GE(work_batch_size, 1);
    536   controller_->SetWorkBatchSize(work_batch_size);
    537 }
    538 
    539 void SequenceManagerImpl::AddTaskObserver(
    540     MessageLoop::TaskObserver* task_observer) {
    541   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    542   main_thread_only().task_observers.AddObserver(task_observer);
    543 }
    544 
    545 void SequenceManagerImpl::RemoveTaskObserver(
    546     MessageLoop::TaskObserver* task_observer) {
    547   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    548   main_thread_only().task_observers.RemoveObserver(task_observer);
    549 }
    550 
    551 void SequenceManagerImpl::AddTaskTimeObserver(
    552     TaskTimeObserver* task_time_observer) {
    553   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    554   main_thread_only().task_time_observers.AddObserver(task_time_observer);
    555 }
    556 
    557 void SequenceManagerImpl::RemoveTaskTimeObserver(
    558     TaskTimeObserver* task_time_observer) {
    559   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    560   main_thread_only().task_time_observers.RemoveObserver(task_time_observer);
    561 }
    562 
    563 bool SequenceManagerImpl::GetAndClearSystemIsQuiescentBit() {
    564   bool task_was_run =
    565       main_thread_only().task_was_run_on_quiescence_monitored_queue;
    566   main_thread_only().task_was_run_on_quiescence_monitored_queue = false;
    567   return !task_was_run;
    568 }
    569 
    570 internal::EnqueueOrder SequenceManagerImpl::GetNextSequenceNumber() {
    571   return enqueue_order_generator_.GenerateNext();
    572 }
    573 
    574 std::unique_ptr<trace_event::ConvertableToTraceFormat>
    575 SequenceManagerImpl::AsValueWithSelectorResult(
    576     bool should_run,
    577     internal::WorkQueue* selected_work_queue) const {
    578   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    579   std::unique_ptr<trace_event::TracedValue> state(
    580       new trace_event::TracedValue());
    581   TimeTicks now = NowTicks();
    582   state->BeginArray("active_queues");
    583   for (auto* const queue : main_thread_only().active_queues)
    584     queue->AsValueInto(now, state.get());
    585   state->EndArray();
    586   state->BeginArray("queues_to_gracefully_shutdown");
    587   for (const auto& pair : main_thread_only().queues_to_gracefully_shutdown)
    588     pair.first->AsValueInto(now, state.get());
    589   state->EndArray();
    590   state->BeginArray("queues_to_delete");
    591   for (const auto& pair : main_thread_only().queues_to_delete)
    592     pair.first->AsValueInto(now, state.get());
    593   state->EndArray();
    594   state->BeginDictionary("selector");
    595   main_thread_only().selector.AsValueInto(state.get());
    596   state->EndDictionary();
    597   if (should_run) {
    598     state->SetString("selected_queue",
    599                      selected_work_queue->task_queue()->GetName());
    600     state->SetString("work_queue_name", selected_work_queue->name());
    601   }
    602 
    603   state->BeginArray("time_domains");
    604   for (auto* time_domain : main_thread_only().time_domains)
    605     time_domain->AsValueInto(state.get());
    606   state->EndArray();
    607   {
    608     AutoLock lock(any_thread_lock_);
    609     state->BeginArray("has_incoming_immediate_work");
    610     for (const internal::IncomingImmediateWorkList* iter =
    611              any_thread().incoming_immediate_work_list;
    612          iter; iter = iter->next) {
    613       state->AppendString(iter->queue->GetName());
    614     }
    615     state->EndArray();
    616   }
    617   return std::move(state);
    618 }
    619 
    620 void SequenceManagerImpl::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) {
    621   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    622   DCHECK(queue->IsQueueEnabled());
    623   // Only schedule DoWork if there's something to do.
    624   if (queue->HasTaskToRunImmediately() && !queue->BlockedByFence())
    625     MaybeScheduleImmediateWork(FROM_HERE);
    626 }
    627 
    628 void SequenceManagerImpl::SweepCanceledDelayedTasks() {
    629   std::map<TimeDomain*, TimeTicks> time_domain_now;
    630   for (auto* const queue : main_thread_only().active_queues)
    631     SweepCanceledDelayedTasksInQueue(queue, &time_domain_now);
    632   for (const auto& pair : main_thread_only().queues_to_gracefully_shutdown)
    633     SweepCanceledDelayedTasksInQueue(pair.first, &time_domain_now);
    634 }
    635 
    636 void SequenceManagerImpl::TakeQueuesToGracefullyShutdownFromHelper() {
    637   std::vector<std::unique_ptr<internal::TaskQueueImpl>> queues =
    638       graceful_shutdown_helper_->TakeQueues();
    639   for (std::unique_ptr<internal::TaskQueueImpl>& queue : queues) {
    640     main_thread_only().queues_to_gracefully_shutdown[queue.get()] =
    641         std::move(queue);
    642   }
    643 }
    644 
    645 void SequenceManagerImpl::CleanUpQueues() {
    646   TakeQueuesToGracefullyShutdownFromHelper();
    647 
    648   for (auto it = main_thread_only().queues_to_gracefully_shutdown.begin();
    649        it != main_thread_only().queues_to_gracefully_shutdown.end();) {
    650     if (it->first->IsEmpty()) {
    651       UnregisterTaskQueueImpl(std::move(it->second));
    652       main_thread_only().active_queues.erase(it->first);
    653       main_thread_only().queues_to_gracefully_shutdown.erase(it++);
    654     } else {
    655       ++it;
    656     }
    657   }
    658   main_thread_only().queues_to_delete.clear();
    659 }
    660 
    661 scoped_refptr<internal::GracefulQueueShutdownHelper>
    662 SequenceManagerImpl::GetGracefulQueueShutdownHelper() const {
    663   return graceful_shutdown_helper_;
    664 }
    665 
    666 WeakPtr<SequenceManagerImpl> SequenceManagerImpl::GetWeakPtr() {
    667   return weak_factory_.GetWeakPtr();
    668 }
    669 
    670 void SequenceManagerImpl::SetDefaultTaskRunner(
    671     scoped_refptr<SingleThreadTaskRunner> task_runner) {
    672   controller_->SetDefaultTaskRunner(task_runner);
    673 }
    674 
    675 const TickClock* SequenceManagerImpl::GetTickClock() const {
    676   return controller_->GetClock();
    677 }
    678 
    679 TimeTicks SequenceManagerImpl::NowTicks() const {
    680   return controller_->GetClock()->NowTicks();
    681 }
    682 
    683 bool SequenceManagerImpl::ShouldRecordCPUTimeForTask() {
    684   return ThreadTicks::IsSupported() &&
    685          main_thread_only().uniform_distribution(
    686              main_thread_only().random_generator) <
    687              metric_recording_settings_
    688                  .task_sampling_rate_for_recording_cpu_time;
    689 }
    690 
    691 const SequenceManager::MetricRecordingSettings&
    692 SequenceManagerImpl::GetMetricRecordingSettings() const {
    693   return metric_recording_settings_;
    694 }
    695 
    696 MSVC_DISABLE_OPTIMIZE()
    697 bool SequenceManagerImpl::Validate() {
    698   return memory_corruption_sentinel_ == kMemoryCorruptionSentinelValue;
    699 }
    700 MSVC_ENABLE_OPTIMIZE()
    701 
    702 void SequenceManagerImpl::EnableCrashKeys(
    703     const char* file_name_crash_key_name,
    704     const char* function_name_crash_key_name) {
    705   DCHECK(!main_thread_only().file_name_crash_key);
    706   DCHECK(!main_thread_only().function_name_crash_key);
    707 #if !defined(OS_NACL)
    708   main_thread_only().file_name_crash_key = debug::AllocateCrashKeyString(
    709       file_name_crash_key_name, debug::CrashKeySize::Size64);
    710   main_thread_only().function_name_crash_key = debug::AllocateCrashKeyString(
    711       function_name_crash_key_name, debug::CrashKeySize::Size64);
    712 #endif  // OS_NACL
    713 }
    714 
    715 internal::TaskQueueImpl* SequenceManagerImpl::currently_executing_task_queue()
    716     const {
    717   if (main_thread_only().task_execution_stack.empty())
    718     return nullptr;
    719   return main_thread_only().task_execution_stack.rbegin()->task_queue;
    720 }
    721 
    722 }  // namespace internal
    723 }  // namespace sequence_manager
    724 }  // namespace base
    725