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 <climits> | 7 #include <climits> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
11 #include "base/sequence_checker.h" | 11 #include "base/sequence_checker.h" |
12 | 12 |
13 namespace gpu { | 13 namespace gpu { |
14 | 14 |
15 static const int kMaxSyncBase = INT_MAX; | 15 static const int kMaxSyncBase = INT_MAX; |
16 | 16 |
17 scoped_refptr<SyncPointClientState> SyncPointClientState::Create() { | 17 scoped_refptr<SyncPointClientState> SyncPointClientState::Create() { |
18 return new SyncPointClientState; | 18 return new SyncPointClientState; |
19 } | 19 } |
20 | 20 |
21 uint32_t SyncPointClientState::GenerateUnprocessedOrderNumber( | 21 uint32_t SyncPointClientState::GenerateUnprocessedOrderNumber( |
22 SyncPointManager* sync_point_manager) { | 22 SyncPointManager* sync_point_manager) { |
23 const uint32_t order_num = sync_point_manager->GenerateOrderNumber(); | 23 const uint32_t order_num = sync_point_manager->GenerateOrderNumber(); |
24 base::subtle::Release_Store(&unprocessed_order_num_, order_num); | 24 base::subtle::Release_Store(&unprocessed_order_num_, order_num); |
25 return order_num; | 25 return order_num; |
26 } | 26 } |
27 | 27 |
| 28 void SyncPointClientState::BeginProcessingOrderNumber(uint32_t order_num) { |
| 29 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| 30 DCHECK_GE(order_num, current_order_num_); |
| 31 current_order_num_ = order_num; |
| 32 } |
| 33 |
| 34 void SyncPointClientState::FinishProcessingOrderNumber(uint32_t order_num) { |
| 35 DCHECK(processing_thread_checker_.CalledOnValidThread()); |
| 36 DCHECK_EQ(current_order_num_, order_num); |
| 37 DCHECK_GT(order_num, processed_order_num()); |
| 38 |
| 39 // Catch invalid waits which were waiting on fence syncs that do not exist. |
| 40 uint32_t invalid_release = 0; |
| 41 { |
| 42 base::AutoLock auto_lock(fence_sync_lock_); |
| 43 uint32_t highest_wait_release = 0; |
| 44 while (!order_fence_queue_.empty() && |
| 45 order_fence_queue_.top().order_num <= order_num) { |
| 46 const uint32_t fence_release = order_fence_queue_.top().fence_release; |
| 47 highest_wait_release = std::max(highest_wait_release, fence_release); |
| 48 order_fence_queue_.pop(); |
| 49 } |
| 50 |
| 51 if (highest_wait_release > fence_sync_release_) { |
| 52 invalid_release = fence_sync_release_; |
| 53 } |
| 54 } |
| 55 |
| 56 if (invalid_release) { |
| 57 // Bad wait for release that doesn't exist, release all waits up to here. |
| 58 ReleaseFenceSync(invalid_release); |
| 59 } |
| 60 |
| 61 base::subtle::Release_Store(&processed_order_num_, order_num); |
| 62 } |
| 63 |
28 SyncPointClientState::SyncPointClientState() | 64 SyncPointClientState::SyncPointClientState() |
29 : processed_order_num_(0), | 65 : processed_order_num_(0), |
30 unprocessed_order_num_(0), | 66 unprocessed_order_num_(0), |
31 current_order_num_(0) { | 67 current_order_num_(0), |
| 68 fence_sync_release_(0) { |
32 } | 69 } |
33 | 70 |
34 SyncPointClientState::~SyncPointClientState() { | 71 SyncPointClientState::~SyncPointClientState() { |
| 72 // Release all fences on destruction. |
| 73 ReleaseFenceSync(UINT32_MAX); |
| 74 } |
| 75 |
| 76 SyncPointClientState::ReleaseCallback::ReleaseCallback( |
| 77 uint32_t release, const base::Closure& callback) |
| 78 : release_count(release), |
| 79 callback_closure(callback) { |
| 80 } |
| 81 |
| 82 SyncPointClientState::ReleaseCallback::~ReleaseCallback() { |
| 83 } |
| 84 |
| 85 bool SyncPointClientState::WaitForRelease(uint32_t wait_order_num, |
| 86 uint32_t release, |
| 87 const base::Closure& callback) { |
| 88 // Lock must be held the whole time while we validate otherwise it could be |
| 89 // released while we are checking. |
| 90 { |
| 91 base::AutoLock auto_lock(fence_sync_lock_); |
| 92 if (release > fence_sync_release_) { |
| 93 const uint32_t processed_num = processed_order_num(); |
| 94 const uint32_t unprocessed_num = unprocessed_order_num(); |
| 95 |
| 96 // Release should have a lower order number than wait order number. |
| 97 if (processed_num > wait_order_num) |
| 98 return false; |
| 99 |
| 100 // Release should have more unprocessed numbers if we are waiting. |
| 101 if (unprocessed_num > processed_num) |
| 102 return false; |
| 103 |
| 104 // Add the callback which will be called upon release. |
| 105 release_callback_queue_.push(ReleaseCallback(release, callback)); |
| 106 |
| 107 // Validate by ensuring fence is released by the expected order number. |
| 108 const uint32_t expected_order_num = std::min(unprocessed_num, |
| 109 wait_order_num); |
| 110 order_fence_queue_.push(OrderFence(expected_order_num, release)); |
| 111 |
| 112 return true; |
| 113 } |
| 114 } |
| 115 |
| 116 // Already released, run the callback now. |
| 117 callback.Run(); |
| 118 return true; |
| 119 } |
| 120 |
| 121 void SyncPointClientState::ReleaseFenceSync(uint32_t release) { |
| 122 // Call callbacks without the lock to avoid possible deadlocks. |
| 123 std::vector<base::Closure> callback_list; |
| 124 { |
| 125 base::AutoLock auto_lock(fence_sync_lock_); |
| 126 DCHECK_GT(release, fence_sync_release_); |
| 127 fence_sync_release_ = release; |
| 128 |
| 129 while (!release_callback_queue_.empty() && |
| 130 release_callback_queue_.top().release_count <= release) { |
| 131 callback_list.push_back(release_callback_queue_.top().callback_closure); |
| 132 release_callback_queue_.pop(); |
| 133 } |
| 134 } |
| 135 |
| 136 for (const base::Closure& closure : callback_list) { |
| 137 closure.Run(); |
| 138 } |
35 } | 139 } |
36 | 140 |
37 SyncPointClient::~SyncPointClient() { | 141 SyncPointClient::~SyncPointClient() { |
38 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); | 142 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); |
39 } | 143 } |
40 | 144 |
| 145 bool SyncPointClient::Wait(scoped_refptr<SyncPointClientState> release_state, |
| 146 uint32_t release_count, |
| 147 const base::Closure& wait_complete_callback) { |
| 148 const uint32_t wait_order_number = client_state_->current_order_num(); |
| 149 return release_state->WaitForRelease(wait_order_number, |
| 150 release_count, |
| 151 wait_complete_callback); |
| 152 } |
| 153 |
| 154 void SyncPointClient::ReleaseFenceSync(uint32_t release) { |
| 155 client_state_->ReleaseFenceSync(release); |
| 156 } |
| 157 |
41 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, | 158 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, |
42 scoped_refptr<SyncPointClientState> state, | 159 scoped_refptr<SyncPointClientState> state, |
43 CommandBufferNamespace namespace_id, | 160 CommandBufferNamespace namespace_id, |
44 uint64_t client_id) | 161 uint64_t client_id) |
45 : sync_point_manager_(sync_point_manager), | 162 : sync_point_manager_(sync_point_manager), |
46 client_state_(state), | 163 client_state_(state), |
47 namespace_id_(namespace_id), | 164 namespace_id_(namespace_id), |
48 client_id_(client_id) { | 165 client_id_(client_id) { |
49 } | 166 } |
50 | 167 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); | 294 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); |
178 | 295 |
179 base::AutoLock auto_lock(client_maps_lock_); | 296 base::AutoLock auto_lock(client_maps_lock_); |
180 ClientMap& client_map = client_maps_[namespace_id]; | 297 ClientMap& client_map = client_maps_[namespace_id]; |
181 ClientMap::iterator it = client_map.find(client_id); | 298 ClientMap::iterator it = client_map.find(client_id); |
182 DCHECK(it != client_map.end()); | 299 DCHECK(it != client_map.end()); |
183 client_map.erase(it); | 300 client_map.erase(it); |
184 } | 301 } |
185 | 302 |
186 } // namespace gpu | 303 } // namespace gpu |
OLD | NEW |