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/edk/system/data_pipe.h" | 5 #include "mojo/edk/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> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "mojo/edk/system/awakable_list.h" | 13 #include "mojo/edk/system/awakable_list.h" |
14 #include "mojo/edk/system/configuration.h" | 14 #include "mojo/edk/system/configuration.h" |
| 15 #include "mojo/edk/system/data_pipe_impl.h" |
15 #include "mojo/edk/system/memory.h" | 16 #include "mojo/edk/system/memory.h" |
16 #include "mojo/edk/system/options_validation.h" | 17 #include "mojo/edk/system/options_validation.h" |
17 | 18 |
18 namespace mojo { | 19 namespace mojo { |
19 namespace system { | 20 namespace system { |
20 | 21 |
| 22 DataPipe::DataPipe(bool has_local_producer, |
| 23 bool has_local_consumer, |
| 24 const MojoCreateDataPipeOptions& validated_options, |
| 25 scoped_ptr<DataPipeImpl> impl) |
| 26 : may_discard_((validated_options.flags & |
| 27 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)), |
| 28 element_num_bytes_(validated_options.element_num_bytes), |
| 29 capacity_num_bytes_(validated_options.capacity_num_bytes), |
| 30 producer_open_(true), |
| 31 consumer_open_(true), |
| 32 producer_awakable_list_(has_local_producer ? new AwakableList() |
| 33 : nullptr), |
| 34 consumer_awakable_list_(has_local_consumer ? new AwakableList() |
| 35 : nullptr), |
| 36 producer_two_phase_max_num_bytes_written_(0), |
| 37 consumer_two_phase_max_num_bytes_read_(0), |
| 38 impl_(impl.Pass()) { |
| 39 impl_->set_owner(this); |
| 40 |
| 41 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) |
| 42 // Check that the passed in options actually are validated. |
| 43 MojoCreateDataPipeOptions unused = {0}; |
| 44 DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused), |
| 45 MOJO_RESULT_OK); |
| 46 #endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) |
| 47 } |
| 48 |
21 // static | 49 // static |
22 MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { | 50 MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { |
23 MojoCreateDataPipeOptions result = { | 51 MojoCreateDataPipeOptions result = { |
24 static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), | 52 static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), |
25 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, | 53 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, |
26 1u, | 54 1u, |
27 static_cast<uint32_t>( | 55 static_cast<uint32_t>( |
28 GetConfiguration().default_data_pipe_capacity_bytes)}; | 56 GetConfiguration().default_data_pipe_capacity_bytes)}; |
29 return result; | 57 return result; |
30 } | 58 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 uint32_t max_num_bytes_to_write = num_bytes.Get(); | 137 uint32_t max_num_bytes_to_write = num_bytes.Get(); |
110 if (max_num_bytes_to_write % element_num_bytes_ != 0) | 138 if (max_num_bytes_to_write % element_num_bytes_ != 0) |
111 return MOJO_RESULT_INVALID_ARGUMENT; | 139 return MOJO_RESULT_INVALID_ARGUMENT; |
112 | 140 |
113 if (max_num_bytes_to_write == 0) | 141 if (max_num_bytes_to_write == 0) |
114 return MOJO_RESULT_OK; // Nothing to do. | 142 return MOJO_RESULT_OK; // Nothing to do. |
115 | 143 |
116 uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0; | 144 uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0; |
117 | 145 |
118 HandleSignalsState old_consumer_state = | 146 HandleSignalsState old_consumer_state = |
119 ConsumerGetHandleSignalsStateImplNoLock(); | 147 impl_->ConsumerGetHandleSignalsState(); |
120 MojoResult rv = ProducerWriteDataImplNoLock( | 148 MojoResult rv = impl_->ProducerWriteData( |
121 elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write); | 149 elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write); |
122 HandleSignalsState new_consumer_state = | 150 HandleSignalsState new_consumer_state = |
123 ConsumerGetHandleSignalsStateImplNoLock(); | 151 impl_->ConsumerGetHandleSignalsState(); |
124 if (!new_consumer_state.equals(old_consumer_state)) | 152 if (!new_consumer_state.equals(old_consumer_state)) |
125 AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); | 153 AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); |
126 return rv; | 154 return rv; |
127 } | 155 } |
128 | 156 |
129 MojoResult DataPipe::ProducerBeginWriteData( | 157 MojoResult DataPipe::ProducerBeginWriteData( |
130 UserPointer<void*> buffer, | 158 UserPointer<void*> buffer, |
131 UserPointer<uint32_t> buffer_num_bytes, | 159 UserPointer<uint32_t> buffer_num_bytes, |
132 bool all_or_none) { | 160 bool all_or_none) { |
133 base::AutoLock locker(lock_); | 161 base::AutoLock locker(lock_); |
134 DCHECK(has_local_producer_no_lock()); | 162 DCHECK(has_local_producer_no_lock()); |
135 | 163 |
136 if (producer_in_two_phase_write_no_lock()) | 164 if (producer_in_two_phase_write_no_lock()) |
137 return MOJO_RESULT_BUSY; | 165 return MOJO_RESULT_BUSY; |
138 if (!consumer_open_no_lock()) | 166 if (!consumer_open_no_lock()) |
139 return MOJO_RESULT_FAILED_PRECONDITION; | 167 return MOJO_RESULT_FAILED_PRECONDITION; |
140 | 168 |
141 uint32_t min_num_bytes_to_write = 0; | 169 uint32_t min_num_bytes_to_write = 0; |
142 if (all_or_none) { | 170 if (all_or_none) { |
143 min_num_bytes_to_write = buffer_num_bytes.Get(); | 171 min_num_bytes_to_write = buffer_num_bytes.Get(); |
144 if (min_num_bytes_to_write % element_num_bytes_ != 0) | 172 if (min_num_bytes_to_write % element_num_bytes_ != 0) |
145 return MOJO_RESULT_INVALID_ARGUMENT; | 173 return MOJO_RESULT_INVALID_ARGUMENT; |
146 } | 174 } |
147 | 175 |
148 MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes, | 176 MojoResult rv = impl_->ProducerBeginWriteData(buffer, buffer_num_bytes, |
149 min_num_bytes_to_write); | 177 min_num_bytes_to_write); |
150 if (rv != MOJO_RESULT_OK) | 178 if (rv != MOJO_RESULT_OK) |
151 return rv; | 179 return rv; |
152 // Note: No need to awake producer awakables, even though we're going from | 180 // Note: No need to awake producer awakables, even though we're going from |
153 // writable to non-writable (since you can't wait on non-writability). | 181 // writable to non-writable (since you can't wait on non-writability). |
154 // Similarly, though this may have discarded data (in "may discard" mode), | 182 // Similarly, though this may have discarded data (in "may discard" mode), |
155 // making it non-readable, there's still no need to awake consumer awakables. | 183 // making it non-readable, there's still no need to awake consumer awakables. |
156 DCHECK(producer_in_two_phase_write_no_lock()); | 184 DCHECK(producer_in_two_phase_write_no_lock()); |
157 return MOJO_RESULT_OK; | 185 return MOJO_RESULT_OK; |
158 } | 186 } |
159 | 187 |
160 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { | 188 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { |
161 base::AutoLock locker(lock_); | 189 base::AutoLock locker(lock_); |
162 DCHECK(has_local_producer_no_lock()); | 190 DCHECK(has_local_producer_no_lock()); |
163 | 191 |
164 if (!producer_in_two_phase_write_no_lock()) | 192 if (!producer_in_two_phase_write_no_lock()) |
165 return MOJO_RESULT_FAILED_PRECONDITION; | 193 return MOJO_RESULT_FAILED_PRECONDITION; |
166 // Note: Allow successful completion of the two-phase write even if the | 194 // Note: Allow successful completion of the two-phase write even if the |
167 // consumer has been closed. | 195 // consumer has been closed. |
168 | 196 |
169 HandleSignalsState old_consumer_state = | 197 HandleSignalsState old_consumer_state = |
170 ConsumerGetHandleSignalsStateImplNoLock(); | 198 impl_->ConsumerGetHandleSignalsState(); |
171 MojoResult rv; | 199 MojoResult rv; |
172 if (num_bytes_written > producer_two_phase_max_num_bytes_written_ || | 200 if (num_bytes_written > producer_two_phase_max_num_bytes_written_ || |
173 num_bytes_written % element_num_bytes_ != 0) { | 201 num_bytes_written % element_num_bytes_ != 0) { |
174 rv = MOJO_RESULT_INVALID_ARGUMENT; | 202 rv = MOJO_RESULT_INVALID_ARGUMENT; |
175 producer_two_phase_max_num_bytes_written_ = 0; | 203 producer_two_phase_max_num_bytes_written_ = 0; |
176 } else { | 204 } else { |
177 rv = ProducerEndWriteDataImplNoLock(num_bytes_written); | 205 rv = impl_->ProducerEndWriteData(num_bytes_written); |
178 } | 206 } |
179 // Two-phase write ended even on failure. | 207 // Two-phase write ended even on failure. |
180 DCHECK(!producer_in_two_phase_write_no_lock()); | 208 DCHECK(!producer_in_two_phase_write_no_lock()); |
181 // If we're now writable, we *became* writable (since we weren't writable | 209 // If we're now writable, we *became* writable (since we weren't writable |
182 // during the two-phase write), so awake producer awakables. | 210 // during the two-phase write), so awake producer awakables. |
183 HandleSignalsState new_producer_state = | 211 HandleSignalsState new_producer_state = |
184 ProducerGetHandleSignalsStateImplNoLock(); | 212 impl_->ProducerGetHandleSignalsState(); |
185 if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE)) | 213 if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE)) |
186 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); | 214 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); |
187 HandleSignalsState new_consumer_state = | 215 HandleSignalsState new_consumer_state = |
188 ConsumerGetHandleSignalsStateImplNoLock(); | 216 impl_->ConsumerGetHandleSignalsState(); |
189 if (!new_consumer_state.equals(old_consumer_state)) | 217 if (!new_consumer_state.equals(old_consumer_state)) |
190 AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); | 218 AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); |
191 return rv; | 219 return rv; |
192 } | 220 } |
193 | 221 |
194 HandleSignalsState DataPipe::ProducerGetHandleSignalsState() { | 222 HandleSignalsState DataPipe::ProducerGetHandleSignalsState() { |
195 base::AutoLock locker(lock_); | 223 base::AutoLock locker(lock_); |
196 DCHECK(has_local_producer_no_lock()); | 224 DCHECK(has_local_producer_no_lock()); |
197 return ProducerGetHandleSignalsStateImplNoLock(); | 225 return impl_->ProducerGetHandleSignalsState(); |
198 } | 226 } |
199 | 227 |
200 MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable, | 228 MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable, |
201 MojoHandleSignals signals, | 229 MojoHandleSignals signals, |
202 uint32_t context, | 230 uint32_t context, |
203 HandleSignalsState* signals_state) { | 231 HandleSignalsState* signals_state) { |
204 base::AutoLock locker(lock_); | 232 base::AutoLock locker(lock_); |
205 DCHECK(has_local_producer_no_lock()); | 233 DCHECK(has_local_producer_no_lock()); |
206 | 234 |
207 HandleSignalsState producer_state = ProducerGetHandleSignalsStateImplNoLock(); | 235 HandleSignalsState producer_state = impl_->ProducerGetHandleSignalsState(); |
208 if (producer_state.satisfies(signals)) { | 236 if (producer_state.satisfies(signals)) { |
209 if (signals_state) | 237 if (signals_state) |
210 *signals_state = producer_state; | 238 *signals_state = producer_state; |
211 return MOJO_RESULT_ALREADY_EXISTS; | 239 return MOJO_RESULT_ALREADY_EXISTS; |
212 } | 240 } |
213 if (!producer_state.can_satisfy(signals)) { | 241 if (!producer_state.can_satisfy(signals)) { |
214 if (signals_state) | 242 if (signals_state) |
215 *signals_state = producer_state; | 243 *signals_state = producer_state; |
216 return MOJO_RESULT_FAILED_PRECONDITION; | 244 return MOJO_RESULT_FAILED_PRECONDITION; |
217 } | 245 } |
218 | 246 |
219 producer_awakable_list_->Add(awakable, signals, context); | 247 producer_awakable_list_->Add(awakable, signals, context); |
220 return MOJO_RESULT_OK; | 248 return MOJO_RESULT_OK; |
221 } | 249 } |
222 | 250 |
223 void DataPipe::ProducerRemoveAwakable(Awakable* awakable, | 251 void DataPipe::ProducerRemoveAwakable(Awakable* awakable, |
224 HandleSignalsState* signals_state) { | 252 HandleSignalsState* signals_state) { |
225 base::AutoLock locker(lock_); | 253 base::AutoLock locker(lock_); |
226 DCHECK(has_local_producer_no_lock()); | 254 DCHECK(has_local_producer_no_lock()); |
227 producer_awakable_list_->Remove(awakable); | 255 producer_awakable_list_->Remove(awakable); |
228 if (signals_state) | 256 if (signals_state) |
229 *signals_state = ProducerGetHandleSignalsStateImplNoLock(); | 257 *signals_state = impl_->ProducerGetHandleSignalsState(); |
230 } | 258 } |
231 | 259 |
232 void DataPipe::ProducerStartSerialize(Channel* channel, | 260 void DataPipe::ProducerStartSerialize(Channel* channel, |
233 size_t* max_size, | 261 size_t* max_size, |
234 size_t* max_platform_handles) { | 262 size_t* max_platform_handles) { |
235 base::AutoLock locker(lock_); | 263 base::AutoLock locker(lock_); |
236 DCHECK(has_local_producer_no_lock()); | 264 DCHECK(has_local_producer_no_lock()); |
237 ProducerStartSerializeImplNoLock(channel, max_size, max_platform_handles); | 265 impl_->ProducerStartSerialize(channel, max_size, max_platform_handles); |
238 } | 266 } |
239 | 267 |
240 bool DataPipe::ProducerEndSerialize( | 268 bool DataPipe::ProducerEndSerialize( |
241 Channel* channel, | 269 Channel* channel, |
242 void* destination, | 270 void* destination, |
243 size_t* actual_size, | 271 size_t* actual_size, |
244 embedder::PlatformHandleVector* platform_handles) { | 272 embedder::PlatformHandleVector* platform_handles) { |
245 base::AutoLock locker(lock_); | 273 base::AutoLock locker(lock_); |
246 DCHECK(has_local_producer_no_lock()); | 274 DCHECK(has_local_producer_no_lock()); |
247 return ProducerEndSerializeImplNoLock(channel, destination, actual_size, | 275 return impl_->ProducerEndSerialize(channel, destination, actual_size, |
248 platform_handles); | 276 platform_handles); |
249 } | 277 } |
250 | 278 |
251 bool DataPipe::ProducerIsBusy() const { | 279 bool DataPipe::ProducerIsBusy() const { |
252 base::AutoLock locker(lock_); | 280 base::AutoLock locker(lock_); |
253 return producer_in_two_phase_write_no_lock(); | 281 return producer_in_two_phase_write_no_lock(); |
254 } | 282 } |
255 | 283 |
256 void DataPipe::ConsumerCancelAllAwakables() { | 284 void DataPipe::ConsumerCancelAllAwakables() { |
257 base::AutoLock locker(lock_); | 285 base::AutoLock locker(lock_); |
258 DCHECK(has_local_consumer_no_lock()); | 286 DCHECK(has_local_consumer_no_lock()); |
(...skipping 18 matching lines...) Expand all Loading... |
277 uint32_t max_num_bytes_to_read = num_bytes.Get(); | 305 uint32_t max_num_bytes_to_read = num_bytes.Get(); |
278 if (max_num_bytes_to_read % element_num_bytes_ != 0) | 306 if (max_num_bytes_to_read % element_num_bytes_ != 0) |
279 return MOJO_RESULT_INVALID_ARGUMENT; | 307 return MOJO_RESULT_INVALID_ARGUMENT; |
280 | 308 |
281 if (max_num_bytes_to_read == 0) | 309 if (max_num_bytes_to_read == 0) |
282 return MOJO_RESULT_OK; // Nothing to do. | 310 return MOJO_RESULT_OK; // Nothing to do. |
283 | 311 |
284 uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0; | 312 uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0; |
285 | 313 |
286 HandleSignalsState old_producer_state = | 314 HandleSignalsState old_producer_state = |
287 ProducerGetHandleSignalsStateImplNoLock(); | 315 impl_->ProducerGetHandleSignalsState(); |
288 MojoResult rv = ConsumerReadDataImplNoLock( | 316 MojoResult rv = impl_->ConsumerReadData( |
289 elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read, peek); | 317 elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read, peek); |
290 HandleSignalsState new_producer_state = | 318 HandleSignalsState new_producer_state = |
291 ProducerGetHandleSignalsStateImplNoLock(); | 319 impl_->ProducerGetHandleSignalsState(); |
292 if (!new_producer_state.equals(old_producer_state)) | 320 if (!new_producer_state.equals(old_producer_state)) |
293 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); | 321 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); |
294 return rv; | 322 return rv; |
295 } | 323 } |
296 | 324 |
297 MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes, | 325 MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes, |
298 bool all_or_none) { | 326 bool all_or_none) { |
299 base::AutoLock locker(lock_); | 327 base::AutoLock locker(lock_); |
300 DCHECK(has_local_consumer_no_lock()); | 328 DCHECK(has_local_consumer_no_lock()); |
301 | 329 |
302 if (consumer_in_two_phase_read_no_lock()) | 330 if (consumer_in_two_phase_read_no_lock()) |
303 return MOJO_RESULT_BUSY; | 331 return MOJO_RESULT_BUSY; |
304 | 332 |
305 uint32_t max_num_bytes_to_discard = num_bytes.Get(); | 333 uint32_t max_num_bytes_to_discard = num_bytes.Get(); |
306 if (max_num_bytes_to_discard % element_num_bytes_ != 0) | 334 if (max_num_bytes_to_discard % element_num_bytes_ != 0) |
307 return MOJO_RESULT_INVALID_ARGUMENT; | 335 return MOJO_RESULT_INVALID_ARGUMENT; |
308 | 336 |
309 if (max_num_bytes_to_discard == 0) | 337 if (max_num_bytes_to_discard == 0) |
310 return MOJO_RESULT_OK; // Nothing to do. | 338 return MOJO_RESULT_OK; // Nothing to do. |
311 | 339 |
312 uint32_t min_num_bytes_to_discard = | 340 uint32_t min_num_bytes_to_discard = |
313 all_or_none ? max_num_bytes_to_discard : 0; | 341 all_or_none ? max_num_bytes_to_discard : 0; |
314 | 342 |
315 HandleSignalsState old_producer_state = | 343 HandleSignalsState old_producer_state = |
316 ProducerGetHandleSignalsStateImplNoLock(); | 344 impl_->ProducerGetHandleSignalsState(); |
317 MojoResult rv = ConsumerDiscardDataImplNoLock( | 345 MojoResult rv = impl_->ConsumerDiscardData( |
318 num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard); | 346 num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard); |
319 HandleSignalsState new_producer_state = | 347 HandleSignalsState new_producer_state = |
320 ProducerGetHandleSignalsStateImplNoLock(); | 348 impl_->ProducerGetHandleSignalsState(); |
321 if (!new_producer_state.equals(old_producer_state)) | 349 if (!new_producer_state.equals(old_producer_state)) |
322 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); | 350 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); |
323 return rv; | 351 return rv; |
324 } | 352 } |
325 | 353 |
326 MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) { | 354 MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) { |
327 base::AutoLock locker(lock_); | 355 base::AutoLock locker(lock_); |
328 DCHECK(has_local_consumer_no_lock()); | 356 DCHECK(has_local_consumer_no_lock()); |
329 | 357 |
330 if (consumer_in_two_phase_read_no_lock()) | 358 if (consumer_in_two_phase_read_no_lock()) |
331 return MOJO_RESULT_BUSY; | 359 return MOJO_RESULT_BUSY; |
332 | 360 |
333 // Note: Don't need to validate |*num_bytes| for query. | 361 // Note: Don't need to validate |*num_bytes| for query. |
334 return ConsumerQueryDataImplNoLock(num_bytes); | 362 return impl_->ConsumerQueryData(num_bytes); |
335 } | 363 } |
336 | 364 |
337 MojoResult DataPipe::ConsumerBeginReadData( | 365 MojoResult DataPipe::ConsumerBeginReadData( |
338 UserPointer<const void*> buffer, | 366 UserPointer<const void*> buffer, |
339 UserPointer<uint32_t> buffer_num_bytes, | 367 UserPointer<uint32_t> buffer_num_bytes, |
340 bool all_or_none) { | 368 bool all_or_none) { |
341 base::AutoLock locker(lock_); | 369 base::AutoLock locker(lock_); |
342 DCHECK(has_local_consumer_no_lock()); | 370 DCHECK(has_local_consumer_no_lock()); |
343 | 371 |
344 if (consumer_in_two_phase_read_no_lock()) | 372 if (consumer_in_two_phase_read_no_lock()) |
345 return MOJO_RESULT_BUSY; | 373 return MOJO_RESULT_BUSY; |
346 | 374 |
347 uint32_t min_num_bytes_to_read = 0; | 375 uint32_t min_num_bytes_to_read = 0; |
348 if (all_or_none) { | 376 if (all_or_none) { |
349 min_num_bytes_to_read = buffer_num_bytes.Get(); | 377 min_num_bytes_to_read = buffer_num_bytes.Get(); |
350 if (min_num_bytes_to_read % element_num_bytes_ != 0) | 378 if (min_num_bytes_to_read % element_num_bytes_ != 0) |
351 return MOJO_RESULT_INVALID_ARGUMENT; | 379 return MOJO_RESULT_INVALID_ARGUMENT; |
352 } | 380 } |
353 | 381 |
354 MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes, | 382 MojoResult rv = impl_->ConsumerBeginReadData(buffer, buffer_num_bytes, |
355 min_num_bytes_to_read); | 383 min_num_bytes_to_read); |
356 if (rv != MOJO_RESULT_OK) | 384 if (rv != MOJO_RESULT_OK) |
357 return rv; | 385 return rv; |
358 DCHECK(consumer_in_two_phase_read_no_lock()); | 386 DCHECK(consumer_in_two_phase_read_no_lock()); |
359 return MOJO_RESULT_OK; | 387 return MOJO_RESULT_OK; |
360 } | 388 } |
361 | 389 |
362 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { | 390 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { |
363 base::AutoLock locker(lock_); | 391 base::AutoLock locker(lock_); |
364 DCHECK(has_local_consumer_no_lock()); | 392 DCHECK(has_local_consumer_no_lock()); |
365 | 393 |
366 if (!consumer_in_two_phase_read_no_lock()) | 394 if (!consumer_in_two_phase_read_no_lock()) |
367 return MOJO_RESULT_FAILED_PRECONDITION; | 395 return MOJO_RESULT_FAILED_PRECONDITION; |
368 | 396 |
369 HandleSignalsState old_producer_state = | 397 HandleSignalsState old_producer_state = |
370 ProducerGetHandleSignalsStateImplNoLock(); | 398 impl_->ProducerGetHandleSignalsState(); |
371 MojoResult rv; | 399 MojoResult rv; |
372 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ || | 400 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ || |
373 num_bytes_read % element_num_bytes_ != 0) { | 401 num_bytes_read % element_num_bytes_ != 0) { |
374 rv = MOJO_RESULT_INVALID_ARGUMENT; | 402 rv = MOJO_RESULT_INVALID_ARGUMENT; |
375 consumer_two_phase_max_num_bytes_read_ = 0; | 403 consumer_two_phase_max_num_bytes_read_ = 0; |
376 } else { | 404 } else { |
377 rv = ConsumerEndReadDataImplNoLock(num_bytes_read); | 405 rv = impl_->ConsumerEndReadData(num_bytes_read); |
378 } | 406 } |
379 // Two-phase read ended even on failure. | 407 // Two-phase read ended even on failure. |
380 DCHECK(!consumer_in_two_phase_read_no_lock()); | 408 DCHECK(!consumer_in_two_phase_read_no_lock()); |
381 // If we're now readable, we *became* readable (since we weren't readable | 409 // If we're now readable, we *became* readable (since we weren't readable |
382 // during the two-phase read), so awake consumer awakables. | 410 // during the two-phase read), so awake consumer awakables. |
383 HandleSignalsState new_consumer_state = | 411 HandleSignalsState new_consumer_state = |
384 ConsumerGetHandleSignalsStateImplNoLock(); | 412 impl_->ConsumerGetHandleSignalsState(); |
385 if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE)) | 413 if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE)) |
386 AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); | 414 AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); |
387 HandleSignalsState new_producer_state = | 415 HandleSignalsState new_producer_state = |
388 ProducerGetHandleSignalsStateImplNoLock(); | 416 impl_->ProducerGetHandleSignalsState(); |
389 if (!new_producer_state.equals(old_producer_state)) | 417 if (!new_producer_state.equals(old_producer_state)) |
390 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); | 418 AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); |
391 return rv; | 419 return rv; |
392 } | 420 } |
393 | 421 |
394 HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() { | 422 HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() { |
395 base::AutoLock locker(lock_); | 423 base::AutoLock locker(lock_); |
396 DCHECK(has_local_consumer_no_lock()); | 424 DCHECK(has_local_consumer_no_lock()); |
397 return ConsumerGetHandleSignalsStateImplNoLock(); | 425 return impl_->ConsumerGetHandleSignalsState(); |
398 } | 426 } |
399 | 427 |
400 MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable, | 428 MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable, |
401 MojoHandleSignals signals, | 429 MojoHandleSignals signals, |
402 uint32_t context, | 430 uint32_t context, |
403 HandleSignalsState* signals_state) { | 431 HandleSignalsState* signals_state) { |
404 base::AutoLock locker(lock_); | 432 base::AutoLock locker(lock_); |
405 DCHECK(has_local_consumer_no_lock()); | 433 DCHECK(has_local_consumer_no_lock()); |
406 | 434 |
407 HandleSignalsState consumer_state = ConsumerGetHandleSignalsStateImplNoLock(); | 435 HandleSignalsState consumer_state = impl_->ConsumerGetHandleSignalsState(); |
408 if (consumer_state.satisfies(signals)) { | 436 if (consumer_state.satisfies(signals)) { |
409 if (signals_state) | 437 if (signals_state) |
410 *signals_state = consumer_state; | 438 *signals_state = consumer_state; |
411 return MOJO_RESULT_ALREADY_EXISTS; | 439 return MOJO_RESULT_ALREADY_EXISTS; |
412 } | 440 } |
413 if (!consumer_state.can_satisfy(signals)) { | 441 if (!consumer_state.can_satisfy(signals)) { |
414 if (signals_state) | 442 if (signals_state) |
415 *signals_state = consumer_state; | 443 *signals_state = consumer_state; |
416 return MOJO_RESULT_FAILED_PRECONDITION; | 444 return MOJO_RESULT_FAILED_PRECONDITION; |
417 } | 445 } |
418 | 446 |
419 consumer_awakable_list_->Add(awakable, signals, context); | 447 consumer_awakable_list_->Add(awakable, signals, context); |
420 return MOJO_RESULT_OK; | 448 return MOJO_RESULT_OK; |
421 } | 449 } |
422 | 450 |
423 void DataPipe::ConsumerRemoveAwakable(Awakable* awakable, | 451 void DataPipe::ConsumerRemoveAwakable(Awakable* awakable, |
424 HandleSignalsState* signals_state) { | 452 HandleSignalsState* signals_state) { |
425 base::AutoLock locker(lock_); | 453 base::AutoLock locker(lock_); |
426 DCHECK(has_local_consumer_no_lock()); | 454 DCHECK(has_local_consumer_no_lock()); |
427 consumer_awakable_list_->Remove(awakable); | 455 consumer_awakable_list_->Remove(awakable); |
428 if (signals_state) | 456 if (signals_state) |
429 *signals_state = ConsumerGetHandleSignalsStateImplNoLock(); | 457 *signals_state = impl_->ConsumerGetHandleSignalsState(); |
430 } | 458 } |
431 | 459 |
432 void DataPipe::ConsumerStartSerialize(Channel* channel, | 460 void DataPipe::ConsumerStartSerialize(Channel* channel, |
433 size_t* max_size, | 461 size_t* max_size, |
434 size_t* max_platform_handles) { | 462 size_t* max_platform_handles) { |
435 base::AutoLock locker(lock_); | 463 base::AutoLock locker(lock_); |
436 DCHECK(has_local_consumer_no_lock()); | 464 DCHECK(has_local_consumer_no_lock()); |
437 ConsumerStartSerializeImplNoLock(channel, max_size, max_platform_handles); | 465 impl_->ConsumerStartSerialize(channel, max_size, max_platform_handles); |
438 } | 466 } |
439 | 467 |
440 bool DataPipe::ConsumerEndSerialize( | 468 bool DataPipe::ConsumerEndSerialize( |
441 Channel* channel, | 469 Channel* channel, |
442 void* destination, | 470 void* destination, |
443 size_t* actual_size, | 471 size_t* actual_size, |
444 embedder::PlatformHandleVector* platform_handles) { | 472 embedder::PlatformHandleVector* platform_handles) { |
445 base::AutoLock locker(lock_); | 473 base::AutoLock locker(lock_); |
446 DCHECK(has_local_consumer_no_lock()); | 474 DCHECK(has_local_consumer_no_lock()); |
447 return ConsumerEndSerializeImplNoLock(channel, destination, actual_size, | 475 return impl_->ConsumerEndSerialize(channel, destination, actual_size, |
448 platform_handles); | 476 platform_handles); |
449 } | 477 } |
450 | 478 |
451 bool DataPipe::ConsumerIsBusy() const { | 479 bool DataPipe::ConsumerIsBusy() const { |
452 base::AutoLock locker(lock_); | 480 base::AutoLock locker(lock_); |
453 return consumer_in_two_phase_read_no_lock(); | 481 return consumer_in_two_phase_read_no_lock(); |
454 } | 482 } |
455 | 483 |
456 DataPipe::DataPipe(bool has_local_producer, | |
457 bool has_local_consumer, | |
458 const MojoCreateDataPipeOptions& validated_options) | |
459 : may_discard_((validated_options.flags & | |
460 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)), | |
461 element_num_bytes_(validated_options.element_num_bytes), | |
462 capacity_num_bytes_(validated_options.capacity_num_bytes), | |
463 producer_open_(true), | |
464 consumer_open_(true), | |
465 producer_awakable_list_(has_local_producer ? new AwakableList() | |
466 : nullptr), | |
467 consumer_awakable_list_(has_local_consumer ? new AwakableList() | |
468 : nullptr), | |
469 producer_two_phase_max_num_bytes_written_(0), | |
470 consumer_two_phase_max_num_bytes_read_(0) { | |
471 // Check that the passed in options actually are validated. | |
472 MojoCreateDataPipeOptions unused = {0}; | |
473 DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused), | |
474 MOJO_RESULT_OK); | |
475 } | |
476 | |
477 DataPipe::~DataPipe() { | 484 DataPipe::~DataPipe() { |
478 DCHECK(!producer_open_); | 485 DCHECK(!producer_open_); |
479 DCHECK(!consumer_open_); | 486 DCHECK(!consumer_open_); |
480 DCHECK(!producer_awakable_list_); | 487 DCHECK(!producer_awakable_list_); |
481 DCHECK(!consumer_awakable_list_); | 488 DCHECK(!consumer_awakable_list_); |
482 } | 489 } |
483 | 490 |
484 void DataPipe::ProducerCloseNoLock() { | 491 void DataPipe::ProducerCloseNoLock() { |
485 lock_.AssertAcquired(); | 492 lock_.AssertAcquired(); |
486 DCHECK(producer_open_); | 493 DCHECK(producer_open_); |
487 producer_open_ = false; | 494 producer_open_ = false; |
488 DCHECK(has_local_producer_no_lock()); | 495 DCHECK(has_local_producer_no_lock()); |
489 producer_awakable_list_.reset(); | 496 producer_awakable_list_.reset(); |
490 // Not a bug, except possibly in "user" code. | 497 // Not a bug, except possibly in "user" code. |
491 DVLOG_IF(2, producer_in_two_phase_write_no_lock()) | 498 DVLOG_IF(2, producer_in_two_phase_write_no_lock()) |
492 << "Producer closed with active two-phase write"; | 499 << "Producer closed with active two-phase write"; |
493 producer_two_phase_max_num_bytes_written_ = 0; | 500 producer_two_phase_max_num_bytes_written_ = 0; |
494 ProducerCloseImplNoLock(); | 501 impl_->ProducerClose(); |
495 AwakeConsumerAwakablesForStateChangeNoLock( | 502 AwakeConsumerAwakablesForStateChangeNoLock( |
496 ConsumerGetHandleSignalsStateImplNoLock()); | 503 impl_->ConsumerGetHandleSignalsState()); |
497 } | 504 } |
498 | 505 |
499 void DataPipe::ConsumerCloseNoLock() { | 506 void DataPipe::ConsumerCloseNoLock() { |
500 lock_.AssertAcquired(); | 507 lock_.AssertAcquired(); |
501 DCHECK(consumer_open_); | 508 DCHECK(consumer_open_); |
502 consumer_open_ = false; | 509 consumer_open_ = false; |
503 DCHECK(has_local_consumer_no_lock()); | 510 DCHECK(has_local_consumer_no_lock()); |
504 consumer_awakable_list_.reset(); | 511 consumer_awakable_list_.reset(); |
505 // Not a bug, except possibly in "user" code. | 512 // Not a bug, except possibly in "user" code. |
506 DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) | 513 DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) |
507 << "Consumer closed with active two-phase read"; | 514 << "Consumer closed with active two-phase read"; |
508 consumer_two_phase_max_num_bytes_read_ = 0; | 515 consumer_two_phase_max_num_bytes_read_ = 0; |
509 ConsumerCloseImplNoLock(); | 516 impl_->ConsumerClose(); |
510 AwakeProducerAwakablesForStateChangeNoLock( | 517 AwakeProducerAwakablesForStateChangeNoLock( |
511 ProducerGetHandleSignalsStateImplNoLock()); | 518 impl_->ProducerGetHandleSignalsState()); |
512 } | 519 } |
513 | 520 |
514 void DataPipe::AwakeProducerAwakablesForStateChangeNoLock( | 521 void DataPipe::AwakeProducerAwakablesForStateChangeNoLock( |
515 const HandleSignalsState& new_producer_state) { | 522 const HandleSignalsState& new_producer_state) { |
516 lock_.AssertAcquired(); | 523 lock_.AssertAcquired(); |
517 if (!has_local_producer_no_lock()) | 524 if (!has_local_producer_no_lock()) |
518 return; | 525 return; |
519 producer_awakable_list_->AwakeForStateChange(new_producer_state); | 526 producer_awakable_list_->AwakeForStateChange(new_producer_state); |
520 } | 527 } |
521 | 528 |
522 void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock( | 529 void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock( |
523 const HandleSignalsState& new_consumer_state) { | 530 const HandleSignalsState& new_consumer_state) { |
524 lock_.AssertAcquired(); | 531 lock_.AssertAcquired(); |
525 if (!has_local_consumer_no_lock()) | 532 if (!has_local_consumer_no_lock()) |
526 return; | 533 return; |
527 consumer_awakable_list_->AwakeForStateChange(new_consumer_state); | 534 consumer_awakable_list_->AwakeForStateChange(new_consumer_state); |
528 } | 535 } |
529 | 536 |
530 } // namespace system | 537 } // namespace system |
531 } // namespace mojo | 538 } // namespace mojo |
OLD | NEW |