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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 base::AutoLock locker(lock_); | 72 base::AutoLock locker(lock_); |
73 DCHECK(producer_open_); | 73 DCHECK(producer_open_); |
74 producer_open_ = false; | 74 producer_open_ = false; |
75 DCHECK(has_local_producer_no_lock()); | 75 DCHECK(has_local_producer_no_lock()); |
76 producer_waiter_list_.reset(); | 76 producer_waiter_list_.reset(); |
77 // Not a bug, except possibly in "user" code. | 77 // Not a bug, except possibly in "user" code. |
78 DVLOG_IF(2, producer_in_two_phase_write_no_lock()) | 78 DVLOG_IF(2, producer_in_two_phase_write_no_lock()) |
79 << "Producer closed with active two-phase write"; | 79 << "Producer closed with active two-phase write"; |
80 producer_two_phase_max_num_bytes_written_ = 0; | 80 producer_two_phase_max_num_bytes_written_ = 0; |
81 ProducerCloseImplNoLock(); | 81 ProducerCloseImplNoLock(); |
| 82 AwakeConsumerWaitersForStateChangeNoLock(); |
82 } | 83 } |
83 | 84 |
84 MojoResult DataPipe::ProducerWriteData(const void* elements, | 85 MojoResult DataPipe::ProducerWriteData(const void* elements, |
85 uint32_t* num_bytes, | 86 uint32_t* num_bytes, |
86 bool all_or_none) { | 87 bool all_or_none) { |
87 base::AutoLock locker(lock_); | 88 base::AutoLock locker(lock_); |
88 DCHECK(has_local_producer_no_lock()); | 89 DCHECK(has_local_producer_no_lock()); |
89 | 90 |
90 if (producer_in_two_phase_write_no_lock()) | 91 if (producer_in_two_phase_write_no_lock()) |
91 return MOJO_RESULT_BUSY; | 92 return MOJO_RESULT_BUSY; |
92 if (!consumer_open_no_lock()) | 93 if (!consumer_open_no_lock()) |
93 return MOJO_RESULT_FAILED_PRECONDITION; | 94 return MOJO_RESULT_FAILED_PRECONDITION; |
94 | 95 |
95 // Returning "busy" takes priority over "invalid argument". | 96 // Returning "busy" takes priority over "invalid argument". |
96 if (*num_bytes % element_num_bytes_ != 0) | 97 if (*num_bytes % element_num_bytes_ != 0) |
97 return MOJO_RESULT_INVALID_ARGUMENT; | 98 return MOJO_RESULT_INVALID_ARGUMENT; |
98 | 99 |
99 if (*num_bytes == 0) | 100 if (*num_bytes == 0) |
100 return MOJO_RESULT_OK; // Nothing to do. | 101 return MOJO_RESULT_OK; // Nothing to do. |
101 | 102 |
102 return ProducerWriteDataImplNoLock(elements, num_bytes, all_or_none); | 103 MojoWaitFlags old_consumer_satisfied_flags = ConsumerSatisfiedFlagsNoLock(); |
| 104 MojoResult rv = ProducerWriteDataImplNoLock(elements, num_bytes, all_or_none); |
| 105 if (ConsumerSatisfiedFlagsNoLock() != old_consumer_satisfied_flags) |
| 106 AwakeConsumerWaitersForStateChangeNoLock(); |
| 107 return rv; |
103 } | 108 } |
104 | 109 |
105 MojoResult DataPipe::ProducerBeginWriteData(void** buffer, | 110 MojoResult DataPipe::ProducerBeginWriteData(void** buffer, |
106 uint32_t* buffer_num_bytes, | 111 uint32_t* buffer_num_bytes, |
107 bool all_or_none) { | 112 bool all_or_none) { |
108 base::AutoLock locker(lock_); | 113 base::AutoLock locker(lock_); |
109 DCHECK(has_local_producer_no_lock()); | 114 DCHECK(has_local_producer_no_lock()); |
110 | 115 |
111 if (producer_in_two_phase_write_no_lock()) | 116 if (producer_in_two_phase_write_no_lock()) |
112 return MOJO_RESULT_BUSY; | 117 return MOJO_RESULT_BUSY; |
113 if (!consumer_open_no_lock()) | 118 if (!consumer_open_no_lock()) |
114 return MOJO_RESULT_FAILED_PRECONDITION; | 119 return MOJO_RESULT_FAILED_PRECONDITION; |
115 | 120 |
116 MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes, | 121 MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes, |
117 all_or_none); | 122 all_or_none); |
118 if (rv != MOJO_RESULT_OK) | 123 if (rv != MOJO_RESULT_OK) |
119 return rv; | 124 return rv; |
120 | 125 // Note: No need to awake producer waiters, even though we're going from |
| 126 // writable to non-writable (since you can't wait on non-writability). |
| 127 // Similarly, though this may have discarded data (in "may discard" mode), |
| 128 // making it non-readable, there's still no need to awake consumer waiters. |
121 DCHECK(producer_in_two_phase_write_no_lock()); | 129 DCHECK(producer_in_two_phase_write_no_lock()); |
122 return MOJO_RESULT_OK; | 130 return MOJO_RESULT_OK; |
123 } | 131 } |
124 | 132 |
125 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { | 133 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { |
126 base::AutoLock locker(lock_); | 134 base::AutoLock locker(lock_); |
127 DCHECK(has_local_producer_no_lock()); | 135 DCHECK(has_local_producer_no_lock()); |
128 | 136 |
129 if (!producer_in_two_phase_write_no_lock()) | 137 if (!producer_in_two_phase_write_no_lock()) |
130 return MOJO_RESULT_FAILED_PRECONDITION; | 138 return MOJO_RESULT_FAILED_PRECONDITION; |
131 // Note: Allow successful completion of the two-phase write even if the | 139 // Note: Allow successful completion of the two-phase write even if the |
132 // consumer has been closed. | 140 // consumer has been closed. |
133 | 141 |
| 142 MojoWaitFlags old_consumer_satisfied_flags = ConsumerSatisfiedFlagsNoLock(); |
134 MojoResult rv = ProducerEndWriteDataImplNoLock(num_bytes_written); | 143 MojoResult rv = ProducerEndWriteDataImplNoLock(num_bytes_written); |
135 // Two-phase write ended even on failure. | 144 // Two-phase write ended even on failure. |
136 DCHECK(!producer_in_two_phase_write_no_lock()); | 145 DCHECK(!producer_in_two_phase_write_no_lock()); |
| 146 // If we're now writable, we *became* writable (since we weren't writable |
| 147 // during the two-phase write), so awake producer waiters. |
| 148 if ((ProducerSatisfiedFlagsNoLock() & MOJO_WAIT_FLAG_WRITABLE)) |
| 149 AwakeProducerWaitersForStateChangeNoLock(); |
| 150 if (ConsumerSatisfiedFlagsNoLock() != old_consumer_satisfied_flags) |
| 151 AwakeConsumerWaitersForStateChangeNoLock(); |
137 return rv; | 152 return rv; |
138 } | 153 } |
139 | 154 |
140 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, | 155 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, |
141 MojoWaitFlags flags, | 156 MojoWaitFlags flags, |
142 MojoResult wake_result) { | 157 MojoResult wake_result) { |
143 base::AutoLock locker(lock_); | 158 base::AutoLock locker(lock_); |
144 DCHECK(has_local_producer_no_lock()); | 159 DCHECK(has_local_producer_no_lock()); |
145 | 160 |
146 if ((flags & ProducerSatisfiedFlagsNoLock())) | 161 if ((flags & ProducerSatisfiedFlagsNoLock())) |
(...skipping 21 matching lines...) Expand all Loading... |
168 base::AutoLock locker(lock_); | 183 base::AutoLock locker(lock_); |
169 DCHECK(consumer_open_); | 184 DCHECK(consumer_open_); |
170 consumer_open_ = false; | 185 consumer_open_ = false; |
171 DCHECK(has_local_consumer_no_lock()); | 186 DCHECK(has_local_consumer_no_lock()); |
172 consumer_waiter_list_.reset(); | 187 consumer_waiter_list_.reset(); |
173 // Not a bug, except possibly in "user" code. | 188 // Not a bug, except possibly in "user" code. |
174 DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) | 189 DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) |
175 << "Consumer closed with active two-phase read"; | 190 << "Consumer closed with active two-phase read"; |
176 consumer_two_phase_max_num_bytes_read_ = 0; | 191 consumer_two_phase_max_num_bytes_read_ = 0; |
177 ConsumerCloseImplNoLock(); | 192 ConsumerCloseImplNoLock(); |
| 193 AwakeProducerWaitersForStateChangeNoLock(); |
178 } | 194 } |
179 | 195 |
180 MojoResult DataPipe::ConsumerReadData(void* elements, | 196 MojoResult DataPipe::ConsumerReadData(void* elements, |
181 uint32_t* num_bytes, | 197 uint32_t* num_bytes, |
182 bool all_or_none) { | 198 bool all_or_none) { |
183 base::AutoLock locker(lock_); | 199 base::AutoLock locker(lock_); |
184 DCHECK(has_local_consumer_no_lock()); | 200 DCHECK(has_local_consumer_no_lock()); |
185 | 201 |
186 if (consumer_in_two_phase_read_no_lock()) | 202 if (consumer_in_two_phase_read_no_lock()) |
187 return MOJO_RESULT_BUSY; | 203 return MOJO_RESULT_BUSY; |
188 | 204 |
189 if (*num_bytes % element_num_bytes_ != 0) | 205 if (*num_bytes % element_num_bytes_ != 0) |
190 return MOJO_RESULT_INVALID_ARGUMENT; | 206 return MOJO_RESULT_INVALID_ARGUMENT; |
191 | 207 |
192 if (*num_bytes == 0) | 208 if (*num_bytes == 0) |
193 return MOJO_RESULT_OK; // Nothing to do. | 209 return MOJO_RESULT_OK; // Nothing to do. |
194 | 210 |
195 return ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none); | 211 MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock(); |
| 212 MojoResult rv = ConsumerReadDataImplNoLock(elements, num_bytes, all_or_none); |
| 213 if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags) |
| 214 AwakeProducerWaitersForStateChangeNoLock(); |
| 215 return rv; |
196 } | 216 } |
197 | 217 |
198 MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes, | 218 MojoResult DataPipe::ConsumerDiscardData(uint32_t* num_bytes, |
199 bool all_or_none) { | 219 bool all_or_none) { |
200 base::AutoLock locker(lock_); | 220 base::AutoLock locker(lock_); |
201 DCHECK(has_local_consumer_no_lock()); | 221 DCHECK(has_local_consumer_no_lock()); |
202 | 222 |
203 if (consumer_in_two_phase_read_no_lock()) | 223 if (consumer_in_two_phase_read_no_lock()) |
204 return MOJO_RESULT_BUSY; | 224 return MOJO_RESULT_BUSY; |
205 | 225 |
206 if (*num_bytes % element_num_bytes_ != 0) | 226 if (*num_bytes % element_num_bytes_ != 0) |
207 return MOJO_RESULT_INVALID_ARGUMENT; | 227 return MOJO_RESULT_INVALID_ARGUMENT; |
208 | 228 |
209 if (*num_bytes == 0) | 229 if (*num_bytes == 0) |
210 return MOJO_RESULT_OK; // Nothing to do. | 230 return MOJO_RESULT_OK; // Nothing to do. |
211 | 231 |
212 return ConsumerDiscardDataImplNoLock(num_bytes, all_or_none); | 232 MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock(); |
| 233 MojoResult rv = ConsumerDiscardDataImplNoLock(num_bytes, all_or_none); |
| 234 if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags) |
| 235 AwakeProducerWaitersForStateChangeNoLock(); |
| 236 return rv; |
213 } | 237 } |
214 | 238 |
215 MojoResult DataPipe::ConsumerQueryData(uint32_t* num_bytes) { | 239 MojoResult DataPipe::ConsumerQueryData(uint32_t* num_bytes) { |
216 base::AutoLock locker(lock_); | 240 base::AutoLock locker(lock_); |
217 DCHECK(has_local_consumer_no_lock()); | 241 DCHECK(has_local_consumer_no_lock()); |
218 | 242 |
219 if (consumer_in_two_phase_read_no_lock()) | 243 if (consumer_in_two_phase_read_no_lock()) |
220 return MOJO_RESULT_BUSY; | 244 return MOJO_RESULT_BUSY; |
221 | 245 |
222 // Note: Don't need to validate |*num_bytes| for query. | 246 // Note: Don't need to validate |*num_bytes| for query. |
223 return ConsumerQueryDataImplNoLock(num_bytes); | 247 return ConsumerQueryDataImplNoLock(num_bytes); |
224 } | 248 } |
225 | 249 |
226 MojoResult DataPipe::ConsumerBeginReadData(const void** buffer, | 250 MojoResult DataPipe::ConsumerBeginReadData(const void** buffer, |
227 uint32_t* buffer_num_bytes, | 251 uint32_t* buffer_num_bytes, |
228 bool all_or_none) { | 252 bool all_or_none) { |
229 base::AutoLock locker(lock_); | 253 base::AutoLock locker(lock_); |
230 DCHECK(has_local_consumer_no_lock()); | 254 DCHECK(has_local_consumer_no_lock()); |
231 | 255 |
232 if (consumer_in_two_phase_read_no_lock()) | 256 if (consumer_in_two_phase_read_no_lock()) |
233 return MOJO_RESULT_BUSY; | 257 return MOJO_RESULT_BUSY; |
234 | 258 |
235 MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes, | 259 MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes, |
236 all_or_none); | 260 all_or_none); |
237 if (rv != MOJO_RESULT_OK) | 261 if (rv != MOJO_RESULT_OK) |
238 return rv; | 262 return rv; |
239 | |
240 DCHECK(consumer_in_two_phase_read_no_lock()); | 263 DCHECK(consumer_in_two_phase_read_no_lock()); |
241 return MOJO_RESULT_OK; | 264 return MOJO_RESULT_OK; |
242 } | 265 } |
243 | 266 |
244 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { | 267 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { |
245 base::AutoLock locker(lock_); | 268 base::AutoLock locker(lock_); |
246 DCHECK(has_local_consumer_no_lock()); | 269 DCHECK(has_local_consumer_no_lock()); |
247 | 270 |
248 if (!consumer_in_two_phase_read_no_lock()) | 271 if (!consumer_in_two_phase_read_no_lock()) |
249 return MOJO_RESULT_FAILED_PRECONDITION; | 272 return MOJO_RESULT_FAILED_PRECONDITION; |
250 | 273 |
| 274 MojoWaitFlags old_producer_satisfied_flags = ProducerSatisfiedFlagsNoLock(); |
251 MojoResult rv = ConsumerEndReadDataImplNoLock(num_bytes_read); | 275 MojoResult rv = ConsumerEndReadDataImplNoLock(num_bytes_read); |
252 // Two-phase read ended even on failure. | 276 // Two-phase read ended even on failure. |
253 DCHECK(!consumer_in_two_phase_read_no_lock()); | 277 DCHECK(!consumer_in_two_phase_read_no_lock()); |
| 278 // If we're now readable, we *became* readable (since we weren't readable |
| 279 // during the two-phase read), so awake consumer waiters. |
| 280 if ((ConsumerSatisfiedFlagsNoLock() & MOJO_WAIT_FLAG_READABLE)) |
| 281 AwakeConsumerWaitersForStateChangeNoLock(); |
| 282 if (ProducerSatisfiedFlagsNoLock() != old_producer_satisfied_flags) |
| 283 AwakeProducerWaitersForStateChangeNoLock(); |
254 return rv; | 284 return rv; |
255 } | 285 } |
256 | 286 |
257 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, | 287 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, |
258 MojoWaitFlags flags, | 288 MojoWaitFlags flags, |
259 MojoResult wake_result) { | 289 MojoResult wake_result) { |
260 base::AutoLock locker(lock_); | 290 base::AutoLock locker(lock_); |
261 DCHECK(has_local_consumer_no_lock()); | 291 DCHECK(has_local_consumer_no_lock()); |
262 | 292 |
263 if ((flags & ConsumerSatisfiedFlagsNoLock())) | 293 if ((flags & ConsumerSatisfiedFlagsNoLock())) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() { | 341 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock() { |
312 lock_.AssertAcquired(); | 342 lock_.AssertAcquired(); |
313 if (!has_local_consumer_no_lock()) | 343 if (!has_local_consumer_no_lock()) |
314 return; | 344 return; |
315 consumer_waiter_list_->AwakeWaitersForStateChange( | 345 consumer_waiter_list_->AwakeWaitersForStateChange( |
316 ConsumerSatisfiedFlagsNoLock(), ConsumerSatisfiableFlagsNoLock()); | 346 ConsumerSatisfiedFlagsNoLock(), ConsumerSatisfiableFlagsNoLock()); |
317 } | 347 } |
318 | 348 |
319 } // namespace system | 349 } // namespace system |
320 } // namespace mojo | 350 } // namespace mojo |
OLD | NEW |