| 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 |