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

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: 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 explicit 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 cc::TaskCategory category)
28 : SimpleThread(name_prefix, options), 28 : SimpleThread(name_prefix, options), pool_(pool), category_(category) {}
29 pool_(pool),
30 categories_(categories) {}
31 29
32 void Run() override { pool_->Run(categories_); } 30 void Run() override { pool_->Run(category_); }
33 31
34 private: 32 private:
35 RasterWorkerPool* const pool_; 33 RasterWorkerPool* const pool_;
36 const std::vector<cc::TaskCategory> categories_; 34 const cc::TaskCategory category_;
37 }; 35 };
38 36
39 } // namespace 37 } // namespace
40 38
41 // A sequenced task runner which posts tasks to a RasterWorkerPool. 39 // A sequenced task runner which posts tasks to a RasterWorkerPool.
42 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner 40 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
43 : public base::SequencedTaskRunner { 41 : public base::SequencedTaskRunner {
44 public: 42 public:
45 explicit RasterWorkerPoolSequencedTaskRunner( 43 explicit RasterWorkerPoolSequencedTaskRunner(
46 cc::TaskGraphRunner* task_graph_runner) 44 cc::TaskGraphRunner* task_graph_runner)
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 cc::Task::Vector tasks_; 107 cc::Task::Vector tasks_;
110 // Graph object used for scheduling tasks. 108 // Graph object used for scheduling tasks.
111 cc::TaskGraph graph_; 109 cc::TaskGraph graph_;
112 // Cached vector to avoid allocation when getting the list of complete 110 // Cached vector to avoid allocation when getting the list of complete
113 // tasks. 111 // tasks.
114 cc::Task::Vector completed_tasks_; 112 cc::Task::Vector completed_tasks_;
115 }; 113 };
116 114
117 RasterWorkerPool::RasterWorkerPool() 115 RasterWorkerPool::RasterWorkerPool()
118 : namespace_token_(GetNamespaceToken()), 116 : namespace_token_(GetNamespaceToken()),
119 has_ready_to_run_tasks_cv_(&lock_), 117 nonconcurrent_foreground_has_ready_to_run_tasks_cv_(&lock_),
118 foreground_has_ready_to_run_tasks_cv_(&lock_),
119 background_has_ready_to_run_tasks_cv_(&lock_),
120 nonconcurrent_foreground_running_task_count_(0),
121 foreground_running_task_count_(0),
122 background_running_task_count_(0),
123 target_running_task_count_(0),
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 target_running_task_count_ = num_threads;
132 if (threads_.size() == 0) {
133 task_categories.push_back(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND);
134 }
135 133
136 // All threads can run foreground tasks. 134 // Start a single thread for nonconcurrent foreground work.
137 task_categories.push_back(cc::TASK_CATEGORY_FOREGROUND); 135 {
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( 136 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
145 base::StringPrintf("CompositorTileWorker%u", 137 base::StringPrintf("CompositorTileWorker%u",
146 static_cast<unsigned>(threads_.size() + 1)) 138 static_cast<unsigned>(threads_.size() + 1))
147 .c_str(), 139 .c_str(),
148 thread_options, this, task_categories)); 140 thread_options, this, cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND));
149 thread->Start(); 141 thread->Start();
150 threads_.push_back(std::move(thread)); 142 threads_.push_back(std::move(thread));
151 } 143 }
144
145 // start |num_threads| threads for foreground work.
146 for (int i = 0; i < num_threads; i++) {
147 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
148 base::StringPrintf("CompositorTileWorker%u",
149 static_cast<unsigned>(threads_.size() + 1))
150 .c_str(),
151 thread_options, this, cc::TASK_CATEGORY_FOREGROUND));
152 thread->Start();
153 threads_.push_back(std::move(thread));
154 }
155
156 // Start a single thread for background work.
157 {
158 scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
159 base::StringPrintf("CompositorTileWorker%u",
160 static_cast<unsigned>(threads_.size() + 1))
161 .c_str(),
162 thread_options, this, cc::TASK_CATEGORY_BACKGROUND));
163 thread->Start();
164 threads_.push_back(std::move(thread));
165 }
152 } 166 }
153 167
154 void RasterWorkerPool::Shutdown() { 168 void RasterWorkerPool::Shutdown() {
155 WaitForTasksToFinishRunning(namespace_token_); 169 WaitForTasksToFinishRunning(namespace_token_);
156 CollectCompletedTasks(namespace_token_, &completed_tasks_); 170 CollectCompletedTasks(namespace_token_, &completed_tasks_);
157 // Shutdown raster threads. 171 // Shutdown raster threads.
158 { 172 {
159 base::AutoLock lock(lock_); 173 base::AutoLock lock(lock_);
160 174
161 DCHECK(!work_queue_.HasReadyToRunTasks()); 175 DCHECK(!work_queue_.HasReadyToRunTasks());
162 DCHECK(!work_queue_.HasAnyNamespaces()); 176 DCHECK(!work_queue_.HasAnyNamespaces());
163 177
164 DCHECK(!shutdown_); 178 DCHECK(!shutdown_);
165 shutdown_ = true; 179 shutdown_ = true;
166 180
167 // Wake up all workers so they exit. 181 // Wake up all workers so they exit.
168 has_ready_to_run_tasks_cv_.Broadcast(); 182 nonconcurrent_foreground_has_ready_to_run_tasks_cv_.Broadcast();
183 foreground_has_ready_to_run_tasks_cv_.Broadcast();
184 background_has_ready_to_run_tasks_cv_.Broadcast();
169 } 185 }
170 while (!threads_.empty()) { 186 while (!threads_.empty()) {
171 threads_.back()->Join(); 187 threads_.back()->Join();
172 threads_.pop_back(); 188 threads_.pop_back();
173 } 189 }
174 } 190 }
175 191
176 // Overridden from base::TaskRunner: 192 // Overridden from base::TaskRunner:
177 bool RasterWorkerPool::PostDelayedTask( 193 bool RasterWorkerPool::PostDelayedTask(
178 const tracked_objects::Location& from_here, 194 const tracked_objects::Location& from_here,
(...skipping 25 matching lines...) Expand all
204 220
205 ScheduleTasksWithLockAcquired(namespace_token_, &graph_); 221 ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
206 completed_tasks_.clear(); 222 completed_tasks_.clear();
207 return true; 223 return true;
208 } 224 }
209 225
210 bool RasterWorkerPool::RunsTasksOnCurrentThread() const { 226 bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
211 return true; 227 return true;
212 } 228 }
213 229
214 void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories) { 230 void RasterWorkerPool::Run(cc::TaskCategory category) {
215 base::AutoLock lock(lock_); 231 base::AutoLock lock(lock_);
232 base::ConditionVariable& cv = ConditionVariableForCategory(category);
216 233
217 while (true) { 234 while (true) {
218 if (!RunTaskWithLockAcquired(categories)) { 235 if (!ShouldRunTaskForCategory(category)) {
236 // We are no longer running tasks, which may allow another category to
237 // start running. Signal other worker threads.
238 SignalTaskReadyConditionVariables();
239
219 // Exit when shutdown is set and no more tasks are pending. 240 // Exit when shutdown is set and no more tasks are pending.
220 if (shutdown_) 241 if (shutdown_)
221 break; 242 break;
222 243
223 // Wait for more tasks. 244 // Wait for more tasks.
224 has_ready_to_run_tasks_cv_.Wait(); 245 cv.Wait();
225 continue; 246 continue;
226 } 247 }
248 RunTaskWithLockAcquired(category);
227 } 249 }
228 } 250 }
229 251
230 void RasterWorkerPool::FlushForTesting() { 252 void RasterWorkerPool::FlushForTesting() {
231 base::AutoLock lock(lock_); 253 base::AutoLock lock(lock_);
232 254
233 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) { 255 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) {
234 has_namespaces_with_finished_running_tasks_cv_.Wait(); 256 has_namespaces_with_finished_running_tasks_cv_.Wait();
235 } 257 }
236 } 258 }
(...skipping 22 matching lines...) Expand all
259 } 281 }
260 282
261 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token, 283 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
262 cc::TaskGraph* graph) { 284 cc::TaskGraph* graph) {
263 DCHECK(token.IsValid()); 285 DCHECK(token.IsValid());
264 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph)); 286 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph));
265 DCHECK(!shutdown_); 287 DCHECK(!shutdown_);
266 288
267 work_queue_.ScheduleTasks(token, graph); 289 work_queue_.ScheduleTasks(token, graph);
268 290
269 // If there is more work available, wake up the other worker threads. 291 // There may be more work available, so wake up another worker thread.
270 if (work_queue_.HasReadyToRunTasks()) 292 SignalTaskReadyConditionVariables();
271 has_ready_to_run_tasks_cv_.Broadcast();
272 } 293 }
273 294
274 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) { 295 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
275 TRACE_EVENT0("disabled-by-default-cc.debug", 296 TRACE_EVENT0("disabled-by-default-cc.debug",
276 "RasterWorkerPool::WaitForTasksToFinishRunning"); 297 "RasterWorkerPool::WaitForTasksToFinishRunning");
277 298
278 DCHECK(token.IsValid()); 299 DCHECK(token.IsValid());
279 300
280 { 301 {
281 base::AutoLock lock(lock_); 302 base::AutoLock lock(lock_);
282 base::ThreadRestrictions::ScopedAllowWait allow_wait; 303 base::ThreadRestrictions::ScopedAllowWait allow_wait;
283 304
284 auto* task_namespace = work_queue_.GetNamespaceForToken(token); 305 auto* task_namespace = work_queue_.GetNamespaceForToken(token);
285 306
286 if (!task_namespace) 307 if (!task_namespace)
287 return; 308 return;
288 309
289 while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace)) 310 while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace))
290 has_namespaces_with_finished_running_tasks_cv_.Wait(); 311 has_namespaces_with_finished_running_tasks_cv_.Wait();
312
313 // There may be other namespaces that have finished running tasks, so wake
314 // up another origin thread.
315 has_namespaces_with_finished_running_tasks_cv_.Signal();
291 } 316 }
292 } 317 }
293 318
294 void RasterWorkerPool::CollectCompletedTasks( 319 void RasterWorkerPool::CollectCompletedTasks(
295 cc::NamespaceToken token, 320 cc::NamespaceToken token,
296 cc::Task::Vector* completed_tasks) { 321 cc::Task::Vector* completed_tasks) {
297 TRACE_EVENT0("disabled-by-default-cc.debug", 322 TRACE_EVENT0("disabled-by-default-cc.debug",
298 "RasterWorkerPool::CollectCompletedTasks"); 323 "RasterWorkerPool::CollectCompletedTasks");
299 324
300 { 325 {
301 base::AutoLock lock(lock_); 326 base::AutoLock lock(lock_);
302 CollectCompletedTasksWithLockAcquired(token, completed_tasks); 327 CollectCompletedTasksWithLockAcquired(token, completed_tasks);
303 } 328 }
304 } 329 }
305 330
306 void RasterWorkerPool::CollectCompletedTasksWithLockAcquired( 331 void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
307 cc::NamespaceToken token, 332 cc::NamespaceToken token,
308 cc::Task::Vector* completed_tasks) { 333 cc::Task::Vector* completed_tasks) {
309 DCHECK(token.IsValid()); 334 DCHECK(token.IsValid());
310 work_queue_.CollectCompletedTasks(token, completed_tasks); 335 work_queue_.CollectCompletedTasks(token, completed_tasks);
311 } 336 }
312 337
313 bool RasterWorkerPool::RunTaskWithLockAcquired( 338 void RasterWorkerPool::RunTaskWithLockAcquired(cc::TaskCategory category) {
314 const std::vector<cc::TaskCategory>& categories) {
315 for (const auto& category : categories) {
316 if (work_queue_.HasReadyToRunTasksForCategory(category)) {
317 RunTaskInCategoryWithLockAcquired(category);
318 return true;
319 }
320 }
321 return false;
322 }
323
324 void RasterWorkerPool::RunTaskInCategoryWithLockAcquired(
325 cc::TaskCategory category) {
326 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask"); 339 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
327 340
328 lock_.AssertAcquired(); 341 lock_.AssertAcquired();
329 342
330 auto prioritized_task = work_queue_.GetNextTaskToRun(category); 343 auto prioritized_task = work_queue_.GetNextTaskToRun(category);
331 cc::Task* task = prioritized_task.task; 344 cc::Task* task = prioritized_task.task;
332 345
346 // Create a ScopedTaskCount to increment the task count while running.
347 ScopedTaskCount scoped_task_count = ScopedTaskCountForCategory(category);
348
349 // There may be more work available, so wake up another worker thread.
350 SignalTaskReadyConditionVariables();
351
333 // Call WillRun() before releasing |lock_| and running task. 352 // Call WillRun() before releasing |lock_| and running task.
334 task->WillRun(); 353 task->WillRun();
335 354
336 { 355 {
337 base::AutoUnlock unlock(lock_); 356 base::AutoUnlock unlock(lock_);
338 357
339 task->RunOnWorkerThread(); 358 task->RunOnWorkerThread();
340 } 359 }
341 360
342 // This will mark task as finished running. 361 // This will mark task as finished running.
343 task->DidRun(); 362 task->DidRun();
344 363
345 work_queue_.CompleteTask(prioritized_task); 364 work_queue_.CompleteTask(prioritized_task);
346 365
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();
350
351 // If namespace has finished running all tasks, wake up origin threads. 366 // If namespace has finished running all tasks, wake up origin threads.
352 if (work_queue_.HasFinishedRunningTasksInNamespace( 367 if (work_queue_.HasFinishedRunningTasksInNamespace(
353 prioritized_task.task_namespace)) 368 prioritized_task.task_namespace))
354 has_namespaces_with_finished_running_tasks_cv_.Broadcast(); 369 has_namespaces_with_finished_running_tasks_cv_.Signal();
370 }
371
372 bool RasterWorkerPool::ShouldRunTaskForCategory(cc::TaskCategory category) {
373 // During shutdown we want to flush threads as fast as possible - don't bother
374 // enforcing running task limits.
375 if (!shutdown_) {
376 // Enforce running task limits.
377 int foreground_thread_count = nonconcurrent_foreground_running_task_count_ +
378 foreground_running_task_count_;
379 int total_thread_count =
380 foreground_thread_count + background_running_task_count_;
381 if (total_thread_count >= target_running_task_count_) {
382 return false;
383 }
384
385 if (category == cc::TASK_CATEGORY_BACKGROUND &&
386 foreground_thread_count > 0) {
387 return false;
388 }
389 }
390
391 return work_queue_.HasReadyToRunTasksForCategory(category);
392 }
393
394 void RasterWorkerPool::SignalTaskReadyConditionVariables() {
395 lock_.AssertAcquired();
396 if (ShouldRunTaskForCategory(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND)) {
397 nonconcurrent_foreground_has_ready_to_run_tasks_cv_.Signal();
398 }
399 if (ShouldRunTaskForCategory(cc::TASK_CATEGORY_FOREGROUND)) {
400 foreground_has_ready_to_run_tasks_cv_.Signal();
401 }
402 if (ShouldRunTaskForCategory(cc::TASK_CATEGORY_BACKGROUND)) {
403 background_has_ready_to_run_tasks_cv_.Signal();
404 }
405 }
406
407 RasterWorkerPool::ScopedTaskCount RasterWorkerPool::ScopedTaskCountForCategory(
408 cc::TaskCategory category) {
409 switch (category) {
410 case cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND:
411 return ScopedTaskCount(&nonconcurrent_foreground_running_task_count_);
412 case cc::TASK_CATEGORY_FOREGROUND:
413 return ScopedTaskCount(&foreground_running_task_count_);
414 case cc::TASK_CATEGORY_BACKGROUND:
415 return ScopedTaskCount(&background_running_task_count_);
416 }
417 }
418
419 base::ConditionVariable& RasterWorkerPool::ConditionVariableForCategory(
420 cc::TaskCategory category) {
421 switch (category) {
422 case cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND:
423 return nonconcurrent_foreground_has_ready_to_run_tasks_cv_;
424 case cc::TASK_CATEGORY_FOREGROUND:
425 return foreground_has_ready_to_run_tasks_cv_;
426 case cc::TASK_CATEGORY_BACKGROUND:
427 return background_has_ready_to_run_tasks_cv_;
428 }
355 } 429 }
356 430
357 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) 431 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
358 : closure_(closure) {} 432 : closure_(closure) {}
359 433
360 // Overridden from cc::Task: 434 // Overridden from cc::Task:
361 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() { 435 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() {
362 closure_.Run(); 436 closure_.Run();
363 closure_.Reset(); 437 closure_.Reset();
364 } 438 }
365 439
366 RasterWorkerPool::ClosureTask::~ClosureTask() {} 440 RasterWorkerPool::ClosureTask::~ClosureTask() {}
367 441
368 } // namespace content 442 } // namespace content
OLDNEW
« content/renderer/raster_worker_pool.h ('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