Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: mojo/system/data_pipe.cc

Issue 621153003: Move mojo edk into mojo/edk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix checkdeps Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/system/data_pipe.h ('k') | mojo/system/data_pipe_consumer_dispatcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "mojo/system/data_pipe.h"
6
7 #include <string.h>
8
9 #include <algorithm>
10 #include <limits>
11
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "mojo/system/constants.h"
15 #include "mojo/system/memory.h"
16 #include "mojo/system/options_validation.h"
17 #include "mojo/system/waiter_list.h"
18
19 namespace mojo {
20 namespace system {
21
22 // static
23 const MojoCreateDataPipeOptions DataPipe::kDefaultCreateOptions = {
24 static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)),
25 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1u,
26 static_cast<uint32_t>(kDefaultDataPipeCapacityBytes)};
27
28 // static
29 MojoResult DataPipe::ValidateCreateOptions(
30 UserPointer<const MojoCreateDataPipeOptions> in_options,
31 MojoCreateDataPipeOptions* out_options) {
32 const MojoCreateDataPipeOptionsFlags kKnownFlags =
33 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD;
34
35 *out_options = kDefaultCreateOptions;
36 if (in_options.IsNull())
37 return MOJO_RESULT_OK;
38
39 UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options);
40 if (!reader.is_valid())
41 return MOJO_RESULT_INVALID_ARGUMENT;
42
43 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader))
44 return MOJO_RESULT_OK;
45 if ((reader.options().flags & ~kKnownFlags))
46 return MOJO_RESULT_UNIMPLEMENTED;
47 out_options->flags = reader.options().flags;
48
49 // Checks for fields beyond |flags|:
50
51 if (!OPTIONS_STRUCT_HAS_MEMBER(
52 MojoCreateDataPipeOptions, element_num_bytes, reader))
53 return MOJO_RESULT_OK;
54 if (reader.options().element_num_bytes == 0)
55 return MOJO_RESULT_INVALID_ARGUMENT;
56 out_options->element_num_bytes = reader.options().element_num_bytes;
57
58 if (!OPTIONS_STRUCT_HAS_MEMBER(
59 MojoCreateDataPipeOptions, capacity_num_bytes, reader) ||
60 reader.options().capacity_num_bytes == 0) {
61 // Round the default capacity down to a multiple of the element size (but at
62 // least one element).
63 out_options->capacity_num_bytes =
64 std::max(static_cast<uint32_t>(kDefaultDataPipeCapacityBytes -
65 (kDefaultDataPipeCapacityBytes %
66 out_options->element_num_bytes)),
67 out_options->element_num_bytes);
68 return MOJO_RESULT_OK;
69 }
70 if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0)
71 return MOJO_RESULT_INVALID_ARGUMENT;
72 if (reader.options().capacity_num_bytes > kMaxDataPipeCapacityBytes)
73 return MOJO_RESULT_RESOURCE_EXHAUSTED;
74 out_options->capacity_num_bytes = reader.options().capacity_num_bytes;
75
76 return MOJO_RESULT_OK;
77 }
78
79 void DataPipe::ProducerCancelAllWaiters() {
80 base::AutoLock locker(lock_);
81 DCHECK(has_local_producer_no_lock());
82 producer_waiter_list_->CancelAllWaiters();
83 }
84
85 void DataPipe::ProducerClose() {
86 base::AutoLock locker(lock_);
87 DCHECK(producer_open_);
88 producer_open_ = false;
89 DCHECK(has_local_producer_no_lock());
90 producer_waiter_list_.reset();
91 // Not a bug, except possibly in "user" code.
92 DVLOG_IF(2, producer_in_two_phase_write_no_lock())
93 << "Producer closed with active two-phase write";
94 producer_two_phase_max_num_bytes_written_ = 0;
95 ProducerCloseImplNoLock();
96 AwakeConsumerWaitersForStateChangeNoLock(
97 ConsumerGetHandleSignalsStateImplNoLock());
98 }
99
100 MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements,
101 UserPointer<uint32_t> num_bytes,
102 bool all_or_none) {
103 base::AutoLock locker(lock_);
104 DCHECK(has_local_producer_no_lock());
105
106 if (producer_in_two_phase_write_no_lock())
107 return MOJO_RESULT_BUSY;
108 if (!consumer_open_no_lock())
109 return MOJO_RESULT_FAILED_PRECONDITION;
110
111 // Returning "busy" takes priority over "invalid argument".
112 uint32_t max_num_bytes_to_write = num_bytes.Get();
113 if (max_num_bytes_to_write % element_num_bytes_ != 0)
114 return MOJO_RESULT_INVALID_ARGUMENT;
115
116 if (max_num_bytes_to_write == 0)
117 return MOJO_RESULT_OK; // Nothing to do.
118
119 uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0;
120
121 HandleSignalsState old_consumer_state =
122 ConsumerGetHandleSignalsStateImplNoLock();
123 MojoResult rv = ProducerWriteDataImplNoLock(
124 elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write);
125 HandleSignalsState new_consumer_state =
126 ConsumerGetHandleSignalsStateImplNoLock();
127 if (!new_consumer_state.equals(old_consumer_state))
128 AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state);
129 return rv;
130 }
131
132 MojoResult DataPipe::ProducerBeginWriteData(
133 UserPointer<void*> buffer,
134 UserPointer<uint32_t> buffer_num_bytes,
135 bool all_or_none) {
136 base::AutoLock locker(lock_);
137 DCHECK(has_local_producer_no_lock());
138
139 if (producer_in_two_phase_write_no_lock())
140 return MOJO_RESULT_BUSY;
141 if (!consumer_open_no_lock())
142 return MOJO_RESULT_FAILED_PRECONDITION;
143
144 uint32_t min_num_bytes_to_write = 0;
145 if (all_or_none) {
146 min_num_bytes_to_write = buffer_num_bytes.Get();
147 if (min_num_bytes_to_write % element_num_bytes_ != 0)
148 return MOJO_RESULT_INVALID_ARGUMENT;
149 }
150
151 MojoResult rv = ProducerBeginWriteDataImplNoLock(
152 buffer, buffer_num_bytes, min_num_bytes_to_write);
153 if (rv != MOJO_RESULT_OK)
154 return rv;
155 // Note: No need to awake producer waiters, even though we're going from
156 // writable to non-writable (since you can't wait on non-writability).
157 // Similarly, though this may have discarded data (in "may discard" mode),
158 // making it non-readable, there's still no need to awake consumer waiters.
159 DCHECK(producer_in_two_phase_write_no_lock());
160 return MOJO_RESULT_OK;
161 }
162
163 MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
164 base::AutoLock locker(lock_);
165 DCHECK(has_local_producer_no_lock());
166
167 if (!producer_in_two_phase_write_no_lock())
168 return MOJO_RESULT_FAILED_PRECONDITION;
169 // Note: Allow successful completion of the two-phase write even if the
170 // consumer has been closed.
171
172 HandleSignalsState old_consumer_state =
173 ConsumerGetHandleSignalsStateImplNoLock();
174 MojoResult rv;
175 if (num_bytes_written > producer_two_phase_max_num_bytes_written_ ||
176 num_bytes_written % element_num_bytes_ != 0) {
177 rv = MOJO_RESULT_INVALID_ARGUMENT;
178 producer_two_phase_max_num_bytes_written_ = 0;
179 } else {
180 rv = ProducerEndWriteDataImplNoLock(num_bytes_written);
181 }
182 // Two-phase write ended even on failure.
183 DCHECK(!producer_in_two_phase_write_no_lock());
184 // If we're now writable, we *became* writable (since we weren't writable
185 // during the two-phase write), so awake producer waiters.
186 HandleSignalsState new_producer_state =
187 ProducerGetHandleSignalsStateImplNoLock();
188 if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE))
189 AwakeProducerWaitersForStateChangeNoLock(new_producer_state);
190 HandleSignalsState new_consumer_state =
191 ConsumerGetHandleSignalsStateImplNoLock();
192 if (!new_consumer_state.equals(old_consumer_state))
193 AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state);
194 return rv;
195 }
196
197 HandleSignalsState DataPipe::ProducerGetHandleSignalsState() {
198 base::AutoLock locker(lock_);
199 DCHECK(has_local_producer_no_lock());
200 return ProducerGetHandleSignalsStateImplNoLock();
201 }
202
203 MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter,
204 MojoHandleSignals signals,
205 uint32_t context,
206 HandleSignalsState* signals_state) {
207 base::AutoLock locker(lock_);
208 DCHECK(has_local_producer_no_lock());
209
210 HandleSignalsState producer_state = ProducerGetHandleSignalsStateImplNoLock();
211 if (producer_state.satisfies(signals)) {
212 if (signals_state)
213 *signals_state = producer_state;
214 return MOJO_RESULT_ALREADY_EXISTS;
215 }
216 if (!producer_state.can_satisfy(signals)) {
217 if (signals_state)
218 *signals_state = producer_state;
219 return MOJO_RESULT_FAILED_PRECONDITION;
220 }
221
222 producer_waiter_list_->AddWaiter(waiter, signals, context);
223 return MOJO_RESULT_OK;
224 }
225
226 void DataPipe::ProducerRemoveWaiter(Waiter* waiter,
227 HandleSignalsState* signals_state) {
228 base::AutoLock locker(lock_);
229 DCHECK(has_local_producer_no_lock());
230 producer_waiter_list_->RemoveWaiter(waiter);
231 if (signals_state)
232 *signals_state = ProducerGetHandleSignalsStateImplNoLock();
233 }
234
235 bool DataPipe::ProducerIsBusy() const {
236 base::AutoLock locker(lock_);
237 return producer_in_two_phase_write_no_lock();
238 }
239
240 void DataPipe::ConsumerCancelAllWaiters() {
241 base::AutoLock locker(lock_);
242 DCHECK(has_local_consumer_no_lock());
243 consumer_waiter_list_->CancelAllWaiters();
244 }
245
246 void DataPipe::ConsumerClose() {
247 base::AutoLock locker(lock_);
248 DCHECK(consumer_open_);
249 consumer_open_ = false;
250 DCHECK(has_local_consumer_no_lock());
251 consumer_waiter_list_.reset();
252 // Not a bug, except possibly in "user" code.
253 DVLOG_IF(2, consumer_in_two_phase_read_no_lock())
254 << "Consumer closed with active two-phase read";
255 consumer_two_phase_max_num_bytes_read_ = 0;
256 ConsumerCloseImplNoLock();
257 AwakeProducerWaitersForStateChangeNoLock(
258 ProducerGetHandleSignalsStateImplNoLock());
259 }
260
261 MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements,
262 UserPointer<uint32_t> num_bytes,
263 bool all_or_none) {
264 base::AutoLock locker(lock_);
265 DCHECK(has_local_consumer_no_lock());
266
267 if (consumer_in_two_phase_read_no_lock())
268 return MOJO_RESULT_BUSY;
269
270 uint32_t max_num_bytes_to_read = num_bytes.Get();
271 if (max_num_bytes_to_read % element_num_bytes_ != 0)
272 return MOJO_RESULT_INVALID_ARGUMENT;
273
274 if (max_num_bytes_to_read == 0)
275 return MOJO_RESULT_OK; // Nothing to do.
276
277 uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0;
278
279 HandleSignalsState old_producer_state =
280 ProducerGetHandleSignalsStateImplNoLock();
281 MojoResult rv = ConsumerReadDataImplNoLock(
282 elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read);
283 HandleSignalsState new_producer_state =
284 ProducerGetHandleSignalsStateImplNoLock();
285 if (!new_producer_state.equals(old_producer_state))
286 AwakeProducerWaitersForStateChangeNoLock(new_producer_state);
287 return rv;
288 }
289
290 MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
291 bool all_or_none) {
292 base::AutoLock locker(lock_);
293 DCHECK(has_local_consumer_no_lock());
294
295 if (consumer_in_two_phase_read_no_lock())
296 return MOJO_RESULT_BUSY;
297
298 uint32_t max_num_bytes_to_discard = num_bytes.Get();
299 if (max_num_bytes_to_discard % element_num_bytes_ != 0)
300 return MOJO_RESULT_INVALID_ARGUMENT;
301
302 if (max_num_bytes_to_discard == 0)
303 return MOJO_RESULT_OK; // Nothing to do.
304
305 uint32_t min_num_bytes_to_discard =
306 all_or_none ? max_num_bytes_to_discard : 0;
307
308 HandleSignalsState old_producer_state =
309 ProducerGetHandleSignalsStateImplNoLock();
310 MojoResult rv = ConsumerDiscardDataImplNoLock(
311 num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard);
312 HandleSignalsState new_producer_state =
313 ProducerGetHandleSignalsStateImplNoLock();
314 if (!new_producer_state.equals(old_producer_state))
315 AwakeProducerWaitersForStateChangeNoLock(new_producer_state);
316 return rv;
317 }
318
319 MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) {
320 base::AutoLock locker(lock_);
321 DCHECK(has_local_consumer_no_lock());
322
323 if (consumer_in_two_phase_read_no_lock())
324 return MOJO_RESULT_BUSY;
325
326 // Note: Don't need to validate |*num_bytes| for query.
327 return ConsumerQueryDataImplNoLock(num_bytes);
328 }
329
330 MojoResult DataPipe::ConsumerBeginReadData(
331 UserPointer<const void*> buffer,
332 UserPointer<uint32_t> buffer_num_bytes,
333 bool all_or_none) {
334 base::AutoLock locker(lock_);
335 DCHECK(has_local_consumer_no_lock());
336
337 if (consumer_in_two_phase_read_no_lock())
338 return MOJO_RESULT_BUSY;
339
340 uint32_t min_num_bytes_to_read = 0;
341 if (all_or_none) {
342 min_num_bytes_to_read = buffer_num_bytes.Get();
343 if (min_num_bytes_to_read % element_num_bytes_ != 0)
344 return MOJO_RESULT_INVALID_ARGUMENT;
345 }
346
347 MojoResult rv = ConsumerBeginReadDataImplNoLock(
348 buffer, buffer_num_bytes, min_num_bytes_to_read);
349 if (rv != MOJO_RESULT_OK)
350 return rv;
351 DCHECK(consumer_in_two_phase_read_no_lock());
352 return MOJO_RESULT_OK;
353 }
354
355 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
356 base::AutoLock locker(lock_);
357 DCHECK(has_local_consumer_no_lock());
358
359 if (!consumer_in_two_phase_read_no_lock())
360 return MOJO_RESULT_FAILED_PRECONDITION;
361
362 HandleSignalsState old_producer_state =
363 ProducerGetHandleSignalsStateImplNoLock();
364 MojoResult rv;
365 if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ ||
366 num_bytes_read % element_num_bytes_ != 0) {
367 rv = MOJO_RESULT_INVALID_ARGUMENT;
368 consumer_two_phase_max_num_bytes_read_ = 0;
369 } else {
370 rv = ConsumerEndReadDataImplNoLock(num_bytes_read);
371 }
372 // Two-phase read ended even on failure.
373 DCHECK(!consumer_in_two_phase_read_no_lock());
374 // If we're now readable, we *became* readable (since we weren't readable
375 // during the two-phase read), so awake consumer waiters.
376 HandleSignalsState new_consumer_state =
377 ConsumerGetHandleSignalsStateImplNoLock();
378 if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE))
379 AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state);
380 HandleSignalsState new_producer_state =
381 ProducerGetHandleSignalsStateImplNoLock();
382 if (!new_producer_state.equals(old_producer_state))
383 AwakeProducerWaitersForStateChangeNoLock(new_producer_state);
384 return rv;
385 }
386
387 HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() {
388 base::AutoLock locker(lock_);
389 DCHECK(has_local_consumer_no_lock());
390 return ConsumerGetHandleSignalsStateImplNoLock();
391 }
392
393 MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter,
394 MojoHandleSignals signals,
395 uint32_t context,
396 HandleSignalsState* signals_state) {
397 base::AutoLock locker(lock_);
398 DCHECK(has_local_consumer_no_lock());
399
400 HandleSignalsState consumer_state = ConsumerGetHandleSignalsStateImplNoLock();
401 if (consumer_state.satisfies(signals)) {
402 if (signals_state)
403 *signals_state = consumer_state;
404 return MOJO_RESULT_ALREADY_EXISTS;
405 }
406 if (!consumer_state.can_satisfy(signals)) {
407 if (signals_state)
408 *signals_state = consumer_state;
409 return MOJO_RESULT_FAILED_PRECONDITION;
410 }
411
412 consumer_waiter_list_->AddWaiter(waiter, signals, context);
413 return MOJO_RESULT_OK;
414 }
415
416 void DataPipe::ConsumerRemoveWaiter(Waiter* waiter,
417 HandleSignalsState* signals_state) {
418 base::AutoLock locker(lock_);
419 DCHECK(has_local_consumer_no_lock());
420 consumer_waiter_list_->RemoveWaiter(waiter);
421 if (signals_state)
422 *signals_state = ConsumerGetHandleSignalsStateImplNoLock();
423 }
424
425 bool DataPipe::ConsumerIsBusy() const {
426 base::AutoLock locker(lock_);
427 return consumer_in_two_phase_read_no_lock();
428 }
429
430 DataPipe::DataPipe(bool has_local_producer,
431 bool has_local_consumer,
432 const MojoCreateDataPipeOptions& validated_options)
433 : may_discard_((validated_options.flags &
434 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)),
435 element_num_bytes_(validated_options.element_num_bytes),
436 capacity_num_bytes_(validated_options.capacity_num_bytes),
437 producer_open_(true),
438 consumer_open_(true),
439 producer_waiter_list_(has_local_producer ? new WaiterList() : nullptr),
440 consumer_waiter_list_(has_local_consumer ? new WaiterList() : nullptr),
441 producer_two_phase_max_num_bytes_written_(0),
442 consumer_two_phase_max_num_bytes_read_(0) {
443 // Check that the passed in options actually are validated.
444 MojoCreateDataPipeOptions unused ALLOW_UNUSED = {0};
445 DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused),
446 MOJO_RESULT_OK);
447 }
448
449 DataPipe::~DataPipe() {
450 DCHECK(!producer_open_);
451 DCHECK(!consumer_open_);
452 DCHECK(!producer_waiter_list_);
453 DCHECK(!consumer_waiter_list_);
454 }
455
456 void DataPipe::AwakeProducerWaitersForStateChangeNoLock(
457 const HandleSignalsState& new_producer_state) {
458 lock_.AssertAcquired();
459 if (!has_local_producer_no_lock())
460 return;
461 producer_waiter_list_->AwakeWaitersForStateChange(new_producer_state);
462 }
463
464 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock(
465 const HandleSignalsState& new_consumer_state) {
466 lock_.AssertAcquired();
467 if (!has_local_consumer_no_lock())
468 return;
469 consumer_waiter_list_->AwakeWaitersForStateChange(new_consumer_state);
470 }
471
472 } // namespace system
473 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/system/data_pipe.h ('k') | mojo/system/data_pipe_consumer_dispatcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698