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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 base::AutoLock locker(lock_); | 83 base::AutoLock locker(lock_); |
84 DCHECK(producer_open_); | 84 DCHECK(producer_open_); |
85 producer_open_ = false; | 85 producer_open_ = false; |
86 DCHECK(has_local_producer_no_lock()); | 86 DCHECK(has_local_producer_no_lock()); |
87 producer_waiter_list_.reset(); | 87 producer_waiter_list_.reset(); |
88 // Not a bug, except possibly in "user" code. | 88 // Not a bug, except possibly in "user" code. |
89 DVLOG_IF(2, producer_in_two_phase_write_no_lock()) | 89 DVLOG_IF(2, producer_in_two_phase_write_no_lock()) |
90 << "Producer closed with active two-phase write"; | 90 << "Producer closed with active two-phase write"; |
91 producer_two_phase_max_num_bytes_written_ = 0; | 91 producer_two_phase_max_num_bytes_written_ = 0; |
92 ProducerCloseImplNoLock(); | 92 ProducerCloseImplNoLock(); |
93 AwakeConsumerWaitersForStateChangeNoLock(); | 93 AwakeConsumerWaitersForStateChangeNoLock(ConsumerGetWaitFlagsStateNoLock()); |
94 } | 94 } |
95 | 95 |
96 MojoResult DataPipe::ProducerWriteData(const void* elements, | 96 MojoResult DataPipe::ProducerWriteData(const void* elements, |
97 uint32_t* num_bytes, | 97 uint32_t* num_bytes, |
98 bool all_or_none) { | 98 bool all_or_none) { |
99 base::AutoLock locker(lock_); | 99 base::AutoLock locker(lock_); |
100 DCHECK(has_local_producer_no_lock()); | 100 DCHECK(has_local_producer_no_lock()); |
101 | 101 |
102 if (producer_in_two_phase_write_no_lock()) | 102 if (producer_in_two_phase_write_no_lock()) |
103 return MOJO_RESULT_BUSY; | 103 return MOJO_RESULT_BUSY; |
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 WaitFlagsState old_consumer_state = ConsumerGetWaitFlagsStateNoLock(); | 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 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); | 116 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
117 if (!new_consumer_state.equals(old_consumer_state)) | 117 if (!new_consumer_state.equals(old_consumer_state)) |
118 AwakeConsumerWaitersForStateChangeNoLock(); | 118 AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state); |
119 return rv; | 119 return rv; |
120 } | 120 } |
121 | 121 |
122 MojoResult DataPipe::ProducerBeginWriteData(void** buffer, | 122 MojoResult DataPipe::ProducerBeginWriteData(void** buffer, |
123 uint32_t* buffer_num_bytes, | 123 uint32_t* buffer_num_bytes, |
124 bool all_or_none) { | 124 bool all_or_none) { |
125 base::AutoLock locker(lock_); | 125 base::AutoLock locker(lock_); |
126 DCHECK(has_local_producer_no_lock()); | 126 DCHECK(has_local_producer_no_lock()); |
127 | 127 |
128 if (producer_in_two_phase_write_no_lock()) | 128 if (producer_in_two_phase_write_no_lock()) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 num_bytes_written % element_num_bytes_ != 0) { | 160 num_bytes_written % element_num_bytes_ != 0) { |
161 rv = MOJO_RESULT_INVALID_ARGUMENT; | 161 rv = MOJO_RESULT_INVALID_ARGUMENT; |
162 producer_two_phase_max_num_bytes_written_ = 0; | 162 producer_two_phase_max_num_bytes_written_ = 0; |
163 } else { | 163 } else { |
164 rv = ProducerEndWriteDataImplNoLock(num_bytes_written); | 164 rv = ProducerEndWriteDataImplNoLock(num_bytes_written); |
165 } | 165 } |
166 // Two-phase write ended even on failure. | 166 // Two-phase write ended even on failure. |
167 DCHECK(!producer_in_two_phase_write_no_lock()); | 167 DCHECK(!producer_in_two_phase_write_no_lock()); |
168 // 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 |
169 // during the two-phase write), so awake producer waiters. | 169 // during the two-phase write), so awake producer waiters. |
170 if (ProducerGetWaitFlagsStateNoLock().satisfies(MOJO_WAIT_FLAG_WRITABLE)) | 170 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
171 AwakeProducerWaitersForStateChangeNoLock(); | 171 if (new_producer_state.satisfies(MOJO_WAIT_FLAG_WRITABLE)) |
| 172 AwakeProducerWaitersForStateChangeNoLock(new_producer_state); |
172 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); | 173 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
173 if (!new_consumer_state.equals(old_consumer_state)) | 174 if (!new_consumer_state.equals(old_consumer_state)) |
174 AwakeConsumerWaitersForStateChangeNoLock(); | 175 AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state); |
175 return rv; | 176 return rv; |
176 } | 177 } |
177 | 178 |
178 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, | 179 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, |
179 MojoWaitFlags flags, | 180 MojoWaitFlags flags, |
180 MojoResult wake_result) { | 181 MojoResult wake_result) { |
181 base::AutoLock locker(lock_); | 182 base::AutoLock locker(lock_); |
182 DCHECK(has_local_producer_no_lock()); | 183 DCHECK(has_local_producer_no_lock()); |
183 | 184 |
184 WaitFlagsState producer_state = ProducerGetWaitFlagsStateNoLock(); | 185 WaitFlagsState producer_state = ProducerGetWaitFlagsStateNoLock(); |
(...skipping 27 matching lines...) Expand all Loading... |
212 base::AutoLock locker(lock_); | 213 base::AutoLock locker(lock_); |
213 DCHECK(consumer_open_); | 214 DCHECK(consumer_open_); |
214 consumer_open_ = false; | 215 consumer_open_ = false; |
215 DCHECK(has_local_consumer_no_lock()); | 216 DCHECK(has_local_consumer_no_lock()); |
216 consumer_waiter_list_.reset(); | 217 consumer_waiter_list_.reset(); |
217 // Not a bug, except possibly in "user" code. | 218 // Not a bug, except possibly in "user" code. |
218 DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) | 219 DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) |
219 << "Consumer closed with active two-phase read"; | 220 << "Consumer closed with active two-phase read"; |
220 consumer_two_phase_max_num_bytes_read_ = 0; | 221 consumer_two_phase_max_num_bytes_read_ = 0; |
221 ConsumerCloseImplNoLock(); | 222 ConsumerCloseImplNoLock(); |
222 AwakeProducerWaitersForStateChangeNoLock(); | 223 AwakeProducerWaitersForStateChangeNoLock(ProducerGetWaitFlagsStateNoLock()); |
223 } | 224 } |
224 | 225 |
225 MojoResult DataPipe::ConsumerReadData(void* elements, | 226 MojoResult DataPipe::ConsumerReadData(void* elements, |
226 uint32_t* num_bytes, | 227 uint32_t* num_bytes, |
227 bool all_or_none) { | 228 bool all_or_none) { |
228 base::AutoLock locker(lock_); | 229 base::AutoLock locker(lock_); |
229 DCHECK(has_local_consumer_no_lock()); | 230 DCHECK(has_local_consumer_no_lock()); |
230 | 231 |
231 if (consumer_in_two_phase_read_no_lock()) | 232 if (consumer_in_two_phase_read_no_lock()) |
232 return MOJO_RESULT_BUSY; | 233 return MOJO_RESULT_BUSY; |
233 | 234 |
234 if (*num_bytes % element_num_bytes_ != 0) | 235 if (*num_bytes % element_num_bytes_ != 0) |
235 return MOJO_RESULT_INVALID_ARGUMENT; | 236 return MOJO_RESULT_INVALID_ARGUMENT; |
236 | 237 |
237 if (*num_bytes == 0) | 238 if (*num_bytes == 0) |
238 return MOJO_RESULT_OK; // Nothing to do. | 239 return MOJO_RESULT_OK; // Nothing to do. |
239 | 240 |
240 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); | 241 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); |
241 MojoResult rv = ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none); | 242 MojoResult rv = ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none); |
242 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); | 243 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
243 if (!new_producer_state.equals(old_producer_state)) | 244 if (!new_producer_state.equals(old_producer_state)) |
244 AwakeProducerWaitersForStateChangeNoLock(); | 245 AwakeProducerWaitersForStateChangeNoLock(new_producer_state); |
245 return rv; | 246 return rv; |
246 } | 247 } |
247 | 248 |
248 MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes, | 249 MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes, |
249 bool all_or_none) { | 250 bool all_or_none) { |
250 base::AutoLock locker(lock_); | 251 base::AutoLock locker(lock_); |
251 DCHECK(has_local_consumer_no_lock()); | 252 DCHECK(has_local_consumer_no_lock()); |
252 | 253 |
253 if (consumer_in_two_phase_read_no_lock()) | 254 if (consumer_in_two_phase_read_no_lock()) |
254 return MOJO_RESULT_BUSY; | 255 return MOJO_RESULT_BUSY; |
255 | 256 |
256 if (*num_bytes % element_num_bytes_ != 0) | 257 if (*num_bytes % element_num_bytes_ != 0) |
257 return MOJO_RESULT_INVALID_ARGUMENT; | 258 return MOJO_RESULT_INVALID_ARGUMENT; |
258 | 259 |
259 if (*num_bytes == 0) | 260 if (*num_bytes == 0) |
260 return MOJO_RESULT_OK; // Nothing to do. | 261 return MOJO_RESULT_OK; // Nothing to do. |
261 | 262 |
262 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); | 263 WaitFlagsState old_producer_state = ProducerGetWaitFlagsStateNoLock(); |
263 MojoResult rv = ConsumerDiscardDataImplNoLock(num_bytes, all_or_none); | 264 MojoResult rv = ConsumerDiscardDataImplNoLock(num_bytes, all_or_none); |
264 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); | 265 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
265 if (!new_producer_state.equals(old_producer_state)) | 266 if (!new_producer_state.equals(old_producer_state)) |
266 AwakeProducerWaitersForStateChangeNoLock(); | 267 AwakeProducerWaitersForStateChangeNoLock(new_producer_state); |
267 return rv; | 268 return rv; |
268 } | 269 } |
269 | 270 |
270 MojoResult DataPipe::ConsumerQueryData(uint32_t* num_bytes) { | 271 MojoResult DataPipe::ConsumerQueryData(uint32_t* num_bytes) { |
271 base::AutoLock locker(lock_); | 272 base::AutoLock locker(lock_); |
272 DCHECK(has_local_consumer_no_lock()); | 273 DCHECK(has_local_consumer_no_lock()); |
273 | 274 |
274 if (consumer_in_two_phase_read_no_lock()) | 275 if (consumer_in_two_phase_read_no_lock()) |
275 return MOJO_RESULT_BUSY; | 276 return MOJO_RESULT_BUSY; |
276 | 277 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 consumer_two_phase_max_num_bytes_read_ = 0; | 314 consumer_two_phase_max_num_bytes_read_ = 0; |
314 } else { | 315 } else { |
315 rv = ConsumerEndReadDataImplNoLock(num_bytes_read); | 316 rv = ConsumerEndReadDataImplNoLock(num_bytes_read); |
316 } | 317 } |
317 // Two-phase read ended even on failure. | 318 // Two-phase read ended even on failure. |
318 DCHECK(!consumer_in_two_phase_read_no_lock()); | 319 DCHECK(!consumer_in_two_phase_read_no_lock()); |
319 // If we're now readable, we *became* readable (since we weren't readable | 320 // If we're now readable, we *became* readable (since we weren't readable |
320 // during the two-phase read), so awake consumer waiters. | 321 // during the two-phase read), so awake consumer waiters. |
321 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); | 322 WaitFlagsState new_consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
322 if (new_consumer_state.satisfies(MOJO_WAIT_FLAG_READABLE)) | 323 if (new_consumer_state.satisfies(MOJO_WAIT_FLAG_READABLE)) |
323 AwakeConsumerWaitersForStateChangeNoLock(); | 324 AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state); |
324 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); | 325 WaitFlagsState new_producer_state = ProducerGetWaitFlagsStateNoLock(); |
325 if (!new_producer_state.equals(old_producer_state)) | 326 if (!new_producer_state.equals(old_producer_state)) |
326 AwakeProducerWaitersForStateChangeNoLock(); | 327 AwakeProducerWaitersForStateChangeNoLock(new_producer_state); |
327 return rv; | 328 return rv; |
328 } | 329 } |
329 | 330 |
330 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, | 331 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, |
331 MojoWaitFlags flags, | 332 MojoWaitFlags flags, |
332 MojoResult wake_result) { | 333 MojoResult wake_result) { |
333 base::AutoLock locker(lock_); | 334 base::AutoLock locker(lock_); |
334 DCHECK(has_local_consumer_no_lock()); | 335 DCHECK(has_local_consumer_no_lock()); |
335 | 336 |
336 WaitFlagsState consumer_state = ConsumerGetWaitFlagsStateNoLock(); | 337 WaitFlagsState consumer_state = ConsumerGetWaitFlagsStateNoLock(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 DCHECK_EQ(ValidateCreateOptions(&validated_options, &unused), MOJO_RESULT_OK); | 374 DCHECK_EQ(ValidateCreateOptions(&validated_options, &unused), MOJO_RESULT_OK); |
374 } | 375 } |
375 | 376 |
376 DataPipe::~DataPipe() { | 377 DataPipe::~DataPipe() { |
377 DCHECK(!producer_open_); | 378 DCHECK(!producer_open_); |
378 DCHECK(!consumer_open_); | 379 DCHECK(!consumer_open_); |
379 DCHECK(!producer_waiter_list_); | 380 DCHECK(!producer_waiter_list_); |
380 DCHECK(!consumer_waiter_list_); | 381 DCHECK(!consumer_waiter_list_); |
381 } | 382 } |
382 | 383 |
383 void DataPipe::AwakeProducerWaitersForStateChangeNoLock() { | 384 void DataPipe::AwakeProducerWaitersForStateChangeNoLock( |
| 385 const WaitFlagsState& new_producer_state) { |
384 lock_.AssertAcquired(); | 386 lock_.AssertAcquired(); |
385 if (!has_local_producer_no_lock()) | 387 if (!has_local_producer_no_lock()) |
386 return; | 388 return; |
387 producer_waiter_list_->AwakeWaitersForStateChange( | 389 producer_waiter_list_->AwakeWaitersForStateChange(new_producer_state); |
388 ProducerGetWaitFlagsStateNoLock()); | |
389 } | 390 } |
390 | 391 |
391 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() { | 392 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock( |
| 393 const WaitFlagsState& new_consumer_state) { |
392 lock_.AssertAcquired(); | 394 lock_.AssertAcquired(); |
393 if (!has_local_consumer_no_lock()) | 395 if (!has_local_consumer_no_lock()) |
394 return; | 396 return; |
395 consumer_waiter_list_->AwakeWaitersForStateChange( | 397 consumer_waiter_list_->AwakeWaitersForStateChange(new_consumer_state); |
396 ConsumerGetWaitFlagsStateNoLock()); | |
397 } | 398 } |
398 | 399 |
399 } // namespace system | 400 } // namespace system |
400 } // namespace mojo | 401 } // namespace mojo |
OLD | NEW |