| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/scheduler/base/task_queue_impl.h" | 5 #include "platform/scheduler/base/task_queue_impl.h" |
| 6 | 6 |
| 7 #include "base/trace_event/blame_context.h" | 7 #include "base/trace_event/blame_context.h" |
| 8 #include "platform/scheduler/base/task_queue_manager.h" | 8 #include "platform/scheduler/base/task_queue_manager.h" |
| 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" |
| 10 #include "platform/scheduler/base/time_domain.h" | 10 #include "platform/scheduler/base/time_domain.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
| 47 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
| 48 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
| 49 const Spec& spec, | 49 const Spec& spec, |
| 50 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
| 51 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
| 52 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
| 53 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 53 any_thread_(task_queue_manager, time_domain), |
| 54 name_(spec.name), | 54 name_(spec.name), |
| 55 disabled_by_default_tracing_category_( | 55 disabled_by_default_tracing_category_( |
| 56 disabled_by_default_tracing_category), | 56 disabled_by_default_tracing_category), |
| 57 disabled_by_default_verbose_tracing_category_( | 57 disabled_by_default_verbose_tracing_category_( |
| 58 disabled_by_default_verbose_tracing_category), | 58 disabled_by_default_verbose_tracing_category), |
| 59 main_thread_only_(task_queue_manager, | 59 main_thread_only_(task_queue_manager, this, time_domain), |
| 60 spec.pump_policy, | |
| 61 this, | |
| 62 time_domain), | |
| 63 wakeup_policy_(spec.wakeup_policy), | |
| 64 should_monitor_quiescence_(spec.should_monitor_quiescence), | 60 should_monitor_quiescence_(spec.should_monitor_quiescence), |
| 65 should_notify_observers_(spec.should_notify_observers), | 61 should_notify_observers_(spec.should_notify_observers), |
| 66 should_report_when_execution_blocked_( | 62 should_report_when_execution_blocked_( |
| 67 spec.should_report_when_execution_blocked) { | 63 spec.should_report_when_execution_blocked) { |
| 68 DCHECK(time_domain); | 64 DCHECK(time_domain); |
| 69 time_domain->RegisterQueue(this); | 65 time_domain->RegisterQueue(this); |
| 70 } | 66 } |
| 71 | 67 |
| 72 TaskQueueImpl::~TaskQueueImpl() { | 68 TaskQueueImpl::~TaskQueueImpl() { |
| 73 #if DCHECK_IS_ON() | 69 #if DCHECK_IS_ON() |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 160 |
| 165 if (a.delayed_run_time > b.delayed_run_time) | 161 if (a.delayed_run_time > b.delayed_run_time) |
| 166 return false; | 162 return false; |
| 167 | 163 |
| 168 // If the times happen to match, then we use the sequence number to decide. | 164 // If the times happen to match, then we use the sequence number to decide. |
| 169 // Compare the difference to support integer roll-over. | 165 // Compare the difference to support integer roll-over. |
| 170 return (a.sequence_num - b.sequence_num) < 0; | 166 return (a.sequence_num - b.sequence_num) < 0; |
| 171 } | 167 } |
| 172 | 168 |
| 173 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 169 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 174 PumpPolicy pump_policy, | |
| 175 TimeDomain* time_domain) | 170 TimeDomain* time_domain) |
| 176 : task_queue_manager(task_queue_manager), | 171 : task_queue_manager(task_queue_manager), |
| 177 pump_policy(pump_policy), | |
| 178 time_domain(time_domain), | 172 time_domain(time_domain), |
| 179 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { | 173 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { |
| 180 } | 174 } |
| 181 | 175 |
| 182 TaskQueueImpl::AnyThread::~AnyThread() {} | 176 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 183 | 177 |
| 184 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 178 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| 185 TaskQueueManager* task_queue_manager, | 179 TaskQueueManager* task_queue_manager, |
| 186 PumpPolicy pump_policy, | |
| 187 TaskQueueImpl* task_queue, | 180 TaskQueueImpl* task_queue, |
| 188 TimeDomain* time_domain) | 181 TimeDomain* time_domain) |
| 189 : task_queue_manager(task_queue_manager), | 182 : task_queue_manager(task_queue_manager), |
| 190 pump_policy(pump_policy), | |
| 191 time_domain(time_domain), | 183 time_domain(time_domain), |
| 192 delayed_work_queue( | 184 delayed_work_queue( |
| 193 new WorkQueue(task_queue, | 185 new WorkQueue(task_queue, |
| 194 "delayed", | 186 "delayed", |
| 195 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), | 187 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), |
| 196 immediate_work_queue( | 188 immediate_work_queue( |
| 197 new WorkQueue(task_queue, | 189 new WorkQueue(task_queue, |
| 198 "immediate", | 190 "immediate", |
| 199 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), | 191 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), |
| 200 set_index(0), | 192 set_index(0), |
| 201 is_enabled(true), | 193 is_enabled(true), |
| 202 blame_context(nullptr) {} | 194 blame_context(nullptr), |
| 195 current_fence(0) {} |
| 203 | 196 |
| 204 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 197 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 205 | 198 |
| 206 void TaskQueueImpl::UnregisterTaskQueue() { | 199 void TaskQueueImpl::UnregisterTaskQueue() { |
| 207 base::AutoLock lock(any_thread_lock_); | 200 base::AutoLock lock(any_thread_lock_); |
| 208 if (main_thread_only().time_domain) | 201 if (main_thread_only().time_domain) |
| 209 main_thread_only().time_domain->UnregisterQueue(this); | 202 main_thread_only().time_domain->UnregisterQueue(this); |
| 210 if (!any_thread().task_queue_manager) | 203 if (!any_thread().task_queue_manager) |
| 211 return; | 204 return; |
| 212 any_thread().time_domain = nullptr; | 205 any_thread().time_domain = nullptr; |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 PushOntoImmediateIncomingQueueLocked( | 435 PushOntoImmediateIncomingQueueLocked( |
| 443 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 436 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| 444 base::Passed(&pending_task)), | 437 base::Passed(&pending_task)), |
| 445 base::TimeTicks(), thread_hop_task_sequence_number, false, | 438 base::TimeTicks(), thread_hop_task_sequence_number, false, |
| 446 thread_hop_task_sequence_number)); | 439 thread_hop_task_sequence_number)); |
| 447 } | 440 } |
| 448 | 441 |
| 449 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 442 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
| 450 if (any_thread().immediate_incoming_queue.empty()) | 443 if (any_thread().immediate_incoming_queue.empty()) |
| 451 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 444 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
| 452 if (any_thread().pump_policy == PumpPolicy::AUTO && | 445 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 453 any_thread().immediate_incoming_queue.empty()) { | 446 // it run. |
| 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 447 if (any_thread().immediate_incoming_queue.empty()) { |
| 448 // There's no point posting a DoWork for a disabled queue, however we can |
| 449 // only tell if it's disabled from the main thread. |
| 450 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 451 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) |
| 452 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 453 } else { |
| 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 455 } |
| 455 } | 456 } |
| 456 any_thread().task_queue_manager->DidQueueTask(pending_task); | 457 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 457 // We expect |pending_task| to be inserted at the end. Amoritized O(1). | 458 // We expect |pending_task| to be inserted at the end. Amoritized O(1). |
| 458 any_thread().immediate_incoming_queue.insert( | 459 any_thread().immediate_incoming_queue.insert( |
| 459 any_thread().immediate_incoming_queue.end(), | 460 any_thread().immediate_incoming_queue.end(), |
| 460 std::move(pending_task)); | 461 std::move(pending_task)); |
| 461 DCHECK_EQ(pending_task.enqueue_order(), | 462 DCHECK_EQ(pending_task.enqueue_order(), |
| 462 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); | 463 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); |
| 463 TraceQueueSize(true); | 464 TraceQueueSize(true); |
| 464 } | 465 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 482 TraceQueueSize(false); | 483 TraceQueueSize(false); |
| 483 } | 484 } |
| 484 | 485 |
| 485 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 486 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
| 486 if (main_thread_only().is_enabled == enabled) | 487 if (main_thread_only().is_enabled == enabled) |
| 487 return; | 488 return; |
| 488 main_thread_only().is_enabled = enabled; | 489 main_thread_only().is_enabled = enabled; |
| 489 if (!main_thread_only().task_queue_manager) | 490 if (!main_thread_only().task_queue_manager) |
| 490 return; | 491 return; |
| 491 if (enabled) { | 492 if (enabled) { |
| 493 // Note it's the job of the selector to tell the TaskQueueManager if |
| 494 // a DoWork needs posting. |
| 492 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 495 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| 493 } else { | 496 } else { |
| 494 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 497 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
| 495 } | 498 } |
| 496 } | 499 } |
| 497 | 500 |
| 498 bool TaskQueueImpl::IsQueueEnabled() const { | 501 bool TaskQueueImpl::IsQueueEnabled() const { |
| 499 return main_thread_only().is_enabled; | 502 return main_thread_only().is_enabled; |
| 500 } | 503 } |
| 501 | 504 |
| 502 bool TaskQueueImpl::IsEmpty() const { | 505 bool TaskQueueImpl::IsEmpty() const { |
| 503 if (!main_thread_only().delayed_work_queue->Empty() || | 506 if (!main_thread_only().delayed_work_queue->Empty() || |
| 504 !main_thread_only().immediate_work_queue->Empty()) { | 507 !main_thread_only().immediate_work_queue->Empty()) { |
| 505 return false; | 508 return false; |
| 506 } | 509 } |
| 507 | 510 |
| 508 base::AutoLock lock(any_thread_lock_); | 511 base::AutoLock lock(any_thread_lock_); |
| 509 return any_thread().immediate_incoming_queue.empty() && | 512 return any_thread().immediate_incoming_queue.empty() && |
| 510 main_thread_only().delayed_incoming_queue.empty(); | 513 main_thread_only().delayed_incoming_queue.empty(); |
| 511 } | 514 } |
| 512 | 515 |
| 513 bool TaskQueueImpl::HasPendingImmediateWork() const { | 516 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 517 // Any work queue tasks count as immediate work. |
| 514 if (!main_thread_only().delayed_work_queue->Empty() || | 518 if (!main_thread_only().delayed_work_queue->Empty() || |
| 515 !main_thread_only().immediate_work_queue->Empty()) { | 519 !main_thread_only().immediate_work_queue->Empty()) { |
| 516 return true; | 520 return true; |
| 517 } | 521 } |
| 518 | 522 |
| 519 return NeedsPumping(); | 523 // Tasks on |delayed_incoming_queue| that could run now, count as |
| 520 } | 524 // immediate work. |
| 521 | 525 if (!main_thread_only().delayed_incoming_queue.empty() && |
| 522 bool TaskQueueImpl::NeedsPumping() const { | 526 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
| 523 if (!main_thread_only().immediate_work_queue->Empty()) | 527 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 524 return false; | |
| 525 | |
| 526 base::AutoLock lock(any_thread_lock_); | |
| 527 if (!any_thread().immediate_incoming_queue.empty()) | |
| 528 return true; | |
| 529 | |
| 530 // If there's no immediate Incoming work then we only need pumping if there | |
| 531 // is a delayed task that should be running now. | |
| 532 if (main_thread_only().delayed_incoming_queue.empty()) | |
| 533 return false; | |
| 534 | |
| 535 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= | |
| 536 main_thread_only().time_domain->CreateLazyNow().Now(); | |
| 537 } | |
| 538 | |
| 539 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( | |
| 540 const Task* task) { | |
| 541 // A null task is passed when UpdateQueue is called before any task is run. | |
| 542 // In this case we don't want to pump an after_wakeup queue, so return true | |
| 543 // here. | |
| 544 if (!task) | |
| 545 return true; | |
| 546 | |
| 547 // Return false if task is newer than the oldest immediate task. | |
| 548 if (!any_thread().immediate_incoming_queue.empty() && | |
| 549 task->enqueue_order() > | |
| 550 any_thread().immediate_incoming_queue.begin()->enqueue_order()) { | |
| 551 return false; | |
| 552 } | |
| 553 return true; | |
| 554 } | |
| 555 | |
| 556 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { | |
| 557 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 558 // A null task is passed when UpdateQueue is called before any task is run. | |
| 559 // In this case we don't want to pump an after_wakeup queue, so return true | |
| 560 // here. | |
| 561 if (!task) | |
| 562 return true; | |
| 563 | |
| 564 EnqueueOrder enqueue_order; | |
| 565 if (!main_thread_only().delayed_work_queue->GetFrontTaskEnqueueOrder( | |
| 566 &enqueue_order)) { | |
| 567 return true; | 528 return true; |
| 568 } | 529 } |
| 569 | 530 |
| 570 return task->enqueue_order() < enqueue_order; | 531 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 571 } | 532 base::AutoLock lock(any_thread_lock_); |
| 572 | 533 return !any_thread().immediate_incoming_queue.empty(); |
| 573 bool TaskQueueImpl::ShouldAutoPumpImmediateQueueLocked( | |
| 574 bool should_trigger_wakeup, | |
| 575 const Task* previous_task) { | |
| 576 if (main_thread_only().pump_policy == PumpPolicy::MANUAL) | |
| 577 return false; | |
| 578 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | |
| 579 (!should_trigger_wakeup || | |
| 580 TaskIsOlderThanQueuedImmediateTasksLocked(previous_task))) | |
| 581 return false; | |
| 582 return true; | |
| 583 } | |
| 584 | |
| 585 bool TaskQueueImpl::ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup, | |
| 586 const Task* previous_task) { | |
| 587 if (main_thread_only().pump_policy == PumpPolicy::MANUAL) | |
| 588 return false; | |
| 589 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | |
| 590 (!should_trigger_wakeup || | |
| 591 TaskIsOlderThanQueuedDelayedTasks(previous_task))) | |
| 592 return false; | |
| 593 return true; | |
| 594 } | 534 } |
| 595 | 535 |
| 596 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 536 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
| 597 // Enqueue all delayed tasks that should be running now. | 537 // Enqueue all delayed tasks that should be running now. |
| 598 while (!main_thread_only().delayed_incoming_queue.empty()) { | 538 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 599 DelayedRunTimeQueue::iterator next_task = | 539 DelayedRunTimeQueue::iterator next_task = |
| 600 main_thread_only().delayed_incoming_queue.begin(); | 540 main_thread_only().delayed_incoming_queue.begin(); |
| 601 if (next_task->delayed_run_time > lazy_now->Now()) | 541 if (next_task->delayed_run_time > lazy_now->Now()) |
| 602 break; | 542 break; |
| 603 // TODO(alexclarke): Use extract() when C++17 is allowed. | 543 // TODO(alexclarke): Use extract() when C++17 is allowed. |
| 604 Task& task = const_cast<Task&>(*next_task); | 544 Task& task = const_cast<Task&>(*next_task); |
| 605 task.set_enqueue_order( | 545 task.set_enqueue_order( |
| 606 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 546 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
| 607 main_thread_only().delayed_work_queue->Push(std::move(task)); | 547 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 608 main_thread_only().delayed_incoming_queue.erase(next_task); | 548 main_thread_only().delayed_incoming_queue.erase(next_task); |
| 609 } | 549 } |
| 610 } | 550 } |
| 611 | 551 |
| 612 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 552 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { |
| 613 bool should_trigger_wakeup, | |
| 614 const Task* previous_task) { | |
| 615 if (!main_thread_only().task_queue_manager) | 553 if (!main_thread_only().task_queue_manager) |
| 616 return; | 554 return; |
| 617 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | |
| 618 return; | |
| 619 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 555 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
| 620 TraceQueueSize(false); | 556 TraceQueueSize(false); |
| 621 } | 557 } |
| 622 | 558 |
| 623 void TaskQueueImpl::UpdateImmediateWorkQueue(bool should_trigger_wakeup, | 559 void TaskQueueImpl::UpdateImmediateWorkQueue() { |
| 624 const Task* previous_task) { | |
| 625 DCHECK(main_thread_only().immediate_work_queue->Empty()); | 560 DCHECK(main_thread_only().immediate_work_queue->Empty()); |
| 626 base::AutoLock lock(any_thread_lock_); | 561 base::AutoLock lock(any_thread_lock_); |
| 627 if (!main_thread_only().task_queue_manager) | 562 if (!main_thread_only().task_queue_manager) |
| 628 return; | 563 return; |
| 629 if (!ShouldAutoPumpImmediateQueueLocked(should_trigger_wakeup, previous_task)) | |
| 630 return; | |
| 631 | 564 |
| 632 main_thread_only().immediate_work_queue->SwapLocked( | 565 main_thread_only().immediate_work_queue->SwapLocked( |
| 633 any_thread().immediate_incoming_queue); | 566 any_thread().immediate_incoming_queue); |
| 634 | 567 |
| 635 // |any_thread().immediate_incoming_queue| is now empty so | 568 // |any_thread().immediate_incoming_queue| is now empty so |
| 636 // TimeDomain::UpdateQueues no longer needs to consider this queue for | 569 // TimeDomain::UpdateQueues no longer needs to consider this queue for |
| 637 // reloading. | 570 // reloading. |
| 638 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 571 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
| 639 } | 572 } |
| 640 | 573 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 656 any_thread_lock_.AssertAcquired(); | 589 any_thread_lock_.AssertAcquired(); |
| 657 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), | 590 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), |
| 658 any_thread().immediate_incoming_queue.size() + | 591 any_thread().immediate_incoming_queue.size() + |
| 659 main_thread_only().immediate_work_queue->Size() + | 592 main_thread_only().immediate_work_queue->Size() + |
| 660 main_thread_only().delayed_work_queue->Size() + | 593 main_thread_only().delayed_work_queue->Size() + |
| 661 main_thread_only().delayed_incoming_queue.size()); | 594 main_thread_only().delayed_incoming_queue.size()); |
| 662 if (!is_locked) | 595 if (!is_locked) |
| 663 any_thread_lock_.Release(); | 596 any_thread_lock_.Release(); |
| 664 } | 597 } |
| 665 | 598 |
| 666 void TaskQueueImpl::SetPumpPolicy(PumpPolicy pump_policy) { | |
| 667 base::AutoLock lock(any_thread_lock_); | |
| 668 if (pump_policy == PumpPolicy::AUTO && | |
| 669 any_thread().pump_policy != PumpPolicy::AUTO) { | |
| 670 LazyNow lazy_now(main_thread_only().time_domain->CreateLazyNow()); | |
| 671 PumpQueueLocked(&lazy_now, true); | |
| 672 } | |
| 673 any_thread().pump_policy = pump_policy; | |
| 674 main_thread_only().pump_policy = pump_policy; | |
| 675 } | |
| 676 | |
| 677 TaskQueue::PumpPolicy TaskQueueImpl::GetPumpPolicy() const { | |
| 678 return main_thread_only().pump_policy; | |
| 679 } | |
| 680 | |
| 681 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { | |
| 682 TRACE_EVENT1(disabled_by_default_tracing_category_, | |
| 683 "TaskQueueImpl::PumpQueueLocked", "queue", name_); | |
| 684 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; | |
| 685 if (!task_queue_manager) | |
| 686 return; | |
| 687 | |
| 688 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | |
| 689 | |
| 690 while (!any_thread().immediate_incoming_queue.empty()) { | |
| 691 ComparatorQueue::iterator it = | |
| 692 any_thread().immediate_incoming_queue.begin(); | |
| 693 main_thread_only().immediate_work_queue->Push( | |
| 694 std::move(const_cast<Task&>(*it))); | |
| 695 any_thread().immediate_incoming_queue.erase(it); | |
| 696 } | |
| 697 | |
| 698 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no | |
| 699 // longer needs to consider this queue for reloading. | |
| 700 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | |
| 701 | |
| 702 if (main_thread_only().immediate_work_queue->Empty() && | |
| 703 main_thread_only().delayed_work_queue->Empty()) { | |
| 704 return; | |
| 705 } | |
| 706 | |
| 707 if (may_post_dowork) | |
| 708 task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | |
| 709 } | |
| 710 | |
| 711 void TaskQueueImpl::PumpQueue(LazyNow* lazy_now, bool may_post_dowork) { | |
| 712 base::AutoLock lock(any_thread_lock_); | |
| 713 PumpQueueLocked(lazy_now, may_post_dowork); | |
| 714 } | |
| 715 | |
| 716 const char* TaskQueueImpl::GetName() const { | 599 const char* TaskQueueImpl::GetName() const { |
| 717 return name_; | 600 return name_; |
| 718 } | 601 } |
| 719 | 602 |
| 720 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { | 603 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { |
| 721 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) | 604 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) |
| 722 return; | 605 return; |
| 723 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, | 606 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, |
| 724 priority); | 607 priority); |
| 725 } | 608 } |
| 726 | 609 |
| 727 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 610 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
| 728 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 611 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
| 729 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 612 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
| 730 return static_cast<TaskQueue::QueuePriority>(set_index); | 613 return static_cast<TaskQueue::QueuePriority>(set_index); |
| 731 } | 614 } |
| 732 | 615 |
| 733 // static | 616 // static |
| 734 const char* TaskQueueImpl::PumpPolicyToString( | |
| 735 TaskQueue::PumpPolicy pump_policy) { | |
| 736 switch (pump_policy) { | |
| 737 case TaskQueue::PumpPolicy::AUTO: | |
| 738 return "auto"; | |
| 739 case TaskQueue::PumpPolicy::AFTER_WAKEUP: | |
| 740 return "after_wakeup"; | |
| 741 case TaskQueue::PumpPolicy::MANUAL: | |
| 742 return "manual"; | |
| 743 default: | |
| 744 NOTREACHED(); | |
| 745 return nullptr; | |
| 746 } | |
| 747 } | |
| 748 | |
| 749 // static | |
| 750 const char* TaskQueueImpl::WakeupPolicyToString( | |
| 751 TaskQueue::WakeupPolicy wakeup_policy) { | |
| 752 switch (wakeup_policy) { | |
| 753 case TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES: | |
| 754 return "can_wake_other_queues"; | |
| 755 case TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES: | |
| 756 return "dont_wake_other_queues"; | |
| 757 default: | |
| 758 NOTREACHED(); | |
| 759 return nullptr; | |
| 760 } | |
| 761 } | |
| 762 | |
| 763 // static | |
| 764 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { | 617 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { |
| 765 switch (priority) { | 618 switch (priority) { |
| 766 case CONTROL_PRIORITY: | 619 case CONTROL_PRIORITY: |
| 767 return "control"; | 620 return "control"; |
| 768 case HIGH_PRIORITY: | 621 case HIGH_PRIORITY: |
| 769 return "high"; | 622 return "high"; |
| 770 case NORMAL_PRIORITY: | 623 case NORMAL_PRIORITY: |
| 771 return "normal"; | 624 return "normal"; |
| 772 case BEST_EFFORT_PRIORITY: | 625 case BEST_EFFORT_PRIORITY: |
| 773 return "best_effort"; | 626 return "best_effort"; |
| 774 default: | 627 default: |
| 775 NOTREACHED(); | 628 NOTREACHED(); |
| 776 return nullptr; | 629 return nullptr; |
| 777 } | 630 } |
| 778 } | 631 } |
| 779 | 632 |
| 780 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 633 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
| 781 base::AutoLock lock(any_thread_lock_); | 634 base::AutoLock lock(any_thread_lock_); |
| 782 state->BeginDictionary(); | 635 state->BeginDictionary(); |
| 783 state->SetString("name", GetName()); | 636 state->SetString("name", GetName()); |
| 784 state->SetBoolean("enabled", main_thread_only().is_enabled); | 637 state->SetBoolean("enabled", main_thread_only().is_enabled); |
| 785 state->SetString("time_domain_name", | 638 state->SetString("time_domain_name", |
| 786 main_thread_only().time_domain->GetName()); | 639 main_thread_only().time_domain->GetName()); |
| 787 state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy)); | |
| 788 state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_)); | |
| 789 bool verbose_tracing_enabled = false; | 640 bool verbose_tracing_enabled = false; |
| 790 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 641 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
| 791 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 642 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |
| 792 state->SetInteger("immediate_incoming_queue_size", | 643 state->SetInteger("immediate_incoming_queue_size", |
| 793 any_thread().immediate_incoming_queue.size()); | 644 any_thread().immediate_incoming_queue.size()); |
| 794 state->SetInteger("delayed_incoming_queue_size", | 645 state->SetInteger("delayed_incoming_queue_size", |
| 795 main_thread_only().delayed_incoming_queue.size()); | 646 main_thread_only().delayed_incoming_queue.size()); |
| 796 state->SetInteger("immediate_work_queue_size", | 647 state->SetInteger("immediate_work_queue_size", |
| 797 main_thread_only().immediate_work_queue->Size()); | 648 main_thread_only().immediate_work_queue->Size()); |
| 798 state->SetInteger("delayed_work_queue_size", | 649 state->SetInteger("delayed_work_queue_size", |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 | 728 |
| 878 base::AutoLock lock(any_thread_lock_); | 729 base::AutoLock lock(any_thread_lock_); |
| 879 return any_thread().time_domain; | 730 return any_thread().time_domain; |
| 880 } | 731 } |
| 881 | 732 |
| 882 void TaskQueueImpl::SetBlameContext( | 733 void TaskQueueImpl::SetBlameContext( |
| 883 base::trace_event::BlameContext* blame_context) { | 734 base::trace_event::BlameContext* blame_context) { |
| 884 main_thread_only().blame_context = blame_context; | 735 main_thread_only().blame_context = blame_context; |
| 885 } | 736 } |
| 886 | 737 |
| 738 void TaskQueueImpl::InsertFence() { |
| 739 if (!main_thread_only().task_queue_manager) |
| 740 return; |
| 741 |
| 742 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 743 main_thread_only().current_fence = |
| 744 main_thread_only().task_queue_manager->GetNextSequenceNumber(); |
| 745 |
| 746 // Tasks posted after this point will have a strictly higher enqueue order |
| 747 // and will be blocked from running. |
| 748 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 749 main_thread_only().current_fence); |
| 750 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 751 main_thread_only().current_fence); |
| 752 |
| 753 if (!task_unblocked && previous_fence) { |
| 754 base::AutoLock lock(any_thread_lock_); |
| 755 if (!any_thread().immediate_incoming_queue.empty() && |
| 756 any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 757 previous_fence && |
| 758 any_thread().immediate_incoming_queue.begin()->enqueue_order() < |
| 759 main_thread_only().current_fence) { |
| 760 task_unblocked = true; |
| 761 } |
| 762 } |
| 763 |
| 764 if (main_thread_only().is_enabled && task_unblocked) { |
| 765 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 766 FROM_HERE); |
| 767 } |
| 768 } |
| 769 |
| 770 void TaskQueueImpl::RemoveFence() { |
| 771 if (!main_thread_only().task_queue_manager) |
| 772 return; |
| 773 |
| 774 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 775 main_thread_only().current_fence = 0; |
| 776 |
| 777 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 778 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 779 |
| 780 if (!task_unblocked && previous_fence) { |
| 781 base::AutoLock lock(any_thread_lock_); |
| 782 if (!any_thread().immediate_incoming_queue.empty() && |
| 783 any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 784 previous_fence) { |
| 785 task_unblocked = true; |
| 786 } |
| 787 } |
| 788 |
| 789 if (main_thread_only().is_enabled && task_unblocked) { |
| 790 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 791 FROM_HERE); |
| 792 } |
| 793 } |
| 794 |
| 795 bool TaskQueueImpl::BlockedByFence() const { |
| 796 if (!main_thread_only().current_fence) |
| 797 return false; |
| 798 |
| 799 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 800 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 801 return false; |
| 802 } |
| 803 |
| 804 base::AutoLock lock(any_thread_lock_); |
| 805 if (any_thread().immediate_incoming_queue.empty()) |
| 806 return true; |
| 807 |
| 808 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 809 main_thread_only().current_fence; |
| 810 } |
| 811 |
| 812 bool TaskQueueImpl::BlockedByFenceLocked() const { |
| 813 if (!main_thread_only().current_fence) |
| 814 return false; |
| 815 |
| 816 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 817 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 818 return false; |
| 819 } |
| 820 |
| 821 if (any_thread().immediate_incoming_queue.empty()) |
| 822 return true; |
| 823 |
| 824 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 825 main_thread_only().current_fence; |
| 826 } |
| 827 |
| 887 // static | 828 // static |
| 888 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, | 829 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
| 889 base::trace_event::TracedValue* state) { | 830 base::trace_event::TracedValue* state) { |
| 890 for (const Task& task : queue) { | 831 for (const Task& task : queue) { |
| 891 TaskAsValueInto(task, state); | 832 TaskAsValueInto(task, state); |
| 892 } | 833 } |
| 893 } | 834 } |
| 894 | 835 |
| 895 // static | 836 // static |
| 896 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, | 837 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 916 state->SetBoolean("is_high_res", task.is_high_res); | 857 state->SetBoolean("is_high_res", task.is_high_res); |
| 917 state->SetDouble( | 858 state->SetDouble( |
| 918 "delayed_run_time", | 859 "delayed_run_time", |
| 919 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 860 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 920 state->EndDictionary(); | 861 state->EndDictionary(); |
| 921 } | 862 } |
| 922 | 863 |
| 923 } // namespace internal | 864 } // namespace internal |
| 924 } // namespace scheduler | 865 } // namespace scheduler |
| 925 } // namespace blink | 866 } // namespace blink |
| OLD | NEW |