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

Side by Side Diff: base/synchronization/waitable_event_posix.cc

Issue 419773002: Take extra lock in base::WaitableEvent::WaitMany. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « base/synchronization/waitable_event.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm> 5 #include <algorithm>
6 #include <vector> 6 #include <vector>
7 7
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/synchronization/waitable_event.h" 9 #include "base/synchronization/waitable_event.h"
10 #include "base/synchronization/condition_variable.h" 10 #include "base/synchronization/condition_variable.h"
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 const bool return_value = sw.fired(); 190 const bool return_value = sw.fired();
191 191
192 // We can't acquire @lock_ before releasing the SyncWaiter lock (because 192 // We can't acquire @lock_ before releasing the SyncWaiter lock (because
193 // of locking order), however, in between the two a signal could be fired 193 // of locking order), however, in between the two a signal could be fired
194 // and @sw would accept it, however we will still return false, so the 194 // and @sw would accept it, however we will still return false, so the
195 // signal would be lost on an auto-reset WaitableEvent. Thus we call 195 // signal would be lost on an auto-reset WaitableEvent. Thus we call
196 // Disable which makes sw::Fire return false. 196 // Disable which makes sw::Fire return false.
197 sw.Disable(); 197 sw.Disable();
198 sw.lock()->Release(); 198 sw.lock()->Release();
199 199
200 // This is a bug that has been enshrined in the interface of
201 // WaitableEvent now: |Dequeue| is called even when |sw.fired()| is true,
202 // even though it'll always return false in that case. However, taking
203 // the lock ensures that |Signal| has completed before we return and
204 // means that a WaitableEvent can synchronise its own destruction.
200 kernel_->lock_.Acquire(); 205 kernel_->lock_.Acquire();
201 kernel_->Dequeue(&sw, &sw); 206 kernel_->Dequeue(&sw, &sw);
202 kernel_->lock_.Release(); 207 kernel_->lock_.Release();
203 208
204 return return_value; 209 return return_value;
205 } 210 }
206 211
207 if (finite_time) { 212 if (finite_time) {
208 const TimeDelta max_wait(end_time - current_time); 213 const TimeDelta max_wait(end_time - current_time);
209 sw.cv()->TimedWait(max_wait); 214 sw.cv()->TimedWait(max_wait);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 // remove our SyncWaiter from the wait-list 288 // remove our SyncWaiter from the wait-list
284 for (size_t i = 0; i < count; ++i) { 289 for (size_t i = 0; i < count; ++i) {
285 if (raw_waitables[i] != signaled_event) { 290 if (raw_waitables[i] != signaled_event) {
286 raw_waitables[i]->kernel_->lock_.Acquire(); 291 raw_waitables[i]->kernel_->lock_.Acquire();
287 // There's no possible ABA issue with the address of the SyncWaiter here 292 // There's no possible ABA issue with the address of the SyncWaiter here
288 // because it lives on the stack. Thus the tag value is just the pointer 293 // because it lives on the stack. Thus the tag value is just the pointer
289 // value again. 294 // value again.
290 raw_waitables[i]->kernel_->Dequeue(&sw, &sw); 295 raw_waitables[i]->kernel_->Dequeue(&sw, &sw);
291 raw_waitables[i]->kernel_->lock_.Release(); 296 raw_waitables[i]->kernel_->lock_.Release();
292 } else { 297 } else {
298 // By taking this lock here we ensure that |Signal| has completed by the
willchan no longer on Chromium 2014/08/05 17:26:27 Non-obvious on a first read that Signal() is holdi
yhirano 2014/08/06 11:49:49 Done.
299 // time we return. This matches the behaviour of |Wait| and |TimedWait|.
300 raw_waitables[i]->kernel_->lock_.Acquire();
301 raw_waitables[i]->kernel_->lock_.Release();
293 signaled_index = i; 302 signaled_index = i;
294 } 303 }
295 } 304 }
296 305
297 return signaled_index; 306 return signaled_index;
298 } 307 }
299 308
300 // ----------------------------------------------------------------------------- 309 // -----------------------------------------------------------------------------
301 // If return value == 0: 310 // If return value == 0:
302 // The locks of the WaitableEvents have been taken in order and the Waiter has 311 // The locks of the WaitableEvents have been taken in order and the Waiter has
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 return true; 407 return true;
399 } 408 }
400 } 409 }
401 410
402 return false; 411 return false;
403 } 412 }
404 413
405 // ----------------------------------------------------------------------------- 414 // -----------------------------------------------------------------------------
406 415
407 } // namespace base 416 } // namespace base
OLDNEW
« no previous file with comments | « base/synchronization/waitable_event.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698