| Index: content/renderer/raster_worker_pool.cc
|
| diff --git a/content/renderer/raster_worker_pool.cc b/content/renderer/raster_worker_pool.cc
|
| index b1f5edba3dcbce293b009a5d778d2c549a5e7401..71859d846b6b88e9e890f1b9702b58586ec188f2 100644
|
| --- a/content/renderer/raster_worker_pool.cc
|
| +++ b/content/renderer/raster_worker_pool.cc
|
| @@ -4,16 +4,39 @@
|
|
|
| #include "content/renderer/raster_worker_pool.h"
|
|
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| +#include <string>
|
| #include <utility>
|
| +#include <vector>
|
|
|
| #include "base/strings/stringprintf.h"
|
| #include "base/threading/thread_restrictions.h"
|
| #include "base/trace_event/trace_event.h"
|
| +#include "cc/base/math_util.h"
|
| +#include "cc/raster/task_category.h"
|
|
|
| namespace content {
|
| +namespace {
|
| +
|
| +// A thread which forwards to RasterWorkerPool::Run with the runnable
|
| +// categories.
|
| +class RasterWorkerPoolThread : public base::SimpleThread {
|
| + public:
|
| + explicit RasterWorkerPoolThread(const std::string& name_prefix,
|
| + const Options& options,
|
| + RasterWorkerPool* pool,
|
| + std::vector<cc::TaskCategory> categories)
|
| + : SimpleThread(name_prefix, options),
|
| + pool_(pool),
|
| + categories_(categories) {}
|
| +
|
| + void Run() override { pool_->Run(categories_); }
|
| +
|
| + private:
|
| + RasterWorkerPool* const pool_;
|
| + const std::vector<cc::TaskCategory> categories_;
|
| +};
|
| +
|
| +} // namespace
|
|
|
| // A sequenced task runner which posts tasks to a RasterWorkerPool.
|
| class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
|
| @@ -52,7 +75,10 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
|
| if (!graph_.nodes.empty())
|
| dependencies = 1;
|
|
|
| - cc::TaskGraph::Node node(graph_task.get(), 0u /* category */,
|
| + // Treat any tasks that are enqueued through the SequencedTaskRunner as
|
| + // FOREGROUND priority. We don't have enough information to know the
|
| + // actual priority of such tasks, so we run them as soon as possible.
|
| + cc::TaskGraph::Node node(graph_task.get(), cc::TASK_CATEGORY_FOREGROUND,
|
| 0u /* priority */, dependencies);
|
| if (dependencies) {
|
| graph_.edges.push_back(
|
| @@ -99,12 +125,27 @@ void RasterWorkerPool::Start(
|
| const base::SimpleThread::Options& thread_options) {
|
| DCHECK(threads_.empty());
|
| while (threads_.size() < static_cast<size_t>(num_threads)) {
|
| - scoped_ptr<base::DelegateSimpleThread> thread(
|
| - new base::DelegateSimpleThread(
|
| - this, base::StringPrintf("CompositorTileWorker%u",
|
| - static_cast<unsigned>(threads_.size() + 1))
|
| - .c_str(),
|
| - thread_options));
|
| + // Determine the categories that each thread can run.
|
| + std::vector<cc::TaskCategory> task_categories;
|
| +
|
| + // The first thread can run nonconcurrent tasks.
|
| + if (threads_.size() == 0) {
|
| + task_categories.push_back(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND);
|
| + }
|
| +
|
| + // All threads can run foreground tasks.
|
| + task_categories.push_back(cc::TASK_CATEGORY_FOREGROUND);
|
| +
|
| + // The last thread can run background tasks.
|
| + if (threads_.size() == (static_cast<size_t>(num_threads) - 1)) {
|
| + task_categories.push_back(cc::TASK_CATEGORY_BACKGROUND);
|
| + }
|
| +
|
| + scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
|
| + base::StringPrintf("CompositorTileWorker%u",
|
| + static_cast<unsigned>(threads_.size() + 1))
|
| + .c_str(),
|
| + thread_options, this, task_categories));
|
| thread->Start();
|
| threads_.push_back(std::move(thread));
|
| }
|
| @@ -153,10 +194,13 @@ bool RasterWorkerPool::PostDelayedTask(
|
|
|
| tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
|
| graph_.Reset();
|
| - for (const auto& graph_task : tasks_)
|
| + for (const auto& graph_task : tasks_) {
|
| + // Delayed tasks are assigned FOREGROUND category, ensuring that they run as
|
| + // soon as possible once their delay has expired.
|
| graph_.nodes.push_back(
|
| - cc::TaskGraph::Node(graph_task.get(), 0u /* category */,
|
| + cc::TaskGraph::Node(graph_task.get(), cc::TASK_CATEGORY_FOREGROUND,
|
| 0u /* priority */, 0u /* dependencies */));
|
| + }
|
|
|
| ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
|
| completed_tasks_.clear();
|
| @@ -167,12 +211,11 @@ bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
|
| return true;
|
| }
|
|
|
| -// Overridden from base::DelegateSimpleThread::Delegate:
|
| -void RasterWorkerPool::Run() {
|
| +void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories) {
|
| base::AutoLock lock(lock_);
|
|
|
| while (true) {
|
| - if (!RunTaskWithLockAcquired()) {
|
| + if (!RunTaskWithLockAcquired(categories)) {
|
| // Exit when shutdown is set and no more tasks are pending.
|
| if (shutdown_)
|
| break;
|
| @@ -222,9 +265,9 @@ void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
|
|
|
| work_queue_.ScheduleTasks(token, graph);
|
|
|
| - // If there is more work available, wake up worker thread.
|
| + // If there is more work available, wake up the other worker threads.
|
| if (work_queue_.HasReadyToRunTasks())
|
| - has_ready_to_run_tasks_cv_.Signal();
|
| + has_ready_to_run_tasks_cv_.Broadcast();
|
| }
|
|
|
| void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
|
| @@ -264,34 +307,26 @@ void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
|
| work_queue_.CollectCompletedTasks(token, completed_tasks);
|
| }
|
|
|
| -bool RasterWorkerPool::RunTaskWithLockAcquired() {
|
| +bool RasterWorkerPool::RunTaskWithLockAcquired(
|
| + const std::vector<cc::TaskCategory>& categories) {
|
| + for (const auto& category : categories) {
|
| + if (work_queue_.HasReadyToRunTasksForCategory(category)) {
|
| + RunTaskInCategoryWithLockAcquired(category);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void RasterWorkerPool::RunTaskInCategoryWithLockAcquired(
|
| + cc::TaskCategory category) {
|
| TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
|
|
|
| lock_.AssertAcquired();
|
|
|
| - // Find the first category with any tasks to run. This task graph runner
|
| - // treats categories as an additional priority.
|
| - // TODO(ericrk): Add more category/thread logic.
|
| - const auto& ready_to_run_namespaces = work_queue_.ready_to_run_namespaces();
|
| - auto found = std::find_if(
|
| - ready_to_run_namespaces.cbegin(), ready_to_run_namespaces.cend(),
|
| - [](const std::pair<uint16_t,
|
| - cc::TaskGraphWorkQueue::TaskNamespace::Vector>& pair) {
|
| - return !pair.second.empty();
|
| - });
|
| -
|
| - if (found == ready_to_run_namespaces.cend()) {
|
| - return false;
|
| - }
|
| -
|
| - const uint16_t category = found->first;
|
| auto prioritized_task = work_queue_.GetNextTaskToRun(category);
|
| cc::Task* task = prioritized_task.task;
|
|
|
| - // There may be more work available, so wake up another worker thread.
|
| - if (work_queue_.HasReadyToRunTasks())
|
| - has_ready_to_run_tasks_cv_.Signal();
|
| -
|
| // Call WillRun() before releasing |lock_| and running task.
|
| task->WillRun();
|
|
|
| @@ -306,12 +341,14 @@ bool RasterWorkerPool::RunTaskWithLockAcquired() {
|
|
|
| work_queue_.CompleteTask(prioritized_task);
|
|
|
| + // We may have just dequeued more tasks, wake up the other worker threads.
|
| + if (work_queue_.HasReadyToRunTasks())
|
| + has_ready_to_run_tasks_cv_.Broadcast();
|
| +
|
| // If namespace has finished running all tasks, wake up origin threads.
|
| if (work_queue_.HasFinishedRunningTasksInNamespace(
|
| prioritized_task.task_namespace))
|
| has_namespaces_with_finished_running_tasks_cv_.Broadcast();
|
| -
|
| - return true;
|
| }
|
|
|
| RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
|
|
|