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