Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: gpu/command_buffer/service/sync_point_manager.cc

Issue 1331843005: Implemented new fence syncs which replaces the old sync points. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reverted mojo readme, changed wait() to take a pointer Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/bind.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/location.h"
9 #include "base/logging.h" 12 #include "base/logging.h"
10 #include "base/rand_util.h" 13 #include "base/rand_util.h"
11 #include "base/sequence_checker.h" 14 #include "base/sequence_checker.h"
15 #include "base/single_thread_task_runner.h"
12 16
13 namespace gpu { 17 namespace gpu {
14 18
15 static const int kMaxSyncBase = INT_MAX; 19 static const int kMaxSyncBase = INT_MAX;
16 20
17 scoped_refptr<SyncPointClientState> SyncPointClientState::Create() { 21 namespace {
18 return new SyncPointClientState; 22
19 } 23 void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
20 24 const base::Closure& callback) {
21 uint32_t SyncPointClientState::GenerateUnprocessedOrderNumber( 25 if (task_runner->BelongsToCurrentThread()) {
26 callback.Run();
27 } else {
28 task_runner->PostTask(FROM_HERE, callback);
29 }
30 }
31
32 } // namespace
33
34 scoped_refptr<SyncPointOrderData> SyncPointOrderData::Create() {
35 return new SyncPointOrderData;
36 }
37
38 void SyncPointOrderData::Destroy() {
39 // Because of circular references between the SyncPointOrderData and
40 // SyncPointClientState, we must remove the references on destroy. Releasing
41 // the fence syncs in the order fence queue would be redundant at this point
42 // because they are assumed to be released on the destruction of the
43 // SyncPointClient.
44 base::AutoLock auto_lock(lock_);
45 destroyed_ = true;
46 while (!order_fence_queue_.empty()) {
47 order_fence_queue_.pop();
48 }
49 }
50
51 uint32_t SyncPointOrderData::GenerateUnprocessedOrderNumber(
22 SyncPointManager* sync_point_manager) { 52 SyncPointManager* sync_point_manager) {
23 const uint32_t order_num = sync_point_manager->GenerateOrderNumber(); 53 const uint32_t order_num = sync_point_manager->GenerateOrderNumber();
24 base::subtle::Release_Store(&unprocessed_order_num_, order_num); 54 base::AutoLock auto_lock(lock_);
55 unprocessed_order_num_ = order_num;
25 return order_num; 56 return order_num;
26 } 57 }
27 58
28 SyncPointClientState::SyncPointClientState() 59 void SyncPointOrderData::BeginProcessingOrderNumber(uint32_t order_num) {
29 : processed_order_num_(0), 60 DCHECK(processing_thread_checker_.CalledOnValidThread());
30 unprocessed_order_num_(0), 61 DCHECK_GE(order_num, current_order_num_);
31 current_order_num_(0) { 62 current_order_num_ = order_num;
32 } 63
64 // Catch invalid waits which were waiting on fence syncs that do not exist.
65 // When we begin processing an order number, we should release any fence
66 // syncs which were enqueued but the order number never existed.
67 // Release without the lock to avoid possible deadlocks.
68 std::vector<OrderFence> ensure_releases;
69 {
70 base::AutoLock auto_lock(lock_);
71 while (!order_fence_queue_.empty()) {
72 const OrderFence& order_fence = order_fence_queue_.top();
73 if (order_fence_queue_.top().order_num < order_num) {
74 ensure_releases.push_back(order_fence);
75 order_fence_queue_.pop();
76 continue;
77 }
78 break;
79 }
80 }
81
82 for (OrderFence& order_fence : ensure_releases) {
83 order_fence.client_state->EnsureReleased(order_fence.fence_release);
84 }
85 }
86
87 void SyncPointOrderData::FinishProcessingOrderNumber(uint32_t order_num) {
88 DCHECK(processing_thread_checker_.CalledOnValidThread());
89 DCHECK_EQ(current_order_num_, order_num);
90
91 // Catch invalid waits which were waiting on fence syncs that do not exist.
92 // When we end processing an order number, we should release any fence syncs
93 // which were suppose to be released during this order number.
94 // Release without the lock to avoid possible deadlocks.
95 std::vector<OrderFence> ensure_releases;
96 {
97 base::AutoLock auto_lock(lock_);
98 DCHECK_GT(order_num, processed_order_num_);
99 processed_order_num_ = order_num;
100
101 while (!order_fence_queue_.empty()) {
102 const OrderFence& order_fence = order_fence_queue_.top();
103 if (order_fence_queue_.top().order_num <= order_num) {
104 ensure_releases.push_back(order_fence);
105 order_fence_queue_.pop();
106 continue;
107 }
108 break;
109 }
110 }
111
112 for (OrderFence& order_fence : ensure_releases) {
113 order_fence.client_state->EnsureReleased(order_fence.fence_release);
114 }
115 }
116
117 SyncPointOrderData::OrderFence::OrderFence(
118 uint32_t order,
119 uint64_t release,
120 scoped_refptr<SyncPointClientState> state)
121 : order_num(order), fence_release(release), client_state(state) {}
122
123 SyncPointOrderData::OrderFence::~OrderFence() {}
124
125 SyncPointOrderData::SyncPointOrderData()
126 : current_order_num_(0),
127 destroyed_(false),
128 processed_order_num_(0),
129 unprocessed_order_num_(0) {}
130
131 SyncPointOrderData::~SyncPointOrderData() {}
132
133 bool SyncPointOrderData::ValidateReleaseOrderNumber(
134 scoped_refptr<SyncPointClientState> client_state,
135 uint32_t wait_order_num,
136 uint64_t fence_release) {
137 base::AutoLock auto_lock(lock_);
138 if (destroyed_)
139 return false;
140
141 // Release should have a possible unprocessed order number lower
142 // than the wait order number.
143 if ((processed_order_num_ + 1) >= wait_order_num)
144 return false;
145
146 // Release should have more unprocessed numbers if we are waiting.
147 if (unprocessed_order_num_ <= processed_order_num_)
148 return false;
149
150 // So far it could be valid, but add an order fence guard to be sure it
151 // gets released eventually.
152 const uint32_t expected_order_num =
153 std::min(unprocessed_order_num_, wait_order_num);
154 order_fence_queue_.push(
155 OrderFence(expected_order_num, fence_release, client_state));
156 return true;
157 }
158
159 SyncPointClientState::ReleaseCallback::ReleaseCallback(
160 uint64_t release,
161 const base::Closure& callback)
162 : release_count(release), callback_closure(callback) {}
163
164 SyncPointClientState::ReleaseCallback::~ReleaseCallback() {}
165
166 SyncPointClientState::SyncPointClientState(
167 scoped_refptr<SyncPointOrderData> order_data)
168 : order_data_(order_data), fence_sync_release_(0) {}
33 169
34 SyncPointClientState::~SyncPointClientState() { 170 SyncPointClientState::~SyncPointClientState() {
35 } 171 }
36 172
173 bool SyncPointClientState::WaitForRelease(uint32_t wait_order_num,
174 uint64_t release,
175 const base::Closure& callback) {
176 // Lock must be held the whole time while we validate otherwise it could be
177 // released while we are checking.
178 {
179 base::AutoLock auto_lock(fence_sync_lock_);
180 if (release > fence_sync_release_) {
181 if (!order_data_->ValidateReleaseOrderNumber(this, wait_order_num,
182 release)) {
183 return false;
184 } else {
185 // Add the callback which will be called upon release.
186 release_callback_queue_.push(ReleaseCallback(release, callback));
187 return true;
188 }
189 }
190 }
191
192 // Already released, run the callback now.
193 callback.Run();
194 return true;
195 }
196
197 void SyncPointClientState::ReleaseFenceSync(uint64_t release) {
198 // Call callbacks without the lock to avoid possible deadlocks.
199 std::vector<base::Closure> callback_list;
200 {
201 base::AutoLock auto_lock(fence_sync_lock_);
202 ReleaseFenceSyncLocked(release, &callback_list);
203 }
204
205 for (const base::Closure& closure : callback_list) {
206 closure.Run();
207 }
208 }
209
210 void SyncPointClientState::EnsureReleased(uint64_t release) {
211 // Call callbacks without the lock to avoid possible deadlocks.
212 std::vector<base::Closure> callback_list;
213 {
214 base::AutoLock auto_lock(fence_sync_lock_);
215 if (release <= fence_sync_release_)
216 return;
217
218 ReleaseFenceSyncLocked(release, &callback_list);
219 }
220
221 for (const base::Closure& closure : callback_list) {
222 closure.Run();
223 }
224 }
225
226 void SyncPointClientState::ReleaseFenceSyncLocked(
227 uint64_t release,
228 std::vector<base::Closure>* callback_list) {
229 fence_sync_lock_.AssertAcquired();
230 DCHECK_GT(release, fence_sync_release_);
231
232 fence_sync_release_ = release;
233 while (!release_callback_queue_.empty() &&
234 release_callback_queue_.top().release_count <= release) {
235 callback_list->push_back(release_callback_queue_.top().callback_closure);
236 release_callback_queue_.pop();
237 }
238 }
239
37 SyncPointClient::~SyncPointClient() { 240 SyncPointClient::~SyncPointClient() {
241 // Release all fences on destruction.
242 ReleaseFenceSync(UINT64_MAX);
243
38 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_); 244 sync_point_manager_->DestroySyncPointClient(namespace_id_, client_id_);
39 } 245 }
40 246
247 bool SyncPointClient::Wait(SyncPointClientState* release_state,
248 uint64_t release_count,
249 const base::Closure& wait_complete_callback) {
250 const uint32_t wait_order_number =
251 client_state_->order_data()->current_order_num();
252
253 // If waiting on self or wait was invalid, call the callback and return false.
254 if (client_state_ == release_state ||
255 !release_state->WaitForRelease(wait_order_number, release_count,
256 wait_complete_callback)) {
257 wait_complete_callback.Run();
258 return false;
259 }
260 return true;
261 }
262
263 bool SyncPointClient::WaitNonThreadSafe(
264 SyncPointClientState* release_state,
265 uint64_t release_count,
266 scoped_refptr<base::SingleThreadTaskRunner> runner,
267 const base::Closure& wait_complete_callback) {
268 return Wait(release_state, release_count,
269 base::Bind(&RunOnThread, runner, wait_complete_callback));
270 }
271
272 void SyncPointClient::ReleaseFenceSync(uint64_t release) {
273 client_state_->ReleaseFenceSync(release);
274 }
275
41 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager, 276 SyncPointClient::SyncPointClient(SyncPointManager* sync_point_manager,
42 scoped_refptr<SyncPointClientState> state, 277 scoped_refptr<SyncPointOrderData> order_data,
43 CommandBufferNamespace namespace_id, 278 CommandBufferNamespace namespace_id,
44 uint64_t client_id) 279 uint64_t client_id)
45 : sync_point_manager_(sync_point_manager), 280 : sync_point_manager_(sync_point_manager),
46 client_state_(state), 281 client_state_(new SyncPointClientState(order_data)),
47 namespace_id_(namespace_id), 282 namespace_id_(namespace_id),
48 client_id_(client_id) { 283 client_id_(client_id) {}
49 }
50 284
51 SyncPointManager::SyncPointManager(bool allow_threaded_wait) 285 SyncPointManager::SyncPointManager(bool allow_threaded_wait)
52 : allow_threaded_wait_(allow_threaded_wait), 286 : allow_threaded_wait_(allow_threaded_wait),
53 // To reduce the risk that a sync point created in a previous GPU process 287 // To reduce the risk that a sync point created in a previous GPU process
54 // will be in flight in the next GPU process, randomize the starting sync 288 // will be in flight in the next GPU process, randomize the starting sync
55 // point number. http://crbug.com/373452 289 // point number. http://crbug.com/373452
56 next_sync_point_(base::RandInt(1, kMaxSyncBase)), 290 next_sync_point_(base::RandInt(1, kMaxSyncBase)),
57 retire_cond_var_(&lock_) { 291 retire_cond_var_(&lock_) {
58 global_order_num_.GetNext(); 292 global_order_num_.GetNext();
59 } 293 }
60 294
61 SyncPointManager::~SyncPointManager() { 295 SyncPointManager::~SyncPointManager() {
62 for (const ClientMap& client_map : client_maps_) { 296 for (const ClientMap& client_map : client_maps_) {
63 DCHECK(client_map.empty()); 297 DCHECK(client_map.empty());
64 } 298 }
65 } 299 }
66 300
67 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient( 301 scoped_ptr<SyncPointClient> SyncPointManager::CreateSyncPointClient(
68 scoped_refptr<SyncPointClientState> client_state, 302 scoped_refptr<SyncPointOrderData> order_data,
69 CommandBufferNamespace namespace_id, uint64_t client_id) { 303 CommandBufferNamespace namespace_id,
304 uint64_t client_id) {
70 DCHECK_GE(namespace_id, 0); 305 DCHECK_GE(namespace_id, 0);
71 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 306 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_));
72 base::AutoLock auto_lock(client_maps_lock_); 307 base::AutoLock auto_lock(client_maps_lock_);
73 308
74 ClientMap& client_map = client_maps_[namespace_id]; 309 ClientMap& client_map = client_maps_[namespace_id];
75 std::pair<ClientMap::iterator, bool> result = client_map.insert( 310 std::pair<ClientMap::iterator, bool> result = client_map.insert(
76 std::make_pair(client_id, new SyncPointClient(this, 311 std::make_pair(client_id, new SyncPointClient(this, order_data,
77 client_state, 312 namespace_id, client_id)));
78 namespace_id,
79 client_id)));
80 DCHECK(result.second); 313 DCHECK(result.second);
81 314
82 return make_scoped_ptr(result.first->second); 315 return make_scoped_ptr(result.first->second);
83 } 316 }
84 317
85 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( 318 scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState(
86 CommandBufferNamespace namespace_id, uint64_t client_id) { 319 CommandBufferNamespace namespace_id, uint64_t client_id) {
87 DCHECK_GE(namespace_id, 0); 320 DCHECK_GE(namespace_id, 0);
88 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 321 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_));
89 base::AutoLock auto_lock(client_maps_lock_); 322 base::AutoLock auto_lock(client_maps_lock_);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); 410 DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_));
178 411
179 base::AutoLock auto_lock(client_maps_lock_); 412 base::AutoLock auto_lock(client_maps_lock_);
180 ClientMap& client_map = client_maps_[namespace_id]; 413 ClientMap& client_map = client_maps_[namespace_id];
181 ClientMap::iterator it = client_map.find(client_id); 414 ClientMap::iterator it = client_map.find(client_id);
182 DCHECK(it != client_map.end()); 415 DCHECK(it != client_map.end());
183 client_map.erase(it); 416 client_map.erase(it);
184 } 417 }
185 418
186 } // namespace gpu 419 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/sync_point_manager.h ('k') | gpu/command_buffer/service/sync_point_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698