| 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 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 const uint32_t order_num = sync_point_manager->GenerateOrderNumber(); | 57 const uint32_t order_num = sync_point_manager->GenerateOrderNumber(); |
| 58 base::AutoLock auto_lock(lock_); | 58 base::AutoLock auto_lock(lock_); |
| 59 unprocessed_order_num_ = order_num; | 59 unprocessed_order_num_ = order_num; |
| 60 return order_num; | 60 return order_num; |
| 61 } | 61 } |
| 62 | 62 |
| 63 void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) { | 63 void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) { |
| 64 DCHECK(processing_thread_checker_.CalledOnValidThread()); | 64 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| 65 DCHECK_GE(order_num, current_order_num_); | 65 DCHECK_GE(order_num, current_order_num_); |
| 66 current_order_num_ = order_num; | 66 current_order_num_ = order_num; |
| 67 paused_ = false; |
| 67 | 68 |
| 68 // Catch invalid waits which were waiting on fence syncs that do not exist. | 69 // Catch invalid waits which were waiting on fence syncs that do not exist. |
| 69 // When we begin processing an order number, we should release any fence | 70 // When we begin processing an order number, we should release any fence |
| 70 // syncs which were enqueued but the order number never existed. | 71 // syncs which were enqueued but the order number never existed. |
| 71 // Release without the lock to avoid possible deadlocks. | 72 // Release without the lock to avoid possible deadlocks. |
| 72 std::vector<OrderFence> ensure_releases; | 73 std::vector<OrderFence> ensure_releases; |
| 73 { | 74 { |
| 74 base::AutoLock auto_lock(lock_); | 75 base::AutoLock auto_lock(lock_); |
| 75 while (!order_fence_queue_.empty()) { | 76 while (!order_fence_queue_.empty()) { |
| 76 const OrderFence& order_fence = order_fence_queue_.top(); | 77 const OrderFence& order_fence = order_fence_queue_.top(); |
| 77 if (order_fence_queue_.top().order_num < order_num) { | 78 if (order_fence_queue_.top().order_num < order_num) { |
| 78 ensure_releases.push_back(order_fence); | 79 ensure_releases.push_back(order_fence); |
| 79 order_fence_queue_.pop(); | 80 order_fence_queue_.pop(); |
| 80 continue; | 81 continue; |
| 81 } | 82 } |
| 82 break; | 83 break; |
| 83 } | 84 } |
| 84 } | 85 } |
| 85 | 86 |
| 86 for (OrderFence& order_fence : ensure_releases) { | 87 for (OrderFence& order_fence : ensure_releases) { |
| 87 order_fence.client_state->EnsureReleased(order_fence.fence_release); | 88 order_fence.client_state->EnsureReleased(order_fence.fence_release); |
| 88 } | 89 } |
| 89 } | 90 } |
| 90 | 91 |
| 92 void SyncPointOrderData::PauseProcessingOrderNumber(uint32_t order_num) { |
| 93 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| 94 DCHECK_EQ(current_order_num_, order_num); |
| 95 DCHECK(!paused_); |
| 96 paused_ = true; |
| 97 } |
| 98 |
| 91 void SyncPointOrderData::FinishProcessingOrderNumber(uint32_t order_num) { | 99 void SyncPointOrderData::FinishProcessingOrderNumber(uint32_t order_num) { |
| 92 DCHECK(processing_thread_checker_.CalledOnValidThread()); | 100 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| 93 DCHECK_EQ(current_order_num_, order_num); | 101 DCHECK_EQ(current_order_num_, order_num); |
| 102 DCHECK(!paused_); |
| 94 | 103 |
| 95 // Catch invalid waits which were waiting on fence syncs that do not exist. | 104 // Catch invalid waits which were waiting on fence syncs that do not exist. |
| 96 // When we end processing an order number, we should release any fence syncs | 105 // When we end processing an order number, we should release any fence syncs |
| 97 // which were suppose to be released during this order number. | 106 // which were suppose to be released during this order number. |
| 98 // Release without the lock to avoid possible deadlocks. | 107 // Release without the lock to avoid possible deadlocks. |
| 99 std::vector<OrderFence> ensure_releases; | 108 std::vector<OrderFence> ensure_releases; |
| 100 { | 109 { |
| 101 base::AutoLock auto_lock(lock_); | 110 base::AutoLock auto_lock(lock_); |
| 102 DCHECK_GT(order_num, processed_order_num_); | 111 DCHECK_GT(order_num, processed_order_num_); |
| 103 processed_order_num_ = order_num; | 112 processed_order_num_ = order_num; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 121 SyncPointOrderData::OrderFence::OrderFence( | 130 SyncPointOrderData::OrderFence::OrderFence( |
| 122 uint32_t order, | 131 uint32_t order, |
| 123 uint64_t release, | 132 uint64_t release, |
| 124 scoped_refptr<SyncPointClientState> state) | 133 scoped_refptr<SyncPointClientState> state) |
| 125 : order_num(order), fence_release(release), client_state(state) {} | 134 : order_num(order), fence_release(release), client_state(state) {} |
| 126 | 135 |
| 127 SyncPointOrderData::OrderFence::~OrderFence() {} | 136 SyncPointOrderData::OrderFence::~OrderFence() {} |
| 128 | 137 |
| 129 SyncPointOrderData::SyncPointOrderData() | 138 SyncPointOrderData::SyncPointOrderData() |
| 130 : current_order_num_(0), | 139 : current_order_num_(0), |
| 140 paused_(false), |
| 131 destroyed_(false), | 141 destroyed_(false), |
| 132 processed_order_num_(0), | 142 processed_order_num_(0), |
| 133 unprocessed_order_num_(0) {} | 143 unprocessed_order_num_(0) {} |
| 134 | 144 |
| 135 SyncPointOrderData::~SyncPointOrderData() {} | 145 SyncPointOrderData::~SyncPointOrderData() {} |
| 136 | 146 |
| 137 bool SyncPointOrderData::ValidateReleaseOrderNumber( | 147 bool SyncPointOrderData::ValidateReleaseOrderNumber( |
| 138 scoped_refptr<SyncPointClientState> client_state, | 148 scoped_refptr<SyncPointClientState> client_state, |
| 139 uint32_t wait_order_num, | 149 uint32_t wait_order_num, |
| 140 uint64_t fence_release) { | 150 uint64_t fence_release) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 | 245 |
| 236 fence_sync_release_ = release; | 246 fence_sync_release_ = release; |
| 237 while (!release_callback_queue_.empty() && | 247 while (!release_callback_queue_.empty() && |
| 238 release_callback_queue_.top().release_count <= release) { | 248 release_callback_queue_.top().release_count <= release) { |
| 239 callback_list->push_back(release_callback_queue_.top().callback_closure); | 249 callback_list->push_back(release_callback_queue_.top().callback_closure); |
| 240 release_callback_queue_.pop(); | 250 release_callback_queue_.pop(); |
| 241 } | 251 } |
| 242 } | 252 } |
| 243 | 253 |
| 244 SyncPointClient::~SyncPointClient() { | 254 SyncPointClient::~SyncPointClient() { |
| 245 // Release all fences on destruction. | 255 if (namespace_id_ != gpu::CommandBufferNamespace::INVALID) { |
| 246 ReleaseFenceSync(UINT64_MAX); | 256 // Release all fences on destruction. |
| 257 client_state_->ReleaseFenceSync(UINT64_MAX); |
| 247 | 258 |
| 248 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); | 259 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); |
| 260 } |
| 249 } | 261 } |
| 250 | 262 |
| 251 bool SyncPointClient::Wait(SyncPointClientState* release_state, | 263 bool SyncPointClient::Wait(SyncPointClientState* release_state, |
| 252 uint64_t release_count, | 264 uint64_t release_count, |
| 253 const base::Closure& wait_complete_callback) { | 265 const base::Closure& wait_complete_callback) { |
| 266 // Validate that this Wait call is between BeginProcessingOrderNumber() and |
| 267 // FinishProcessingOrderNumber(), or else we may deadlock. |
| 268 DCHECK(client_state_->order_data()->IsProcessingOrderNumber()); |
| 269 |
| 254 const uint32_t wait_order_number = | 270 const uint32_t wait_order_number = |
| 255 client_state_->order_data()->current_order_num(); | 271 client_state_->order_data()->current_order_num(); |
| 256 | 272 |
| 257 // If waiting on self or wait was invalid, call the callback and return false. | 273 // If waiting on self or wait was invalid, call the callback and return false. |
| 258 if (client_state_ == release_state || | 274 if (client_state_ == release_state || |
| 259 !release_state->WaitForRelease(wait_order_number, release_count, | 275 !release_state->WaitForRelease(wait_order_number, release_count, |
| 260 wait_complete_callback)) { | 276 wait_complete_callback)) { |
| 261 wait_complete_callback.Run(); | 277 wait_complete_callback.Run(); |
| 262 return false; | 278 return false; |
| 263 } | 279 } |
| 264 return true; | 280 return true; |
| 265 } | 281 } |
| 266 | 282 |
| 267 bool SyncPointClient::WaitNonThreadSafe( | 283 bool SyncPointClient::WaitNonThreadSafe( |
| 268 SyncPointClientState* release_state, | 284 SyncPointClientState* release_state, |
| 269 uint64_t release_count, | 285 uint64_t release_count, |
| 270 scoped_refptr<base::SingleThreadTaskRunner> runner, | 286 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 271 const base::Closure& wait_complete_callback) { | 287 const base::Closure& wait_complete_callback) { |
| 272 return Wait(release_state, release_count, | 288 return Wait(release_state, release_count, |
| 273 base::Bind(&RunOnThread, runner, wait_complete_callback)); | 289 base::Bind(&RunOnThread, runner, wait_complete_callback)); |
| 274 } | 290 } |
| 275 | 291 |
| 276 void SyncPointClient::ReleaseFenceSync(uint64_t release) { | 292 bool SyncPointClient::WaitOutOfOrder( |
| 277 client_state_->ReleaseFenceSync(release); | 293 SyncPointClientState* release_state, |
| 278 } | 294 uint64_t release_count, |
| 295 const base::Closure& wait_complete_callback) { |
| 296 // Validate that this Wait call is not between BeginProcessingOrderNumber() |
| 297 // and FinishProcessingOrderNumber(), or else we may deadlock. |
| 298 DCHECK(!client_state_ || |
| 299 !client_state_->order_data()->IsProcessingOrderNumber()); |
| 279 | 300 |
| 280 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, | |
| 281 scoped_refptr<SyncPointOrderData> order_data, | |
| 282 CommandBufferNamespace namespace_id, | |
| 283 uint64_t client_id) | |
| 284 : sync_point_manager_(sync_point_manager), | |
| 285 client_state_(new SyncPointClientState(order_data)), | |
| 286 namespace_id_(namespace_id), | |
| 287 client_id_(client_id) {} | |
| 288 | |
| 289 bool SyncPointClientWaiter::Wait(SyncPointClientState* release_state, | |
| 290 uint64_t release_count, | |
| 291 const base::Closure& wait_complete_callback) { | |
| 292 // No order number associated with the current execution context, using | 301 // No order number associated with the current execution context, using |
| 293 // UINT32_MAX will just assume the release is in the SyncPointClientState's | 302 // UINT32_MAX will just assume the release is in the SyncPointClientState's |
| 294 // order numbers to be executed. | 303 // order numbers to be executed. |
| 295 if (!release_state->WaitForRelease(UINT32_MAX, release_count, | 304 if (!release_state->WaitForRelease(UINT32_MAX, release_count, |
| 296 wait_complete_callback)) { | 305 wait_complete_callback)) { |
| 297 wait_complete_callback.Run(); | 306 wait_complete_callback.Run(); |
| 298 return false; | 307 return false; |
| 299 } | 308 } |
| 300 return true; | 309 return true; |
| 301 } | 310 } |
| 302 | 311 |
| 303 bool SyncPointClientWaiter::WaitNonThreadSafe( | 312 bool SyncPointClient::WaitOutOfOrderNonThreadSafe( |
| 304 SyncPointClientState* release_state, | 313 SyncPointClientState* release_state, |
| 305 uint64_t release_count, | 314 uint64_t release_count, |
| 306 scoped_refptr<base::SingleThreadTaskRunner> runner, | 315 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 307 const base::Closure& wait_complete_callback) { | 316 const base::Closure& wait_complete_callback) { |
| 308 return Wait(release_state, release_count, | 317 return WaitOutOfOrder( |
| 309 base::Bind(&RunOnThread, runner, wait_complete_callback)); | 318 release_state, release_count, |
| 319 base::Bind(&RunOnThread, runner, wait_complete_callback)); |
| 310 } | 320 } |
| 311 | 321 |
| 322 void SyncPointClient::ReleaseFenceSync(uint64_t release) { |
| 323 // Validate that this Release call is between BeginProcessingOrderNumber() and |
| 324 // FinishProcessingOrderNumber(), or else we may deadlock. |
| 325 DCHECK(client_state_->order_data()->IsProcessingOrderNumber()); |
| 326 client_state_->ReleaseFenceSync(release); |
| 327 } |
| 328 |
| 329 SyncPointClient::SyncPointClient() |
| 330 : sync_point_manager_(nullptr), |
| 331 namespace_id_(gpu::CommandBufferNamespace::INVALID), |
| 332 client_id_(0) {} |
| 333 |
| 334 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, |
| 335 scoped_refptr<SyncPointOrderData> order_data, |
| 336 CommandBufferNamespace namespace_id, |
| 337 uint64_t client_id) |
| 338 : sync_point_manager_(sync_point_manager), |
| 339 client_state_(new SyncPointClientState(order_data)), |
| 340 namespace_id_(namespace_id), |
| 341 client_id_(client_id) {} |
| 342 |
| 312 SyncPointManager::SyncPointManager(bool allow_threaded_wait) | 343 SyncPointManager::SyncPointManager(bool allow_threaded_wait) |
| 313 : allow_threaded_wait_(allow_threaded_wait), | 344 : allow_threaded_wait_(allow_threaded_wait), |
| 314 // To reduce the risk that a sync point created in a previous GPU process | 345 // To reduce the risk that a sync point created in a previous GPU process |
| 315 // will be in flight in the next GPU process, randomize the starting sync | 346 // will be in flight in the next GPU process, randomize the starting sync |
| 316 // point number. http://crbug.com/373452 | 347 // point number. http://crbug.com/373452 |
| 317 next_sync_point_(base::RandInt(1, kMaxSyncBase)), | 348 next_sync_point_(base::RandInt(1, kMaxSyncBase)), |
| 318 retire_cond_var_(&lock_) { | 349 retire_cond_var_(&lock_) { |
| 319 global_order_num_.GetNext(); | 350 global_order_num_.GetNext(); |
| 320 } | 351 } |
| 321 | 352 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 335 | 366 |
| 336 ClientMap& client_map = client_maps_[namespace_id]; | 367 ClientMap& client_map = client_maps_[namespace_id]; |
| 337 std::pair<ClientMap::iterator, bool> result = client_map.insert( | 368 std::pair<ClientMap::iterator, bool> result = client_map.insert( |
| 338 std::make_pair(client_id, new SyncPointClient(this, order_data, | 369 std::make_pair(client_id, new SyncPointClient(this, order_data, |
| 339 namespace_id, client_id))); | 370 namespace_id, client_id))); |
| 340 DCHECK(result.second); | 371 DCHECK(result.second); |
| 341 | 372 |
| 342 return make_scoped_ptr(result.first->second); | 373 return make_scoped_ptr(result.first->second); |
| 343 } | 374 } |
| 344 | 375 |
| 376 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClientWaiter() { |
| 377 return make_scoped_ptr(new SyncPointClient); |
| 378 } |
| 379 |
| 345 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( | 380 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( |
| 346 CommandBufferNamespace namespace_id, uint64_t client_id) { | 381 CommandBufferNamespace namespace_id, uint64_t client_id) { |
| 347 if (namespace_id >= 0) { | 382 if (namespace_id >= 0) { |
| 348 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); | 383 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
| 349 base::AutoLock auto_lock(client_maps_lock_); | 384 base::AutoLock auto_lock(client_maps_lock_); |
| 350 ClientMap& client_map = client_maps_[namespace_id]; | 385 ClientMap& client_map = client_maps_[namespace_id]; |
| 351 ClientMap::iterator it = client_map.find(client_id); | 386 ClientMap::iterator it = client_map.find(client_id); |
| 352 if (it != client_map.end()) { | 387 if (it != client_map.end()) { |
| 353 return it->second->client_state(); | 388 return it->second->client_state(); |
| 354 } | 389 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); | 472 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
| 438 | 473 |
| 439 base::AutoLock auto_lock(client_maps_lock_); | 474 base::AutoLock auto_lock(client_maps_lock_); |
| 440 ClientMap& client_map = client_maps_[namespace_id]; | 475 ClientMap& client_map = client_maps_[namespace_id]; |
| 441 ClientMap::iterator it = client_map.find(client_id); | 476 ClientMap::iterator it = client_map.find(client_id); |
| 442 DCHECK(it != client_map.end()); | 477 DCHECK(it != client_map.end()); |
| 443 client_map.erase(it); | 478 client_map.erase(it); |
| 444 } | 479 } |
| 445 | 480 |
| 446 } // namespace gpu | 481 } // namespace gpu |
| OLD | NEW |