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 |