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_->order_data()->IsProcessingOrderNumber()); |
279 | 299 |
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 | 300 // No order number associated with the current execution context, using |
293 // UINT32_MAX will just assume the release is in the SyncPointClientState's | 301 // UINT32_MAX will just assume the release is in the SyncPointClientState's |
294 // order numbers to be executed. | 302 // order numbers to be executed. |
295 if (!release_state->WaitForRelease(UINT32_MAX, release_count, | 303 if (!release_state->WaitForRelease(UINT32_MAX, release_count, |
296 wait_complete_callback)) { | 304 wait_complete_callback)) { |
297 wait_complete_callback.Run(); | 305 wait_complete_callback.Run(); |
298 return false; | 306 return false; |
299 } | 307 } |
300 return true; | 308 return true; |
301 } | 309 } |
302 | 310 |
303 bool SyncPointClientWaiter::WaitNonThreadSafe( | 311 bool SyncPointClient::WaitOutOfOrderNonThreadSafe( |
304 SyncPointClientState* release_state, | 312 SyncPointClientState* release_state, |
305 uint64_t release_count, | 313 uint64_t release_count, |
306 scoped_refptr<base::SingleThreadTaskRunner> runner, | 314 scoped_refptr<base::SingleThreadTaskRunner> runner, |
307 const base::Closure& wait_complete_callback) { | 315 const base::Closure& wait_complete_callback) { |
308 return Wait(release_state, release_count, | 316 return WaitOutOfOrder( |
309 base::Bind(&RunOnThread, runner, wait_complete_callback)); | 317 release_state, release_count, |
| 318 base::Bind(&RunOnThread, runner, wait_complete_callback)); |
310 } | 319 } |
311 | 320 |
| 321 void SyncPointClient::ReleaseFenceSync(uint64_t release) { |
| 322 // Validate that this Release call is between BeginProcessingOrderNumber() and |
| 323 // FinishProcessingOrderNumber(), or else we may deadlock. |
| 324 DCHECK(client_state_->order_data()->IsProcessingOrderNumber()); |
| 325 client_state_->ReleaseFenceSync(release); |
| 326 } |
| 327 |
| 328 SyncPointClient::SyncPointClient() |
| 329 : sync_point_manager_(nullptr), |
| 330 namespace_id_(gpu::CommandBufferNamespace::INVALID), |
| 331 client_id_(0) {} |
| 332 |
| 333 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, |
| 334 scoped_refptr<SyncPointOrderData> order_data, |
| 335 CommandBufferNamespace namespace_id, |
| 336 uint64_t client_id) |
| 337 : sync_point_manager_(sync_point_manager), |
| 338 client_state_(new SyncPointClientState(order_data)), |
| 339 namespace_id_(namespace_id), |
| 340 client_id_(client_id) {} |
| 341 |
312 SyncPointManager::SyncPointManager(bool allow_threaded_wait) | 342 SyncPointManager::SyncPointManager(bool allow_threaded_wait) |
313 : allow_threaded_wait_(allow_threaded_wait), | 343 : allow_threaded_wait_(allow_threaded_wait), |
314 // To reduce the risk that a sync point created in a previous GPU process | 344 // 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 | 345 // will be in flight in the next GPU process, randomize the starting sync |
316 // point number. http://crbug.com/373452 | 346 // point number. http://crbug.com/373452 |
317 next_sync_point_(base::RandInt(1, kMaxSyncBase)), | 347 next_sync_point_(base::RandInt(1, kMaxSyncBase)), |
318 retire_cond_var_(&lock_) { | 348 retire_cond_var_(&lock_) { |
319 global_order_num_.GetNext(); | 349 global_order_num_.GetNext(); |
320 } | 350 } |
321 | 351 |
(...skipping 13 matching lines...) Expand all Loading... |
335 | 365 |
336 ClientMap& client_map = client_maps_[namespace_id]; | 366 ClientMap& client_map = client_maps_[namespace_id]; |
337 std::pair<ClientMap::iterator, bool> result = client_map.insert( | 367 std::pair<ClientMap::iterator, bool> result = client_map.insert( |
338 std::make_pair(client_id, new SyncPointClient(this, order_data, | 368 std::make_pair(client_id, new SyncPointClient(this, order_data, |
339 namespace_id, client_id))); | 369 namespace_id, client_id))); |
340 DCHECK(result.second); | 370 DCHECK(result.second); |
341 | 371 |
342 return make_scoped_ptr(result.first->second); | 372 return make_scoped_ptr(result.first->second); |
343 } | 373 } |
344 | 374 |
| 375 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClientWaiter() { |
| 376 return make_scoped_ptr(new SyncPointClient); |
| 377 } |
| 378 |
345 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( | 379 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( |
346 CommandBufferNamespace namespace_id, uint64_t client_id) { | 380 CommandBufferNamespace namespace_id, uint64_t client_id) { |
347 if (namespace_id >= 0) { | 381 if (namespace_id >= 0) { |
348 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); | 382 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
349 base::AutoLock auto_lock(client_maps_lock_); | 383 base::AutoLock auto_lock(client_maps_lock_); |
350 ClientMap& client_map = client_maps_[namespace_id]; | 384 ClientMap& client_map = client_maps_[namespace_id]; |
351 ClientMap::iterator it = client_map.find(client_id); | 385 ClientMap::iterator it = client_map.find(client_id); |
352 if (it != client_map.end()) { | 386 if (it != client_map.end()) { |
353 return it->second->client_state(); | 387 return it->second->client_state(); |
354 } | 388 } |
(...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_)); | 471 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
438 | 472 |
439 base::AutoLock auto_lock(client_maps_lock_); | 473 base::AutoLock auto_lock(client_maps_lock_); |
440 ClientMap& client_map = client_maps_[namespace_id]; | 474 ClientMap& client_map = client_maps_[namespace_id]; |
441 ClientMap::iterator it = client_map.find(client_id); | 475 ClientMap::iterator it = client_map.find(client_id); |
442 DCHECK(it != client_map.end()); | 476 DCHECK(it != client_map.end()); |
443 client_map.erase(it); | 477 client_map.erase(it); |
444 } | 478 } |
445 | 479 |
446 } // namespace gpu | 480 } // namespace gpu |
OLD | NEW |