| Index: mojo/edk/system/data_pipe.cc
|
| diff --git a/mojo/edk/system/data_pipe.cc b/mojo/edk/system/data_pipe.cc
|
| deleted file mode 100644
|
| index 2f433bdf9a5cd9eb91638a4647868124d1ca40df..0000000000000000000000000000000000000000
|
| --- a/mojo/edk/system/data_pipe.cc
|
| +++ /dev/null
|
| @@ -1,483 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "mojo/edk/system/data_pipe.h"
|
| -
|
| -#include <string.h>
|
| -
|
| -#include <algorithm>
|
| -#include <limits>
|
| -
|
| -#include "base/logging.h"
|
| -#include "mojo/edk/system/awakable_list.h"
|
| -#include "mojo/edk/system/configuration.h"
|
| -#include "mojo/edk/system/memory.h"
|
| -#include "mojo/edk/system/options_validation.h"
|
| -
|
| -namespace mojo {
|
| -namespace system {
|
| -
|
| -// static
|
| -MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() {
|
| - MojoCreateDataPipeOptions result = {
|
| - static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)),
|
| - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
|
| - 1u,
|
| - static_cast<uint32_t>(
|
| - GetConfiguration().default_data_pipe_capacity_bytes)};
|
| - return result;
|
| -}
|
| -
|
| -// static
|
| -MojoResult DataPipe::ValidateCreateOptions(
|
| - UserPointer<const MojoCreateDataPipeOptions> in_options,
|
| - MojoCreateDataPipeOptions* out_options) {
|
| - const MojoCreateDataPipeOptionsFlags kKnownFlags =
|
| - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD;
|
| -
|
| - *out_options = GetDefaultCreateOptions();
|
| - if (in_options.IsNull())
|
| - return MOJO_RESULT_OK;
|
| -
|
| - UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options);
|
| - if (!reader.is_valid())
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| -
|
| - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader))
|
| - return MOJO_RESULT_OK;
|
| - if ((reader.options().flags & ~kKnownFlags))
|
| - return MOJO_RESULT_UNIMPLEMENTED;
|
| - out_options->flags = reader.options().flags;
|
| -
|
| - // Checks for fields beyond |flags|:
|
| -
|
| - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes,
|
| - reader))
|
| - return MOJO_RESULT_OK;
|
| - if (reader.options().element_num_bytes == 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| - out_options->element_num_bytes = reader.options().element_num_bytes;
|
| -
|
| - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes,
|
| - reader) ||
|
| - reader.options().capacity_num_bytes == 0) {
|
| - // Round the default capacity down to a multiple of the element size (but at
|
| - // least one element).
|
| - size_t default_data_pipe_capacity_bytes =
|
| - GetConfiguration().default_data_pipe_capacity_bytes;
|
| - out_options->capacity_num_bytes =
|
| - std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes -
|
| - (default_data_pipe_capacity_bytes %
|
| - out_options->element_num_bytes)),
|
| - out_options->element_num_bytes);
|
| - return MOJO_RESULT_OK;
|
| - }
|
| - if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| - if (reader.options().capacity_num_bytes >
|
| - GetConfiguration().max_data_pipe_capacity_bytes)
|
| - return MOJO_RESULT_RESOURCE_EXHAUSTED;
|
| - out_options->capacity_num_bytes = reader.options().capacity_num_bytes;
|
| -
|
| - return MOJO_RESULT_OK;
|
| -}
|
| -
|
| -void DataPipe::ProducerCancelAllAwakables() {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| - producer_awakable_list_->CancelAll();
|
| -}
|
| -
|
| -void DataPipe::ProducerClose() {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(producer_open_);
|
| - producer_open_ = false;
|
| - DCHECK(has_local_producer_no_lock());
|
| - producer_awakable_list_.reset();
|
| - // Not a bug, except possibly in "user" code.
|
| - DVLOG_IF(2, producer_in_two_phase_write_no_lock())
|
| - << "Producer closed with active two-phase write";
|
| - producer_two_phase_max_num_bytes_written_ = 0;
|
| - ProducerCloseImplNoLock();
|
| - AwakeConsumerAwakablesForStateChangeNoLock(
|
| - ConsumerGetHandleSignalsStateImplNoLock());
|
| -}
|
| -
|
| -MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements,
|
| - UserPointer<uint32_t> num_bytes,
|
| - bool all_or_none) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| -
|
| - if (producer_in_two_phase_write_no_lock())
|
| - return MOJO_RESULT_BUSY;
|
| - if (!consumer_open_no_lock())
|
| - return MOJO_RESULT_FAILED_PRECONDITION;
|
| -
|
| - // Returning "busy" takes priority over "invalid argument".
|
| - uint32_t max_num_bytes_to_write = num_bytes.Get();
|
| - if (max_num_bytes_to_write % element_num_bytes_ != 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| -
|
| - if (max_num_bytes_to_write == 0)
|
| - return MOJO_RESULT_OK; // Nothing to do.
|
| -
|
| - uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0;
|
| -
|
| - HandleSignalsState old_consumer_state =
|
| - ConsumerGetHandleSignalsStateImplNoLock();
|
| - MojoResult rv = ProducerWriteDataImplNoLock(
|
| - elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write);
|
| - HandleSignalsState new_consumer_state =
|
| - ConsumerGetHandleSignalsStateImplNoLock();
|
| - if (!new_consumer_state.equals(old_consumer_state))
|
| - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
|
| - return rv;
|
| -}
|
| -
|
| -MojoResult DataPipe::ProducerBeginWriteData(
|
| - UserPointer<void*> buffer,
|
| - UserPointer<uint32_t> buffer_num_bytes,
|
| - bool all_or_none) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| -
|
| - if (producer_in_two_phase_write_no_lock())
|
| - return MOJO_RESULT_BUSY;
|
| - if (!consumer_open_no_lock())
|
| - return MOJO_RESULT_FAILED_PRECONDITION;
|
| -
|
| - uint32_t min_num_bytes_to_write = 0;
|
| - if (all_or_none) {
|
| - min_num_bytes_to_write = buffer_num_bytes.Get();
|
| - if (min_num_bytes_to_write % element_num_bytes_ != 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| - }
|
| -
|
| - MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes,
|
| - min_num_bytes_to_write);
|
| - if (rv != MOJO_RESULT_OK)
|
| - return rv;
|
| - // Note: No need to awake producer awakables, even though we're going from
|
| - // writable to non-writable (since you can't wait on non-writability).
|
| - // Similarly, though this may have discarded data (in "may discard" mode),
|
| - // making it non-readable, there's still no need to awake consumer awakables.
|
| - DCHECK(producer_in_two_phase_write_no_lock());
|
| - return MOJO_RESULT_OK;
|
| -}
|
| -
|
| -MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| -
|
| - if (!producer_in_two_phase_write_no_lock())
|
| - return MOJO_RESULT_FAILED_PRECONDITION;
|
| - // Note: Allow successful completion of the two-phase write even if the
|
| - // consumer has been closed.
|
| -
|
| - HandleSignalsState old_consumer_state =
|
| - ConsumerGetHandleSignalsStateImplNoLock();
|
| - MojoResult rv;
|
| - if (num_bytes_written > producer_two_phase_max_num_bytes_written_ ||
|
| - num_bytes_written % element_num_bytes_ != 0) {
|
| - rv = MOJO_RESULT_INVALID_ARGUMENT;
|
| - producer_two_phase_max_num_bytes_written_ = 0;
|
| - } else {
|
| - rv = ProducerEndWriteDataImplNoLock(num_bytes_written);
|
| - }
|
| - // Two-phase write ended even on failure.
|
| - DCHECK(!producer_in_two_phase_write_no_lock());
|
| - // If we're now writable, we *became* writable (since we weren't writable
|
| - // during the two-phase write), so awake producer awakables.
|
| - HandleSignalsState new_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE))
|
| - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
|
| - HandleSignalsState new_consumer_state =
|
| - ConsumerGetHandleSignalsStateImplNoLock();
|
| - if (!new_consumer_state.equals(old_consumer_state))
|
| - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
|
| - return rv;
|
| -}
|
| -
|
| -HandleSignalsState DataPipe::ProducerGetHandleSignalsState() {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| - return ProducerGetHandleSignalsStateImplNoLock();
|
| -}
|
| -
|
| -MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable,
|
| - MojoHandleSignals signals,
|
| - uint32_t context,
|
| - HandleSignalsState* signals_state) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| -
|
| - HandleSignalsState producer_state = ProducerGetHandleSignalsStateImplNoLock();
|
| - if (producer_state.satisfies(signals)) {
|
| - if (signals_state)
|
| - *signals_state = producer_state;
|
| - return MOJO_RESULT_ALREADY_EXISTS;
|
| - }
|
| - if (!producer_state.can_satisfy(signals)) {
|
| - if (signals_state)
|
| - *signals_state = producer_state;
|
| - return MOJO_RESULT_FAILED_PRECONDITION;
|
| - }
|
| -
|
| - producer_awakable_list_->Add(awakable, signals, context);
|
| - return MOJO_RESULT_OK;
|
| -}
|
| -
|
| -void DataPipe::ProducerRemoveAwakable(Awakable* awakable,
|
| - HandleSignalsState* signals_state) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_producer_no_lock());
|
| - producer_awakable_list_->Remove(awakable);
|
| - if (signals_state)
|
| - *signals_state = ProducerGetHandleSignalsStateImplNoLock();
|
| -}
|
| -
|
| -bool DataPipe::ProducerIsBusy() const {
|
| - base::AutoLock locker(lock_);
|
| - return producer_in_two_phase_write_no_lock();
|
| -}
|
| -
|
| -void DataPipe::ConsumerCancelAllAwakables() {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| - consumer_awakable_list_->CancelAll();
|
| -}
|
| -
|
| -void DataPipe::ConsumerClose() {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(consumer_open_);
|
| - consumer_open_ = false;
|
| - DCHECK(has_local_consumer_no_lock());
|
| - consumer_awakable_list_.reset();
|
| - // Not a bug, except possibly in "user" code.
|
| - DVLOG_IF(2, consumer_in_two_phase_read_no_lock())
|
| - << "Consumer closed with active two-phase read";
|
| - consumer_two_phase_max_num_bytes_read_ = 0;
|
| - ConsumerCloseImplNoLock();
|
| - AwakeProducerAwakablesForStateChangeNoLock(
|
| - ProducerGetHandleSignalsStateImplNoLock());
|
| -}
|
| -
|
| -MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements,
|
| - UserPointer<uint32_t> num_bytes,
|
| - bool all_or_none,
|
| - bool peek) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| -
|
| - if (consumer_in_two_phase_read_no_lock())
|
| - return MOJO_RESULT_BUSY;
|
| -
|
| - uint32_t max_num_bytes_to_read = num_bytes.Get();
|
| - if (max_num_bytes_to_read % element_num_bytes_ != 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| -
|
| - if (max_num_bytes_to_read == 0)
|
| - return MOJO_RESULT_OK; // Nothing to do.
|
| -
|
| - uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0;
|
| -
|
| - HandleSignalsState old_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - MojoResult rv = ConsumerReadDataImplNoLock(
|
| - elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read, peek);
|
| - HandleSignalsState new_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - if (!new_producer_state.equals(old_producer_state))
|
| - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
|
| - return rv;
|
| -}
|
| -
|
| -MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
|
| - bool all_or_none) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| -
|
| - if (consumer_in_two_phase_read_no_lock())
|
| - return MOJO_RESULT_BUSY;
|
| -
|
| - uint32_t max_num_bytes_to_discard = num_bytes.Get();
|
| - if (max_num_bytes_to_discard % element_num_bytes_ != 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| -
|
| - if (max_num_bytes_to_discard == 0)
|
| - return MOJO_RESULT_OK; // Nothing to do.
|
| -
|
| - uint32_t min_num_bytes_to_discard =
|
| - all_or_none ? max_num_bytes_to_discard : 0;
|
| -
|
| - HandleSignalsState old_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - MojoResult rv = ConsumerDiscardDataImplNoLock(
|
| - num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard);
|
| - HandleSignalsState new_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - if (!new_producer_state.equals(old_producer_state))
|
| - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
|
| - return rv;
|
| -}
|
| -
|
| -MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| -
|
| - if (consumer_in_two_phase_read_no_lock())
|
| - return MOJO_RESULT_BUSY;
|
| -
|
| - // Note: Don't need to validate |*num_bytes| for query.
|
| - return ConsumerQueryDataImplNoLock(num_bytes);
|
| -}
|
| -
|
| -MojoResult DataPipe::ConsumerBeginReadData(
|
| - UserPointer<const void*> buffer,
|
| - UserPointer<uint32_t> buffer_num_bytes,
|
| - bool all_or_none) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| -
|
| - if (consumer_in_two_phase_read_no_lock())
|
| - return MOJO_RESULT_BUSY;
|
| -
|
| - uint32_t min_num_bytes_to_read = 0;
|
| - if (all_or_none) {
|
| - min_num_bytes_to_read = buffer_num_bytes.Get();
|
| - if (min_num_bytes_to_read % element_num_bytes_ != 0)
|
| - return MOJO_RESULT_INVALID_ARGUMENT;
|
| - }
|
| -
|
| - MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes,
|
| - min_num_bytes_to_read);
|
| - if (rv != MOJO_RESULT_OK)
|
| - return rv;
|
| - DCHECK(consumer_in_two_phase_read_no_lock());
|
| - return MOJO_RESULT_OK;
|
| -}
|
| -
|
| -MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| -
|
| - if (!consumer_in_two_phase_read_no_lock())
|
| - return MOJO_RESULT_FAILED_PRECONDITION;
|
| -
|
| - HandleSignalsState old_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - MojoResult rv;
|
| - if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ ||
|
| - num_bytes_read % element_num_bytes_ != 0) {
|
| - rv = MOJO_RESULT_INVALID_ARGUMENT;
|
| - consumer_two_phase_max_num_bytes_read_ = 0;
|
| - } else {
|
| - rv = ConsumerEndReadDataImplNoLock(num_bytes_read);
|
| - }
|
| - // Two-phase read ended even on failure.
|
| - DCHECK(!consumer_in_two_phase_read_no_lock());
|
| - // If we're now readable, we *became* readable (since we weren't readable
|
| - // during the two-phase read), so awake consumer awakables.
|
| - HandleSignalsState new_consumer_state =
|
| - ConsumerGetHandleSignalsStateImplNoLock();
|
| - if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE))
|
| - AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
|
| - HandleSignalsState new_producer_state =
|
| - ProducerGetHandleSignalsStateImplNoLock();
|
| - if (!new_producer_state.equals(old_producer_state))
|
| - AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
|
| - return rv;
|
| -}
|
| -
|
| -HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| - return ConsumerGetHandleSignalsStateImplNoLock();
|
| -}
|
| -
|
| -MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable,
|
| - MojoHandleSignals signals,
|
| - uint32_t context,
|
| - HandleSignalsState* signals_state) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| -
|
| - HandleSignalsState consumer_state = ConsumerGetHandleSignalsStateImplNoLock();
|
| - if (consumer_state.satisfies(signals)) {
|
| - if (signals_state)
|
| - *signals_state = consumer_state;
|
| - return MOJO_RESULT_ALREADY_EXISTS;
|
| - }
|
| - if (!consumer_state.can_satisfy(signals)) {
|
| - if (signals_state)
|
| - *signals_state = consumer_state;
|
| - return MOJO_RESULT_FAILED_PRECONDITION;
|
| - }
|
| -
|
| - consumer_awakable_list_->Add(awakable, signals, context);
|
| - return MOJO_RESULT_OK;
|
| -}
|
| -
|
| -void DataPipe::ConsumerRemoveAwakable(Awakable* awakable,
|
| - HandleSignalsState* signals_state) {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(has_local_consumer_no_lock());
|
| - consumer_awakable_list_->Remove(awakable);
|
| - if (signals_state)
|
| - *signals_state = ConsumerGetHandleSignalsStateImplNoLock();
|
| -}
|
| -
|
| -bool DataPipe::ConsumerIsBusy() const {
|
| - base::AutoLock locker(lock_);
|
| - return consumer_in_two_phase_read_no_lock();
|
| -}
|
| -
|
| -DataPipe::DataPipe(bool has_local_producer,
|
| - bool has_local_consumer,
|
| - const MojoCreateDataPipeOptions& validated_options)
|
| - : may_discard_((validated_options.flags &
|
| - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)),
|
| - element_num_bytes_(validated_options.element_num_bytes),
|
| - capacity_num_bytes_(validated_options.capacity_num_bytes),
|
| - producer_open_(true),
|
| - consumer_open_(true),
|
| - producer_awakable_list_(has_local_producer ? new AwakableList()
|
| - : nullptr),
|
| - consumer_awakable_list_(has_local_consumer ? new AwakableList()
|
| - : nullptr),
|
| - producer_two_phase_max_num_bytes_written_(0),
|
| - consumer_two_phase_max_num_bytes_read_(0) {
|
| - // Check that the passed in options actually are validated.
|
| - MojoCreateDataPipeOptions unused = {0};
|
| - DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused),
|
| - MOJO_RESULT_OK);
|
| -}
|
| -
|
| -DataPipe::~DataPipe() {
|
| - DCHECK(!producer_open_);
|
| - DCHECK(!consumer_open_);
|
| - DCHECK(!producer_awakable_list_);
|
| - DCHECK(!consumer_awakable_list_);
|
| -}
|
| -
|
| -void DataPipe::AwakeProducerAwakablesForStateChangeNoLock(
|
| - const HandleSignalsState& new_producer_state) {
|
| - lock_.AssertAcquired();
|
| - if (!has_local_producer_no_lock())
|
| - return;
|
| - producer_awakable_list_->AwakeForStateChange(new_producer_state);
|
| -}
|
| -
|
| -void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock(
|
| - const HandleSignalsState& new_consumer_state) {
|
| - lock_.AssertAcquired();
|
| - if (!has_local_consumer_no_lock())
|
| - return;
|
| - consumer_awakable_list_->AwakeForStateChange(new_consumer_state);
|
| -}
|
| -
|
| -} // namespace system
|
| -} // namespace mojo
|
|
|