OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "mojo/system/data_pipe.h" | 5 #include "mojo/system/data_pipe.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <limits> | 10 #include <limits> |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 if (!consumer_open_no_lock()) | 104 if (!consumer_open_no_lock()) |
105 return MOJO_RESULT_FAILED_PRECONDITION; | 105 return MOJO_RESULT_FAILED_PRECONDITION; |
106 | 106 |
107 // Returning "busy" takes priority over "invalid argument". | 107 // Returning "busy" takes priority over "invalid argument". |
108 if (*num_bytes % element_num_bytes_ != 0) | 108 if (*num_bytes % element_num_bytes_ != 0) |
109 return MOJO_RESULT_INVALID_ARGUMENT; | 109 return MOJO_RESULT_INVALID_ARGUMENT; |
110 | 110 |
111 if (*num_bytes == 0) | 111 if (*num_bytes == 0) |
112 return MOJO_RESULT_OK; // Nothing to do. | 112 return MOJO_RESULT_OK; // Nothing to do. |
113 | 113 |
114 MojoWaitFlags old_consumer_satisfied_flags = ConsumerSatisfiedFlagsNoLock(); | 114 WaitFlagsState old_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
115 MojoResult rv = ProducerWriteDataImplNoLock(elements, num_bytes, all_or_none); | 115 MojoResult rv = ProducerWriteDataImplNoLock(elements, num_bytes, all_or_none); |
116 if (ConsumerSatisfiedFlagsNoLock() != old_consumer_satisfied_flags) | 116 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
| 117 if (!new_consumer_state.equals(old_consumer_state)) |
117 AwakeConsumerWaitersForStateChangeNoLock(); | 118 AwakeConsumerWaitersForStateChangeNoLock(); |
118 return rv; | 119 return rv; |
119 } | 120 } |
120 | 121 |
121 MojoResult DataPipe::ProducerBeginWriteData(void** buffer, | 122 MojoResult DataPipe::ProducerBeginWriteData(void** buffer, |
122 uint32_t* buffer_num_bytes, | 123 uint32_t* buffer_num_bytes, |
123 bool all_or_none) { | 124 bool all_or_none) { |
124 base::AutoLock locker(lock_); | 125 base::AutoLock locker(lock_); |
125 DCHECK(has_local_producer_no_lock()); | 126 DCHECK(has_local_producer_no_lock()); |
126 | 127 |
(...skipping 19 matching lines...) Expand all Loading... |
146 | 147 |
147 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { | 148 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { |
148 base::AutoLock locker(lock_); | 149 base::AutoLock locker(lock_); |
149 DCHECK(has_local_producer_no_lock()); | 150 DCHECK(has_local_producer_no_lock()); |
150 | 151 |
151 if (!producer_in_two_phase_write_no_lock()) | 152 if (!producer_in_two_phase_write_no_lock()) |
152 return MOJO_RESULT_FAILED_PRECONDITION; | 153 return MOJO_RESULT_FAILED_PRECONDITION; |
153 // Note: Allow successful completion of the two-phase write even if the | 154 // Note: Allow successful completion of the two-phase write even if the |
154 // consumer has been closed. | 155 // consumer has been closed. |
155 | 156 |
156 MojoWaitFlags old_consumer_satisfied_flags = ConsumerSatisfiedFlagsNoLock(); | 157 WaitFlagsState old_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
157 MojoResult rv; | 158 MojoResult rv; |
158 if (num_bytes_written > producer_two_phase_max_num_bytes_written_ || | 159 if (num_bytes_written > producer_two_phase_max_num_bytes_written_ || |
159 num_bytes_written % element_num_bytes_ != 0) { | 160 num_bytes_written % element_num_bytes_ != 0) { |
160 rv = MOJO_RESULT_INVALID_ARGUMENT; | 161 rv = MOJO_RESULT_INVALID_ARGUMENT; |
161 producer_two_phase_max_num_bytes_written_ = 0; | 162 producer_two_phase_max_num_bytes_written_ = 0; |
162 } else { | 163 } else { |
163 rv = ProducerEndWriteDataImplNoLock(num_bytes_written); | 164 rv = ProducerEndWriteDataImplNoLock(num_bytes_written); |
164 } | 165 } |
165 // Two-phase write ended even on failure. | 166 // Two-phase write ended even on failure. |
166 DCHECK(!producer_in_two_phase_write_no_lock()); | 167 DCHECK(!producer_in_two_phase_write_no_lock()); |
167 // If we're now writable, we *became* writable (since we weren't writable | 168 // If we're now writable, we *became* writable (since we weren't writable |
168 // during the two-phase write), so awake producer waiters. | 169 // during the two-phase write), so awake producer waiters. |
169 if ((ProducerSatisfiedFlagsNoLock() & MOJO_WAIT_FLAG_WRITABLE)) | 170 if (ProducerGetWaitFlagsStateNoLock().satisfies(MOJO_WAIT_FLAG_WRITABLE)) |
170 AwakeProducerWaitersForStateChangeNoLock(); | 171 AwakeProducerWaitersForStateChangeNoLock(); |
171 if (ConsumerSatisfiedFlagsNoLock() != old_consumer_satisfied_flags) | 172 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
| 173 if (!new_consumer_state.equals(old_consumer_state)) |
172 AwakeConsumerWaitersForStateChangeNoLock(); | 174 AwakeConsumerWaitersForStateChangeNoLock(); |
173 return rv; | 175 return rv; |
174 } | 176 } |
175 | 177 |
176 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, | 178 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, |
177 MojoWaitFlags flags, | 179 MojoWaitFlags flags, |
178 MojoResult wake_result) { | 180 MojoResult wake_result) { |
179 base::AutoLock locker(lock_); | 181 base::AutoLock locker(lock_); |
180 DCHECK(has_local_producer_no_lock()); | 182 DCHECK(has_local_producer_no_lock()); |
181 | 183 |
182 if ((flags & ProducerSatisfiedFlagsNoLock())) | 184 WaitFlagsState producer_state = ProducerGetWaitFlagsStateNoLock(); |
| 185 if (producer_state.satisfies(flags)) |
183 return MOJO_RESULT_ALREADY_EXISTS; | 186 return MOJO_RESULT_ALREADY_EXISTS; |
184 if (!(flags & ProducerSatisfiableFlagsNoLock())) | 187 if (!producer_state.can_satisfy(flags)) |
185 return MOJO_RESULT_FAILED_PRECONDITION; | 188 return MOJO_RESULT_FAILED_PRECONDITION; |
186 | 189 |
187 producer_waiter_list_->AddWaiter(waiter, flags, wake_result); | 190 producer_waiter_list_->AddWaiter(waiter, flags, wake_result); |
188 return MOJO_RESULT_OK; | 191 return MOJO_RESULT_OK; |
189 } | 192 } |
190 | 193 |
191 void DataPipe::ProducerRemoveWaiter(Waiter* waiter) { | 194 void DataPipe::ProducerRemoveWaiter(Waiter* waiter) { |
192 base::AutoLock locker(lock_); | 195 base::AutoLock locker(lock_); |
193 DCHECK(has_local_producer_no_lock()); | 196 DCHECK(has_local_producer_no_lock()); |
194 producer_waiter_list_->RemoveWaiter(waiter); | 197 producer_waiter_list_->RemoveWaiter(waiter); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 | 230 |
228 if (consumer_in_two_phase_read_no_lock()) | 231 if (consumer_in_two_phase_read_no_lock()) |
229 return MOJO_RESULT_BUSY; | 232 return MOJO_RESULT_BUSY; |
230 | 233 |
231 if (*num_bytes % element_num_bytes_ != 0) | 234 if (*num_bytes % element_num_bytes_ != 0) |
232 return MOJO_RESULT_INVALID_ARGUMENT; | 235 return MOJO_RESULT_INVALID_ARGUMENT; |
233 | 236 |
234 if (*num_bytes == 0) | 237 if (*num_bytes == 0) |
235 return MOJO_RESULT_OK; // Nothing to do. | 238 return MOJO_RESULT_OK; // Nothing to do. |
236 | 239 |
237 MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock(); | 240 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); |
238 MojoResult rv = ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none); | 241 MojoResult rv = ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none); |
239 if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags) | 242 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
| 243 if (!new_producer_state.equals(old_producer_state)) |
240 AwakeProducerWaitersForStateChangeNoLock(); | 244 AwakeProducerWaitersForStateChangeNoLock(); |
241 return rv; | 245 return rv; |
242 } | 246 } |
243 | 247 |
244 MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes, | 248 MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes, |
245 bool all_or_none) { | 249 bool all_or_none) { |
246 base::AutoLock locker(lock_); | 250 base::AutoLock locker(lock_); |
247 DCHECK(has_local_consumer_no_lock()); | 251 DCHECK(has_local_consumer_no_lock()); |
248 | 252 |
249 if (consumer_in_two_phase_read_no_lock()) | 253 if (consumer_in_two_phase_read_no_lock()) |
250 return MOJO_RESULT_BUSY; | 254 return MOJO_RESULT_BUSY; |
251 | 255 |
252 if (*num_bytes % element_num_bytes_ != 0) | 256 if (*num_bytes % element_num_bytes_ != 0) |
253 return MOJO_RESULT_INVALID_ARGUMENT; | 257 return MOJO_RESULT_INVALID_ARGUMENT; |
254 | 258 |
255 if (*num_bytes == 0) | 259 if (*num_bytes == 0) |
256 return MOJO_RESULT_OK; // Nothing to do. | 260 return MOJO_RESULT_OK; // Nothing to do. |
257 | 261 |
258 MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock(); | 262 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); |
259 MojoResult rv = ConsumerDiscardDataImplNoLock(num_bytes, all_or_none); | 263 MojoResult rv = ConsumerDiscardDataImplNoLock(num_bytes, all_or_none); |
260 if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags) | 264 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
| 265 if (!new_producer_state.equals(old_producer_state)) |
261 AwakeProducerWaitersForStateChangeNoLock(); | 266 AwakeProducerWaitersForStateChangeNoLock(); |
262 return rv; | 267 return rv; |
263 } | 268 } |
264 | 269 |
265 MojoResult DataPipe::ConsumerQueryData(uint32_t* num_bytes) { | 270 MojoResult DataPipe::ConsumerQueryData(uint32_t* num_bytes) { |
266 base::AutoLock locker(lock_); | 271 base::AutoLock locker(lock_); |
267 DCHECK(has_local_consumer_no_lock()); | 272 DCHECK(has_local_consumer_no_lock()); |
268 | 273 |
269 if (consumer_in_two_phase_read_no_lock()) | 274 if (consumer_in_two_phase_read_no_lock()) |
270 return MOJO_RESULT_BUSY; | 275 return MOJO_RESULT_BUSY; |
(...skipping 22 matching lines...) Expand all Loading... |
293 return MOJO_RESULT_OK; | 298 return MOJO_RESULT_OK; |
294 } | 299 } |
295 | 300 |
296 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { | 301 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { |
297 base::AutoLock locker(lock_); | 302 base::AutoLock locker(lock_); |
298 DCHECK(has_local_consumer_no_lock()); | 303 DCHECK(has_local_consumer_no_lock()); |
299 | 304 |
300 if (!consumer_in_two_phase_read_no_lock()) | 305 if (!consumer_in_two_phase_read_no_lock()) |
301 return MOJO_RESULT_FAILED_PRECONDITION; | 306 return MOJO_RESULT_FAILED_PRECONDITION; |
302 | 307 |
303 MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock(); | 308 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); |
304 MojoResult rv; | 309 MojoResult rv; |
305 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ || | 310 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ || |
306 num_bytes_read % element_num_bytes_ != 0) { | 311 num_bytes_read % element_num_bytes_ != 0) { |
307 rv = MOJO_RESULT_INVALID_ARGUMENT; | 312 rv = MOJO_RESULT_INVALID_ARGUMENT; |
308 consumer_two_phase_max_num_bytes_read_ = 0; | 313 consumer_two_phase_max_num_bytes_read_ = 0; |
309 } else { | 314 } else { |
310 rv = ConsumerEndReadDataImplNoLock(num_bytes_read); | 315 rv = ConsumerEndReadDataImplNoLock(num_bytes_read); |
311 } | 316 } |
312 // Two-phase read ended even on failure. | 317 // Two-phase read ended even on failure. |
313 DCHECK(!consumer_in_two_phase_read_no_lock()); | 318 DCHECK(!consumer_in_two_phase_read_no_lock()); |
314 // If we're now readable, we *became* readable (since we weren't readable | 319 // If we're now readable, we *became* readable (since we weren't readable |
315 // during the two-phase read), so awake consumer waiters. | 320 // during the two-phase read), so awake consumer waiters. |
316 if ((ConsumerSatisfiedFlagsNoLock() & MOJO_WAIT_FLAG_READABLE)) | 321 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
| 322 if (new_consumer_state.satisfies(MOJO_WAIT_FLAG_READABLE)) |
317 AwakeConsumerWaitersForStateChangeNoLock(); | 323 AwakeConsumerWaitersForStateChangeNoLock(); |
318 if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags) | 324 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
| 325 if (!new_producer_state.equals(old_producer_state)) |
319 AwakeProducerWaitersForStateChangeNoLock(); | 326 AwakeProducerWaitersForStateChangeNoLock(); |
320 return rv; | 327 return rv; |
321 } | 328 } |
322 | 329 |
323 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, | 330 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, |
324 MojoWaitFlags flags, | 331 MojoWaitFlags flags, |
325 MojoResult wake_result) { | 332 MojoResult wake_result) { |
326 base::AutoLock locker(lock_); | 333 base::AutoLock locker(lock_); |
327 DCHECK(has_local_consumer_no_lock()); | 334 DCHECK(has_local_consumer_no_lock()); |
328 | 335 |
329 if ((flags & ConsumerSatisfiedFlagsNoLock())) | 336 WaitFlagsState consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
| 337 if (consumer_state.satisfies(flags)) |
330 return MOJO_RESULT_ALREADY_EXISTS; | 338 return MOJO_RESULT_ALREADY_EXISTS; |
331 if (!(flags & ConsumerSatisfiableFlagsNoLock())) | 339 if (!consumer_state.can_satisfy(flags)) |
332 return MOJO_RESULT_FAILED_PRECONDITION; | 340 return MOJO_RESULT_FAILED_PRECONDITION; |
333 | 341 |
334 consumer_waiter_list_->AddWaiter(waiter, flags, wake_result); | 342 consumer_waiter_list_->AddWaiter(waiter, flags, wake_result); |
335 return MOJO_RESULT_OK; | 343 return MOJO_RESULT_OK; |
336 } | 344 } |
337 | 345 |
338 void DataPipe::ConsumerRemoveWaiter(Waiter* waiter) { | 346 void DataPipe::ConsumerRemoveWaiter(Waiter* waiter) { |
339 base::AutoLock locker(lock_); | 347 base::AutoLock locker(lock_); |
340 DCHECK(has_local_consumer_no_lock()); | 348 DCHECK(has_local_consumer_no_lock()); |
341 consumer_waiter_list_->RemoveWaiter(waiter); | 349 consumer_waiter_list_->RemoveWaiter(waiter); |
(...skipping 28 matching lines...) Expand all Loading... |
370 DCHECK(!consumer_open_); | 378 DCHECK(!consumer_open_); |
371 DCHECK(!producer_waiter_list_); | 379 DCHECK(!producer_waiter_list_); |
372 DCHECK(!consumer_waiter_list_); | 380 DCHECK(!consumer_waiter_list_); |
373 } | 381 } |
374 | 382 |
375 void DataPipe::AwakeProducerWaitersForStateChangeNoLock() { | 383 void DataPipe::AwakeProducerWaitersForStateChangeNoLock() { |
376 lock_.AssertAcquired(); | 384 lock_.AssertAcquired(); |
377 if (!has_local_producer_no_lock()) | 385 if (!has_local_producer_no_lock()) |
378 return; | 386 return; |
379 producer_waiter_list_->AwakeWaitersForStateChange( | 387 producer_waiter_list_->AwakeWaitersForStateChange( |
380 ProducerSatisfiedFlagsNoLock(), ProducerSatisfiableFlagsNoLock()); | 388 ProducerGetWaitFlagsStateNoLock()); |
381 } | 389 } |
382 | 390 |
383 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() { | 391 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() { |
384 lock_.AssertAcquired(); | 392 lock_.AssertAcquired(); |
385 if (!has_local_consumer_no_lock()) | 393 if (!has_local_consumer_no_lock()) |
386 return; | 394 return; |
387 consumer_waiter_list_->AwakeWaitersForStateChange( | 395 consumer_waiter_list_->AwakeWaitersForStateChange( |
388 ConsumerSatisfiedFlagsNoLock(), ConsumerSatisfiableFlagsNoLock()); | 396 ConsumerGetWaitFlagsStateNoLock()); |
389 } | 397 } |
390 | 398 |
391 } // namespace system | 399 } // namespace system |
392 } // namespace mojo | 400 } // namespace mojo |
OLD | NEW |