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

Side by Side Diff: base/waitable_event_posix.cc

Issue 173059: Ensure that SyncWaiter condition variables cannot be destroyed during a broadcast (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 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 | « no previous file | 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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "base/waitable_event.h" 5 #include "base/waitable_event.h"
6 6
7 #include "base/condition_variable.h" 7 #include "base/condition_variable.h"
8 #include "base/lock.h" 8 #include "base/lock.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 10
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 const bool result = kernel_->signaled_; 69 const bool result = kernel_->signaled_;
70 if (result && !kernel_->manual_reset_) 70 if (result && !kernel_->manual_reset_)
71 kernel_->signaled_ = false; 71 kernel_->signaled_ = false;
72 return result; 72 return result;
73 } 73 }
74 74
75 // ----------------------------------------------------------------------------- 75 // -----------------------------------------------------------------------------
76 // Synchronous waits 76 // Synchronous waits
77 77
78 // ----------------------------------------------------------------------------- 78 // -----------------------------------------------------------------------------
79 // This is an synchronous waiter. The thread is waiting on the given condition 79 // This is a synchronous waiter. The thread is waiting on the given condition
80 // variable and the fired flag in this object. 80 // variable and the fired flag in this object.
81 // ----------------------------------------------------------------------------- 81 // -----------------------------------------------------------------------------
82 class SyncWaiter : public WaitableEvent::Waiter { 82 class SyncWaiter : public WaitableEvent::Waiter {
83 public: 83 public:
84 SyncWaiter(ConditionVariable* cv, Lock* lock) 84 SyncWaiter()
85 : fired_(false), 85 : fired_(false),
86 cv_(cv), 86 signaling_event_(NULL),
87 lock_(lock), 87 lock_(),
agl 2009/08/19 17:35:35 Isn't this line a no-op?
88 signaling_event_(NULL) { 88 cv_(&lock_) {
89 } 89 }
90 90
91 bool Fire(WaitableEvent *signaling_event) { 91 bool Fire(WaitableEvent* signaling_event) {
92 lock_->Acquire(); 92 AutoLock locked(lock_);
93 const bool previous_value = fired_;
94 fired_ = true;
95 if (!previous_value)
96 signaling_event_ = signaling_event;
97 lock_->Release();
98 93
99 if (previous_value) 94 if (fired_)
100 return false; 95 return false;
101 96
102 cv_->Broadcast(); 97 fired_ = true;
98 signaling_event_ = signaling_event;
103 99
104 // SyncWaiters are stack allocated on the stack of the blocking thread. 100 cv_.Broadcast();
101
102 // Unlike AsyncWaiter objects, SyncWaiter objects are stack-allocated on
103 // the blocking thread's stack. There is no |delete this;| in Fire. The
104 // SyncWaiter object is destroyed when it goes out of scope.
105
105 return true; 106 return true;
106 } 107 }
107 108
108 WaitableEvent* signaled_event() const { 109 WaitableEvent* signaling_event() const {
109 return signaling_event_; 110 return signaling_event_;
110 } 111 }
111 112
112 // --------------------------------------------------------------------------- 113 // ---------------------------------------------------------------------------
113 // These waiters are always stack allocated and don't delete themselves. Thus 114 // These waiters are always stack allocated and don't delete themselves. Thus
114 // there's no problem and the ABA tag is the same as the object pointer. 115 // there's no problem and the ABA tag is the same as the object pointer.
115 // --------------------------------------------------------------------------- 116 // ---------------------------------------------------------------------------
116 bool Compare(void* tag) { 117 bool Compare(void* tag) {
117 return this == tag; 118 return this == tag;
118 } 119 }
119 120
120 // --------------------------------------------------------------------------- 121 // ---------------------------------------------------------------------------
121 // Called with lock held. 122 // Called with lock held.
122 // --------------------------------------------------------------------------- 123 // ---------------------------------------------------------------------------
123 bool fired() const { 124 bool fired() const {
124 return fired_; 125 return fired_;
125 } 126 }
126 127
127 // --------------------------------------------------------------------------- 128 // ---------------------------------------------------------------------------
128 // During a TimedWait, we need a way to make sure that an auto-reset 129 // During a TimedWait, we need a way to make sure that an auto-reset
129 // WaitableEvent doesn't think that this event has been signaled between 130 // WaitableEvent doesn't think that this event has been signaled between
130 // unlocking it and removing it from the wait-list. Called with lock held. 131 // unlocking it and removing it from the wait-list. Called with lock held.
131 // --------------------------------------------------------------------------- 132 // ---------------------------------------------------------------------------
132 void Disable() { 133 void Disable() {
133 fired_ = true; 134 fired_ = true;
134 } 135 }
135 136
137 Lock* lock() {
138 return &lock_;
139 }
140
141 ConditionVariable* cv() {
142 return &cv_;
143 }
144
136 private: 145 private:
137 bool fired_; 146 bool fired_;
138 ConditionVariable *const cv_;
139 Lock *const lock_;
140 WaitableEvent* signaling_event_; // The WaitableEvent which woke us 147 WaitableEvent* signaling_event_; // The WaitableEvent which woke us
148 Lock lock_;
149 ConditionVariable cv_;
141 }; 150 };
142 151
143 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { 152 bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
144 const Time end_time(Time::Now() + max_time); 153 const Time end_time(Time::Now() + max_time);
145 const bool finite_time = max_time.ToInternalValue() >= 0; 154 const bool finite_time = max_time.ToInternalValue() >= 0;
146 155
147 kernel_->lock_.Acquire(); 156 kernel_->lock_.Acquire();
148 if (kernel_->signaled_) { 157 if (kernel_->signaled_) {
149 if (!kernel_->manual_reset_) { 158 if (!kernel_->manual_reset_) {
150 // In this case we were signaled when we had no waiters. Now that 159 // In this case we were signaled when we had no waiters. Now that
151 // someone has waited upon us, we can automatically reset. 160 // someone has waited upon us, we can automatically reset.
152 kernel_->signaled_ = false; 161 kernel_->signaled_ = false;
153 } 162 }
154 163
155 kernel_->lock_.Release(); 164 kernel_->lock_.Release();
156 return true; 165 return true;
157 } 166 }
158 167
159 Lock lock; 168 SyncWaiter sw;
160 lock.Acquire(); 169 sw.lock()->Acquire();
161 ConditionVariable cv(&lock);
162 SyncWaiter sw(&cv, &lock);
163 170
164 Enqueue(&sw); 171 Enqueue(&sw);
165 kernel_->lock_.Release(); 172 kernel_->lock_.Release();
166 // We are violating locking order here by holding the SyncWaiter lock but not 173 // We are violating locking order here by holding the SyncWaiter lock but not
167 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ 174 // the WaitableEvent lock. However, this is safe because we don't lock @lock_
168 // again before unlocking it. 175 // again before unlocking it.
169 176
170 for (;;) { 177 for (;;) {
171 const Time current_time(Time::Now()); 178 const Time current_time(Time::Now());
172 179
173 if (sw.fired() || (finite_time && current_time >= end_time)) { 180 if (sw.fired() || (finite_time && current_time >= end_time)) {
174 const bool return_value = sw.fired(); 181 const bool return_value = sw.fired();
175 182
176 // We can't acquire @lock_ before releasing @lock (because of locking 183 // We can't acquire @lock_ before releasing the SyncWaiter lock (because
177 // order), however, inbetween the two a signal could be fired and @sw 184 // of locking order), however, in between the two a signal could be fired
178 // would accept it, however we will still return false, so the signal 185 // and @sw would accept it, however we will still return false, so the
179 // would be lost on an auto-reset WaitableEvent. Thus we call Disable 186 // signal would be lost on an auto-reset WaitableEvent. Thus we call
180 // which makes sw::Fire return false. 187 // Disable which makes sw::Fire return false.
181 sw.Disable(); 188 sw.Disable();
182 lock.Release(); 189 sw.lock()->Release();
183 190
184 kernel_->lock_.Acquire(); 191 kernel_->lock_.Acquire();
185 kernel_->Dequeue(&sw, &sw); 192 kernel_->Dequeue(&sw, &sw);
186 kernel_->lock_.Release(); 193 kernel_->lock_.Release();
187 194
188 return return_value; 195 return return_value;
189 } 196 }
190 197
191 if (finite_time) { 198 if (finite_time) {
192 const TimeDelta max_wait(end_time - current_time); 199 const TimeDelta max_wait(end_time - current_time);
193 cv.TimedWait(max_wait); 200 sw.cv()->TimedWait(max_wait);
194 } else { 201 } else {
195 cv.Wait(); 202 sw.cv()->Wait();
196 } 203 }
197 } 204 }
198 } 205 }
199 206
200 bool WaitableEvent::Wait() { 207 bool WaitableEvent::Wait() {
201 return TimedWait(TimeDelta::FromSeconds(-1)); 208 return TimedWait(TimeDelta::FromSeconds(-1));
202 } 209 }
203 210
204 // ----------------------------------------------------------------------------- 211 // -----------------------------------------------------------------------------
205 212
(...skipping 24 matching lines...) Expand all
230 237
231 sort(waitables.begin(), waitables.end(), cmp_fst_addr); 238 sort(waitables.begin(), waitables.end(), cmp_fst_addr);
232 239
233 // The set of waitables must be distinct. Since we have just sorted by 240 // The set of waitables must be distinct. Since we have just sorted by
234 // address, we can check this cheaply by comparing pairs of consecutive 241 // address, we can check this cheaply by comparing pairs of consecutive
235 // elements. 242 // elements.
236 for (size_t i = 0; i < waitables.size() - 1; ++i) { 243 for (size_t i = 0; i < waitables.size() - 1; ++i) {
237 DCHECK(waitables[i].first != waitables[i+1].first); 244 DCHECK(waitables[i].first != waitables[i+1].first);
238 } 245 }
239 246
240 Lock lock; 247 SyncWaiter sw;
241 ConditionVariable cv(&lock);
242 SyncWaiter sw(&cv, &lock);
243 248
244 const size_t r = EnqueueMany(&waitables[0], count, &sw); 249 const size_t r = EnqueueMany(&waitables[0], count, &sw);
245 if (r) { 250 if (r) {
246 // One of the events is already signaled. The SyncWaiter has not been 251 // One of the events is already signaled. The SyncWaiter has not been
247 // enqueued anywhere. EnqueueMany returns the count of remaining waitables 252 // enqueued anywhere. EnqueueMany returns the count of remaining waitables
248 // when the signaled one was seen, so the index of the signaled event is 253 // when the signaled one was seen, so the index of the signaled event is
249 // @count - @r. 254 // @count - @r.
250 return waitables[count - r].second; 255 return waitables[count - r].second;
251 } 256 }
252 257
253 // At this point, we hold the locks on all the WaitableEvents and we have 258 // At this point, we hold the locks on all the WaitableEvents and we have
254 // enqueued our waiter in them all. 259 // enqueued our waiter in them all.
255 lock.Acquire(); 260 sw.lock()->Acquire();
256 // Release the WaitableEvent locks in the reverse order 261 // Release the WaitableEvent locks in the reverse order
257 for (size_t i = 0; i < count; ++i) { 262 for (size_t i = 0; i < count; ++i) {
258 waitables[count - (1 + i)].first->kernel_->lock_.Release(); 263 waitables[count - (1 + i)].first->kernel_->lock_.Release();
259 } 264 }
260 265
261 for (;;) { 266 for (;;) {
262 if (sw.fired()) 267 if (sw.fired())
263 break; 268 break;
264 269
265 cv.Wait(); 270 sw.cv()->Wait();
266 } 271 }
267 lock.Release(); 272 sw.lock()->Release();
268 273
269 // The address of the WaitableEvent which fired is stored in the SyncWaiter. 274 // The address of the WaitableEvent which fired is stored in the SyncWaiter.
270 WaitableEvent *const signaled_event = sw.signaled_event(); 275 WaitableEvent *const signaled_event = sw.signaling_event();
271 // This will store the index of the raw_waitables which fired. 276 // This will store the index of the raw_waitables which fired.
272 size_t signaled_index = 0; 277 size_t signaled_index = 0;
273 278
274 // Take the locks of each WaitableEvent in turn (except the signaled one) and 279 // Take the locks of each WaitableEvent in turn (except the signaled one) and
275 // remove our SyncWaiter from the wait-list 280 // remove our SyncWaiter from the wait-list
276 for (size_t i = 0; i < count; ++i) { 281 for (size_t i = 0; i < count; ++i) {
277 if (raw_waitables[i] != signaled_event) { 282 if (raw_waitables[i] != signaled_event) {
278 raw_waitables[i]->kernel_->lock_.Acquire(); 283 raw_waitables[i]->kernel_->lock_.Acquire();
279 // There's no possible ABA issue with the address of the SyncWaiter here 284 // There's no possible ABA issue with the address of the SyncWaiter here
280 // because it lives on the stack. Thus the tag value is just the pointer 285 // because it lives on the stack. Thus the tag value is just the pointer
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 return true; 386 return true;
382 } 387 }
383 } 388 }
384 389
385 return false; 390 return false;
386 } 391 }
387 392
388 // ----------------------------------------------------------------------------- 393 // -----------------------------------------------------------------------------
389 394
390 } // namespace base 395 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698