| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "gpu/command_buffer/service/sync_point_manager.h" | 5 #include "gpu/command_buffer/service/sync_point_manager.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include <climits> | 11 #include <climits> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/containers/hash_tables.h" | 14 #include "base/containers/hash_tables.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
| 18 #include "base/sequence_checker.h" | 18 #include "base/sequence_checker.h" |
| 19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 20 | 20 |
| 21 namespace gpu { | 21 namespace gpu { |
| 22 | 22 |
| 23 static const int kMaxSyncBase = INT_MAX; | |
| 24 | |
| 25 namespace { | 23 namespace { |
| 26 | 24 |
| 27 void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 25 void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 28 const base::Closure& callback) { | 26 const base::Closure& callback) { |
| 29 if (task_runner->BelongsToCurrentThread()) { | 27 if (task_runner->BelongsToCurrentThread()) { |
| 30 callback.Run(); | 28 callback.Run(); |
| 31 } else { | 29 } else { |
| 32 task_runner->PostTask(FROM_HERE, callback); | 30 task_runner->PostTask(FROM_HERE, callback); |
| 33 } | 31 } |
| 34 } | 32 } |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 | 331 |
| 334 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, | 332 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, |
| 335 scoped_refptr<SyncPointOrderData> order_data, | 333 scoped_refptr<SyncPointOrderData> order_data, |
| 336 CommandBufferNamespace namespace_id, | 334 CommandBufferNamespace namespace_id, |
| 337 uint64_t client_id) | 335 uint64_t client_id) |
| 338 : sync_point_manager_(sync_point_manager), | 336 : sync_point_manager_(sync_point_manager), |
| 339 client_state_(new SyncPointClientState(order_data)), | 337 client_state_(new SyncPointClientState(order_data)), |
| 340 namespace_id_(namespace_id), | 338 namespace_id_(namespace_id), |
| 341 client_id_(client_id) {} | 339 client_id_(client_id) {} |
| 342 | 340 |
| 343 SyncPointManager::SyncPointManager(bool allow_threaded_wait) | 341 SyncPointManager::SyncPointManager(bool allow_threaded_wait) { |
| 344 : // To reduce the risk that a sync point created in a previous GPU process | |
| 345 // will be in flight in the next GPU process, randomize the starting sync | |
| 346 // point number. http://crbug.com/373452 | |
| 347 next_sync_point_(base::RandInt(1, kMaxSyncBase)) { | |
| 348 global_order_num_.GetNext(); | 342 global_order_num_.GetNext(); |
| 349 } | 343 } |
| 350 | 344 |
| 351 SyncPointManager::~SyncPointManager() { | 345 SyncPointManager::~SyncPointManager() { |
| 352 for (const ClientMap& client_map : client_maps_) { | 346 for (const ClientMap& client_map : client_maps_) { |
| 353 DCHECK(client_map.empty()); | 347 DCHECK(client_map.empty()); |
| 354 } | 348 } |
| 355 } | 349 } |
| 356 | 350 |
| 357 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( | 351 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 382 base::AutoLock auto_lock(client_maps_lock_); | 376 base::AutoLock auto_lock(client_maps_lock_); |
| 383 ClientMap& client_map = client_maps_[namespace_id]; | 377 ClientMap& client_map = client_maps_[namespace_id]; |
| 384 ClientMap::iterator it = client_map.find(client_id); | 378 ClientMap::iterator it = client_map.find(client_id); |
| 385 if (it != client_map.end()) { | 379 if (it != client_map.end()) { |
| 386 return it->second->client_state(); | 380 return it->second->client_state(); |
| 387 } | 381 } |
| 388 } | 382 } |
| 389 return nullptr; | 383 return nullptr; |
| 390 } | 384 } |
| 391 | 385 |
| 392 uint32_t SyncPointManager::GenerateSyncPoint() { | |
| 393 base::AutoLock lock(lock_); | |
| 394 uint32_t sync_point = next_sync_point_++; | |
| 395 // When an integer overflow occurs, don't return 0. | |
| 396 if (!sync_point) | |
| 397 sync_point = next_sync_point_++; | |
| 398 | |
| 399 // Note: wrapping would take days for a buggy/compromized renderer that would | |
| 400 // insert sync points in a loop, but if that were to happen, better explicitly | |
| 401 // crash the GPU process than risk worse. | |
| 402 // For normal operation (at most a few per frame), it would take ~a year to | |
| 403 // wrap. | |
| 404 CHECK(sync_point_map_.find(sync_point) == sync_point_map_.end()); | |
| 405 sync_point_map_.insert(std::make_pair(sync_point, ClosureList())); | |
| 406 return sync_point; | |
| 407 } | |
| 408 | |
| 409 void SyncPointManager::RetireSyncPoint(uint32_t sync_point) { | |
| 410 ClosureList list; | |
| 411 { | |
| 412 base::AutoLock lock(lock_); | |
| 413 SyncPointMap::iterator it = sync_point_map_.find(sync_point); | |
| 414 if (it == sync_point_map_.end()) { | |
| 415 LOG(ERROR) << "Attempted to retire sync point that" | |
| 416 " didn't exist or was already retired."; | |
| 417 return; | |
| 418 } | |
| 419 list.swap(it->second); | |
| 420 sync_point_map_.erase(it); | |
| 421 } | |
| 422 for (ClosureList::iterator i = list.begin(); i != list.end(); ++i) | |
| 423 i->Run(); | |
| 424 } | |
| 425 | |
| 426 void SyncPointManager::AddSyncPointCallback(uint32_t sync_point, | |
| 427 const base::Closure& callback) { | |
| 428 { | |
| 429 base::AutoLock lock(lock_); | |
| 430 SyncPointMap::iterator it = sync_point_map_.find(sync_point); | |
| 431 if (it != sync_point_map_.end()) { | |
| 432 it->second.push_back(callback); | |
| 433 return; | |
| 434 } | |
| 435 } | |
| 436 callback.Run(); | |
| 437 } | |
| 438 | |
| 439 bool SyncPointManager::IsSyncPointRetired(uint32_t sync_point) { | |
| 440 base::AutoLock lock(lock_); | |
| 441 return IsSyncPointRetiredLocked(sync_point); | |
| 442 } | |
| 443 | |
| 444 bool SyncPointManager::IsSyncPointRetiredLocked(uint32_t sync_point) { | |
| 445 lock_.AssertAcquired(); | |
| 446 return sync_point_map_.find(sync_point) == sync_point_map_.end(); | |
| 447 } | |
| 448 | |
| 449 uint32_t SyncPointManager::GenerateOrderNumber() { | 386 uint32_t SyncPointManager::GenerateOrderNumber() { |
| 450 return global_order_num_.GetNext(); | 387 return global_order_num_.GetNext(); |
| 451 } | 388 } |
| 452 | 389 |
| 453 void SyncPointManager::DestroySyncPointClient( | 390 void SyncPointManager::DestroySyncPointClient( |
| 454 CommandBufferNamespace namespace_id, uint64_t client_id) { | 391 CommandBufferNamespace namespace_id, uint64_t client_id) { |
| 455 DCHECK_GE(namespace_id, 0); | 392 DCHECK_GE(namespace_id, 0); |
| 456 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); | 393 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
| 457 | 394 |
| 458 base::AutoLock auto_lock(client_maps_lock_); | 395 base::AutoLock auto_lock(client_maps_lock_); |
| 459 ClientMap& client_map = client_maps_[namespace_id]; | 396 ClientMap& client_map = client_maps_[namespace_id]; |
| 460 ClientMap::iterator it = client_map.find(client_id); | 397 ClientMap::iterator it = client_map.find(client_id); |
| 461 DCHECK(it != client_map.end()); | 398 DCHECK(it != client_map.end()); |
| 462 client_map.erase(it); | 399 client_map.erase(it); |
| 463 } | 400 } |
| 464 | 401 |
| 465 } // namespace gpu | 402 } // namespace gpu |
| OLD | NEW |