Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(584)

Side by Side Diff: content/renderer/raster_worker_pool.cc

Issue 1666283002: Reland - Refactor signaling in RWP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix build Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/renderer/raster_worker_pool.h" 5 #include "content/renderer/raster_worker_pool.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 #include "base/trace_event/trace_event.h" 13 #include "base/trace_event/trace_event.h"
14 #include "cc/base/math_util.h" 14 #include "cc/base/math_util.h"
15 #include "cc/raster/task_category.h" 15 #include "cc/raster/task_category.h"
16 16
17 namespace content { 17 namespace content {
18 namespace { 18 namespace {
19 19
20 // A thread which forwards to RasterWorkerPool::Run with the runnable 20 // A thread which forwards to RasterWorkerPool::Run with the runnable
21 // categories. 21 // categories.
22 class RasterWorkerPoolThread : public base::SimpleThread { 22 class RasterWorkerPoolThread : public base::SimpleThread {
23 public: 23 public:
24 explicit RasterWorkerPoolThread(const std::string& name_prefix, 24 RasterWorkerPoolThread(const std::string& name_prefix,
25 const Options& options, 25 const Options& options,
26 RasterWorkerPool* pool, 26 RasterWorkerPool* pool,
27 std::vector<cc::TaskCategory> categories) 27 std::vector<cc::TaskCategory> categories,
28 base::ConditionVariable* ready_to_run_tasks_cv)
28 : SimpleThread(name_prefix, options), 29 : SimpleThread(name_prefix, options),
29 pool_(pool), 30 pool_(pool),
30 categories_(categories) {} 31 categories_(categories),
32 ready_to_run_tasks_cv_(ready_to_run_tasks_cv) {}
31 33
32 void Run() override { pool_->Run(categories_); } 34 void Run() override { pool_->Run(categories_, ready_to_run_tasks_cv_); }
33 35
34 private: 36 private:
35 RasterWorkerPool* const pool_; 37 RasterWorkerPool* const pool_;
36 const std::vector<cc::TaskCategory> categories_; 38 const std::vector<cc::TaskCategory> categories_;
39 base::ConditionVariable* const ready_to_run_tasks_cv_;
37 }; 40 };
38 41
39 } // namespace 42 } // namespace
40 43
41 // A sequenced task runner which posts tasks to a RasterWorkerPool. 44 // A sequenced task runner which posts tasks to a RasterWorkerPool.
42 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner 45 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
43 : public base::SequencedTaskRunner { 46 : public base::SequencedTaskRunner {
44 public: 47 public:
45 explicit RasterWorkerPoolSequencedTaskRunner( 48 explicit RasterWorkerPoolSequencedTaskRunner(
46 cc::TaskGraphRunner* task_graph_runner) 49 cc::TaskGraphRunner* task_graph_runner)
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 cc::Task::Vector tasks_; 112 cc::Task::Vector tasks_;
110 // Graph object used for scheduling tasks. 113 // Graph object used for scheduling tasks.
111 cc::TaskGraph graph_; 114 cc::TaskGraph graph_;
112 // Cached vector to avoid allocation when getting the list of complete 115 // Cached vector to avoid allocation when getting the list of complete
113 // tasks. 116 // tasks.
114 cc::Task::Vector completed_tasks_; 117 cc::Task::Vector completed_tasks_;
115 }; 118 };
116 119
117 RasterWorkerPool::RasterWorkerPool() 120 RasterWorkerPool::RasterWorkerPool()
118 : namespace_token_(GetNamespaceToken()), 121 : namespace_token_(GetNamespaceToken()),
119 has_ready_to_run_tasks_cv_(&lock_), 122 foreground_has_ready_to_run_tasks_cv_(&lock_),
123 background_has_ready_to_run_tasks_cv_(&lock_),
120 has_namespaces_with_finished_running_tasks_cv_(&lock_), 124 has_namespaces_with_finished_running_tasks_cv_(&lock_),
121 shutdown_(false) {} 125 shutdown_(false) {}
122 126
123 void RasterWorkerPool::Start( 127 void RasterWorkerPool::Start(
124 int num_threads, 128 int num_threads,
125 const base::SimpleThread::Options& thread_options) { 129 const base::SimpleThread::Options& thread_options) {
126 DCHECK(threads_.empty()); 130 DCHECK(threads_.empty());
127 while (threads_.size() < static_cast<size_t>(num_threads)) {
128 // Determine the categories that each thread can run.
129 std::vector<cc::TaskCategory> task_categories;
130 131
131 // The first thread can run nonconcurrent tasks. 132 // Start |num_threads| threads for foreground work, including nonconcurrent
132 if (threads_.size() == 0) { 133 // foreground work.
133 task_categories.push_back(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND); 134 std::vector<cc::TaskCategory> foreground_categories;
134 } 135 foreground_categories.push_back(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND);
136 foreground_categories.push_back(cc::TASK_CATEGORY_FOREGROUND);
135 137
136 // All threads can run foreground tasks. 138 for (int i = 0; i < num_threads; i++) {
137 task_categories.push_back(cc::TASK_CATEGORY_FOREGROUND);
138
139 // The last thread can run background tasks.
140 if (threads_.size() == (static_cast<size_t>(num_threads) - 1)) {
141 task_categories.push_back(cc::TASK_CATEGORY_BACKGROUND);
142 }
143
144 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread( 139 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
145 base::StringPrintf("CompositorTileWorker%u", 140 base::StringPrintf("CompositorTileWorker%u",
146 static_cast<unsigned>(threads_.size() + 1)) 141 static_cast<unsigned>(threads_.size() + 1))
147 .c_str(), 142 .c_str(),
148 thread_options, this, task_categories)); 143 thread_options, this, foreground_categories,
144 &foreground_has_ready_to_run_tasks_cv_));
149 thread->Start(); 145 thread->Start();
150 threads_.push_back(std::move(thread)); 146 threads_.push_back(std::move(thread));
151 } 147 }
148
149 // Start a single thread for background work.
150 {
151 std::vector<cc::TaskCategory> background_categories;
152 background_categories.push_back(cc::TASK_CATEGORY_BACKGROUND);
153 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
154 base::StringPrintf("CompositorTileWorker%u",
155 static_cast<unsigned>(threads_.size() + 1))
156 .c_str(),
157 thread_options, this, background_categories,
158 &background_has_ready_to_run_tasks_cv_));
159 thread->Start();
160 threads_.push_back(std::move(thread));
161 }
152 } 162 }
153 163
154 void RasterWorkerPool::Shutdown() { 164 void RasterWorkerPool::Shutdown() {
155 WaitForTasksToFinishRunning(namespace_token_); 165 WaitForTasksToFinishRunning(namespace_token_);
156 CollectCompletedTasks(namespace_token_, &completed_tasks_); 166 CollectCompletedTasks(namespace_token_, &completed_tasks_);
157 // Shutdown raster threads. 167 // Shutdown raster threads.
158 { 168 {
159 base::AutoLock lock(lock_); 169 base::AutoLock lock(lock_);
160 170
161 DCHECK(!work_queue_.HasReadyToRunTasks()); 171 DCHECK(!work_queue_.HasReadyToRunTasks());
162 DCHECK(!work_queue_.HasAnyNamespaces()); 172 DCHECK(!work_queue_.HasAnyNamespaces());
163 173
164 DCHECK(!shutdown_); 174 DCHECK(!shutdown_);
165 shutdown_ = true; 175 shutdown_ = true;
166 176
167 // Wake up all workers so they exit. 177 // Wake up all workers so they exit.
168 has_ready_to_run_tasks_cv_.Broadcast(); 178 foreground_has_ready_to_run_tasks_cv_.Broadcast();
179 background_has_ready_to_run_tasks_cv_.Broadcast();
169 } 180 }
170 while (!threads_.empty()) { 181 while (!threads_.empty()) {
171 threads_.back()->Join(); 182 threads_.back()->Join();
172 threads_.pop_back(); 183 threads_.pop_back();
173 } 184 }
174 } 185 }
175 186
176 // Overridden from base::TaskRunner: 187 // Overridden from base::TaskRunner:
177 bool RasterWorkerPool::PostDelayedTask( 188 bool RasterWorkerPool::PostDelayedTask(
178 const tracked_objects::Location& from_here, 189 const tracked_objects::Location& from_here,
(...skipping 25 matching lines...) Expand all
204 215
205 ScheduleTasksWithLockAcquired(namespace_token_, &graph_); 216 ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
206 completed_tasks_.clear(); 217 completed_tasks_.clear();
207 return true; 218 return true;
208 } 219 }
209 220
210 bool RasterWorkerPool::RunsTasksOnCurrentThread() const { 221 bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
211 return true; 222 return true;
212 } 223 }
213 224
214 void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories) { 225 void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories,
226 base::ConditionVariable* ready_to_run_tasks_cv) {
215 base::AutoLock lock(lock_); 227 base::AutoLock lock(lock_);
216 228
217 while (true) { 229 while (true) {
218 if (!RunTaskWithLockAcquired(categories)) { 230 if (!RunTaskWithLockAcquired(categories)) {
231 // We are no longer running tasks, which may allow another category to
232 // start running. Signal other worker threads.
233 SignalHasReadyToRunTasksWithLockAcquired();
reveman 2016/02/10 20:49:32 Is this necessary if we keep the signal after work
ericrk 2016/02/10 22:30:04 So, if we signal after completing a task, signalin
reveman 2016/02/10 23:25:08 Yes, current code makes sense. Thanks for explaini
234
219 // Exit when shutdown is set and no more tasks are pending. 235 // Exit when shutdown is set and no more tasks are pending.
220 if (shutdown_) 236 if (shutdown_)
221 break; 237 break;
222 238
223 // Wait for more tasks. 239 // Wait for more tasks.
224 has_ready_to_run_tasks_cv_.Wait(); 240 ready_to_run_tasks_cv->Wait();
225 continue; 241 continue;
226 } 242 }
227 } 243 }
228 } 244 }
229 245
230 void RasterWorkerPool::FlushForTesting() { 246 void RasterWorkerPool::FlushForTesting() {
231 base::AutoLock lock(lock_); 247 base::AutoLock lock(lock_);
232 248
233 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) { 249 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) {
234 has_namespaces_with_finished_running_tasks_cv_.Wait(); 250 has_namespaces_with_finished_running_tasks_cv_.Wait();
(...skipping 24 matching lines...) Expand all
259 } 275 }
260 276
261 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token, 277 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
262 cc::TaskGraph* graph) { 278 cc::TaskGraph* graph) {
263 DCHECK(token.IsValid()); 279 DCHECK(token.IsValid());
264 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph)); 280 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph));
265 DCHECK(!shutdown_); 281 DCHECK(!shutdown_);
266 282
267 work_queue_.ScheduleTasks(token, graph); 283 work_queue_.ScheduleTasks(token, graph);
268 284
269 // If there is more work available, wake up the other worker threads. 285 // There may be more work available, so wake up another worker thread.
270 if (work_queue_.HasReadyToRunTasks()) 286 SignalHasReadyToRunTasksWithLockAcquired();
271 has_ready_to_run_tasks_cv_.Broadcast();
272 } 287 }
273 288
274 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) { 289 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
275 TRACE_EVENT0("disabled-by-default-cc.debug", 290 TRACE_EVENT0("disabled-by-default-cc.debug",
276 "RasterWorkerPool::WaitForTasksToFinishRunning"); 291 "RasterWorkerPool::WaitForTasksToFinishRunning");
277 292
278 DCHECK(token.IsValid()); 293 DCHECK(token.IsValid());
279 294
280 { 295 {
281 base::AutoLock lock(lock_); 296 base::AutoLock lock(lock_);
282 base::ThreadRestrictions::ScopedAllowWait allow_wait; 297 base::ThreadRestrictions::ScopedAllowWait allow_wait;
283 298
284 auto* task_namespace = work_queue_.GetNamespaceForToken(token); 299 auto* task_namespace = work_queue_.GetNamespaceForToken(token);
285 300
286 if (!task_namespace) 301 if (!task_namespace)
287 return; 302 return;
288 303
289 while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace)) 304 while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace))
290 has_namespaces_with_finished_running_tasks_cv_.Wait(); 305 has_namespaces_with_finished_running_tasks_cv_.Wait();
306
307 // There may be other namespaces that have finished running tasks, so wake
308 // up another origin thread.
309 has_namespaces_with_finished_running_tasks_cv_.Signal();
291 } 310 }
292 } 311 }
293 312
294 void RasterWorkerPool::CollectCompletedTasks( 313 void RasterWorkerPool::CollectCompletedTasks(
295 cc::NamespaceToken token, 314 cc::NamespaceToken token,
296 cc::Task::Vector* completed_tasks) { 315 cc::Task::Vector* completed_tasks) {
297 TRACE_EVENT0("disabled-by-default-cc.debug", 316 TRACE_EVENT0("disabled-by-default-cc.debug",
298 "RasterWorkerPool::CollectCompletedTasks"); 317 "RasterWorkerPool::CollectCompletedTasks");
299 318
300 { 319 {
(...skipping 22 matching lines...) Expand all
323 342
324 void RasterWorkerPool::RunTaskInCategoryWithLockAcquired( 343 void RasterWorkerPool::RunTaskInCategoryWithLockAcquired(
325 cc::TaskCategory category) { 344 cc::TaskCategory category) {
326 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask"); 345 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
327 346
328 lock_.AssertAcquired(); 347 lock_.AssertAcquired();
329 348
330 auto prioritized_task = work_queue_.GetNextTaskToRun(category); 349 auto prioritized_task = work_queue_.GetNextTaskToRun(category);
331 cc::Task* task = prioritized_task.task; 350 cc::Task* task = prioritized_task.task;
332 351
352 // There may be more work available, so wake up another worker thread.
353 SignalHasReadyToRunTasksWithLockAcquired();
354
333 // Call WillRun() before releasing |lock_| and running task. 355 // Call WillRun() before releasing |lock_| and running task.
334 task->WillRun(); 356 task->WillRun();
335 357
336 { 358 {
337 base::AutoUnlock unlock(lock_); 359 base::AutoUnlock unlock(lock_);
338 360
339 task->RunOnWorkerThread(); 361 task->RunOnWorkerThread();
340 } 362 }
341 363
342 // This will mark task as finished running. 364 // This will mark task as finished running.
343 task->DidRun(); 365 task->DidRun();
344 366
345 work_queue_.CompleteTask(prioritized_task); 367 work_queue_.CompleteTask(prioritized_task);
346 368
347 // We may have just dequeued more tasks, wake up the other worker threads.
348 if (work_queue_.HasReadyToRunTasks())
349 has_ready_to_run_tasks_cv_.Broadcast();
reveman 2016/02/10 20:49:32 Why is this no longer needed? Doesn't CompleteTask
ericrk 2016/02/10 22:30:04 See my comments above.
350
351 // If namespace has finished running all tasks, wake up origin threads. 369 // If namespace has finished running all tasks, wake up origin threads.
352 if (work_queue_.HasFinishedRunningTasksInNamespace( 370 if (work_queue_.HasFinishedRunningTasksInNamespace(
353 prioritized_task.task_namespace)) 371 prioritized_task.task_namespace))
354 has_namespaces_with_finished_running_tasks_cv_.Broadcast(); 372 has_namespaces_with_finished_running_tasks_cv_.Signal();
373 }
374
375 bool RasterWorkerPool::ShouldRunTaskForCategoryWithLockAcquired(
reveman 2016/02/10 20:49:32 Do you think merging this into SignalHasReadyToRun
ericrk 2016/02/10 22:30:04 Meant to use this code in RunTasksWithLockAcquired
reveman 2016/02/10 23:25:08 Got it. Looks good now.
376 cc::TaskCategory category) {
377 lock_.AssertAcquired();
378
379 if (category == cc::TASK_CATEGORY_BACKGROUND) {
380 // Only run background tasks if there are no foreground tasks running or
381 // ready to run.
382 size_t num_running_foreground_tasks =
383 work_queue_.NumRunningTasksForCategory(
384 cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND) +
385 work_queue_.NumRunningTasksForCategory(cc::TASK_CATEGORY_FOREGROUND);
386 bool has_ready_to_run_foreground_tasks =
387 work_queue_.HasReadyToRunTasksForCategory(
388 cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND) ||
389 work_queue_.HasReadyToRunTasksForCategory(cc::TASK_CATEGORY_FOREGROUND);
390
391 if (num_running_foreground_tasks > 0 || has_ready_to_run_foreground_tasks)
392 return false;
393 }
394
395 // Enforce that only one nonconcurrent task runs at a time.
396 if (category == cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND &&
397 work_queue_.NumRunningTasksForCategory(
398 cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND) > 0) {
399 return false;
400 }
401
402 return work_queue_.HasReadyToRunTasksForCategory(category);
reveman 2016/02/10 20:49:32 Maybe early out and avoid all the work above if th
ericrk 2016/02/10 22:30:04 Done.
403 }
404
405 void RasterWorkerPool::SignalHasReadyToRunTasksWithLockAcquired() {
406 lock_.AssertAcquired();
407
408 if (ShouldRunTaskForCategoryWithLockAcquired(cc::TASK_CATEGORY_FOREGROUND) ||
409 ShouldRunTaskForCategoryWithLockAcquired(
410 cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND)) {
411 foreground_has_ready_to_run_tasks_cv_.Signal();
412 }
413
414 if (ShouldRunTaskForCategoryWithLockAcquired(cc::TASK_CATEGORY_BACKGROUND)) {
415 background_has_ready_to_run_tasks_cv_.Signal();
416 }
355 } 417 }
356 418
357 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) 419 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
358 : closure_(closure) {} 420 : closure_(closure) {}
359 421
360 // Overridden from cc::Task: 422 // Overridden from cc::Task:
361 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() { 423 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() {
362 closure_.Run(); 424 closure_.Run();
363 closure_.Reset(); 425 closure_.Reset();
364 } 426 }
365 427
366 RasterWorkerPool::ClosureTask::~ClosureTask() {} 428 RasterWorkerPool::ClosureTask::~ClosureTask() {}
367 429
368 } // namespace content 430 } // namespace content
OLDNEW
« cc/raster/task_graph_work_queue.cc ('K') | « content/renderer/raster_worker_pool.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698