| 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/constants.h" | 13 #include "mojo/edk/system/configuration.h" |
| 14 #include "mojo/edk/system/memory.h" | 14 #include "mojo/edk/system/memory.h" |
| 15 #include "mojo/edk/system/options_validation.h" | 15 #include "mojo/edk/system/options_validation.h" |
| 16 #include "mojo/edk/system/waiter_list.h" | 16 #include "mojo/edk/system/waiter_list.h" |
| 17 | 17 |
| 18 namespace mojo { | 18 namespace mojo { |
| 19 namespace system { | 19 namespace system { |
| 20 | 20 |
| 21 // static | 21 // static |
| 22 const MojoCreateDataPipeOptions DataPipe::kDefaultCreateOptions = { | 22 MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { |
| 23 static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), | 23 MojoCreateDataPipeOptions result = { |
| 24 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, | 24 static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), |
| 25 1u, | 25 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, |
| 26 static_cast<uint32_t>(kDefaultDataPipeCapacityBytes)}; | 26 1u, |
| 27 static_cast<uint32_t>( |
| 28 GetConfiguration().default_data_pipe_capacity_bytes)}; |
| 29 return result; |
| 30 } |
| 27 | 31 |
| 28 // static | 32 // static |
| 29 MojoResult DataPipe::ValidateCreateOptions( | 33 MojoResult DataPipe::ValidateCreateOptions( |
| 30 UserPointer<const MojoCreateDataPipeOptions> in_options, | 34 UserPointer<const MojoCreateDataPipeOptions> in_options, |
| 31 MojoCreateDataPipeOptions* out_options) { | 35 MojoCreateDataPipeOptions* out_options) { |
| 32 const MojoCreateDataPipeOptionsFlags kKnownFlags = | 36 const MojoCreateDataPipeOptionsFlags kKnownFlags = |
| 33 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD; | 37 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD; |
| 34 | 38 |
| 35 *out_options = kDefaultCreateOptions; | 39 *out_options = GetDefaultCreateOptions(); |
| 36 if (in_options.IsNull()) | 40 if (in_options.IsNull()) |
| 37 return MOJO_RESULT_OK; | 41 return MOJO_RESULT_OK; |
| 38 | 42 |
| 39 UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options); | 43 UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options); |
| 40 if (!reader.is_valid()) | 44 if (!reader.is_valid()) |
| 41 return MOJO_RESULT_INVALID_ARGUMENT; | 45 return MOJO_RESULT_INVALID_ARGUMENT; |
| 42 | 46 |
| 43 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader)) | 47 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader)) |
| 44 return MOJO_RESULT_OK; | 48 return MOJO_RESULT_OK; |
| 45 if ((reader.options().flags & ~kKnownFlags)) | 49 if ((reader.options().flags & ~kKnownFlags)) |
| 46 return MOJO_RESULT_UNIMPLEMENTED; | 50 return MOJO_RESULT_UNIMPLEMENTED; |
| 47 out_options->flags = reader.options().flags; | 51 out_options->flags = reader.options().flags; |
| 48 | 52 |
| 49 // Checks for fields beyond |flags|: | 53 // Checks for fields beyond |flags|: |
| 50 | 54 |
| 51 if (!OPTIONS_STRUCT_HAS_MEMBER( | 55 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes, |
| 52 MojoCreateDataPipeOptions, element_num_bytes, reader)) | 56 reader)) |
| 53 return MOJO_RESULT_OK; | 57 return MOJO_RESULT_OK; |
| 54 if (reader.options().element_num_bytes == 0) | 58 if (reader.options().element_num_bytes == 0) |
| 55 return MOJO_RESULT_INVALID_ARGUMENT; | 59 return MOJO_RESULT_INVALID_ARGUMENT; |
| 56 out_options->element_num_bytes = reader.options().element_num_bytes; | 60 out_options->element_num_bytes = reader.options().element_num_bytes; |
| 57 | 61 |
| 58 if (!OPTIONS_STRUCT_HAS_MEMBER( | 62 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes, |
| 59 MojoCreateDataPipeOptions, capacity_num_bytes, reader) || | 63 reader) || |
| 60 reader.options().capacity_num_bytes == 0) { | 64 reader.options().capacity_num_bytes == 0) { |
| 61 // Round the default capacity down to a multiple of the element size (but at | 65 // Round the default capacity down to a multiple of the element size (but at |
| 62 // least one element). | 66 // least one element). |
| 67 size_t default_data_pipe_capacity_bytes = |
| 68 GetConfiguration().default_data_pipe_capacity_bytes; |
| 63 out_options->capacity_num_bytes = | 69 out_options->capacity_num_bytes = |
| 64 std::max(static_cast<uint32_t>(kDefaultDataPipeCapacityBytes - | 70 std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes - |
| 65 (kDefaultDataPipeCapacityBytes % | 71 (default_data_pipe_capacity_bytes % |
| 66 out_options->element_num_bytes)), | 72 out_options->element_num_bytes)), |
| 67 out_options->element_num_bytes); | 73 out_options->element_num_bytes); |
| 68 return MOJO_RESULT_OK; | 74 return MOJO_RESULT_OK; |
| 69 } | 75 } |
| 70 if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0) | 76 if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0) |
| 71 return MOJO_RESULT_INVALID_ARGUMENT; | 77 return MOJO_RESULT_INVALID_ARGUMENT; |
| 72 if (reader.options().capacity_num_bytes > kMaxDataPipeCapacityBytes) | 78 if (reader.options().capacity_num_bytes > |
| 79 GetConfiguration().max_data_pipe_capacity_bytes) |
| 73 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 80 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 74 out_options->capacity_num_bytes = reader.options().capacity_num_bytes; | 81 out_options->capacity_num_bytes = reader.options().capacity_num_bytes; |
| 75 | 82 |
| 76 return MOJO_RESULT_OK; | 83 return MOJO_RESULT_OK; |
| 77 } | 84 } |
| 78 | 85 |
| 79 void DataPipe::ProducerCancelAllWaiters() { | 86 void DataPipe::ProducerCancelAllWaiters() { |
| 80 base::AutoLock locker(lock_); | 87 base::AutoLock locker(lock_); |
| 81 DCHECK(has_local_producer_no_lock()); | 88 DCHECK(has_local_producer_no_lock()); |
| 82 producer_waiter_list_->CancelAllWaiters(); | 89 producer_waiter_list_->CancelAllWaiters(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 if (!consumer_open_no_lock()) | 148 if (!consumer_open_no_lock()) |
| 142 return MOJO_RESULT_FAILED_PRECONDITION; | 149 return MOJO_RESULT_FAILED_PRECONDITION; |
| 143 | 150 |
| 144 uint32_t min_num_bytes_to_write = 0; | 151 uint32_t min_num_bytes_to_write = 0; |
| 145 if (all_or_none) { | 152 if (all_or_none) { |
| 146 min_num_bytes_to_write = buffer_num_bytes.Get(); | 153 min_num_bytes_to_write = buffer_num_bytes.Get(); |
| 147 if (min_num_bytes_to_write % element_num_bytes_ != 0) | 154 if (min_num_bytes_to_write % element_num_bytes_ != 0) |
| 148 return MOJO_RESULT_INVALID_ARGUMENT; | 155 return MOJO_RESULT_INVALID_ARGUMENT; |
| 149 } | 156 } |
| 150 | 157 |
| 151 MojoResult rv = ProducerBeginWriteDataImplNoLock( | 158 MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes, |
| 152 buffer, buffer_num_bytes, min_num_bytes_to_write); | 159 min_num_bytes_to_write); |
| 153 if (rv != MOJO_RESULT_OK) | 160 if (rv != MOJO_RESULT_OK) |
| 154 return rv; | 161 return rv; |
| 155 // Note: No need to awake producer waiters, even though we're going from | 162 // 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). | 163 // writable to non-writable (since you can't wait on non-writability). |
| 157 // Similarly, though this may have discarded data (in "may discard" mode), | 164 // 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. | 165 // making it non-readable, there's still no need to awake consumer waiters. |
| 159 DCHECK(producer_in_two_phase_write_no_lock()); | 166 DCHECK(producer_in_two_phase_write_no_lock()); |
| 160 return MOJO_RESULT_OK; | 167 return MOJO_RESULT_OK; |
| 161 } | 168 } |
| 162 | 169 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 if (consumer_in_two_phase_read_no_lock()) | 345 if (consumer_in_two_phase_read_no_lock()) |
| 339 return MOJO_RESULT_BUSY; | 346 return MOJO_RESULT_BUSY; |
| 340 | 347 |
| 341 uint32_t min_num_bytes_to_read = 0; | 348 uint32_t min_num_bytes_to_read = 0; |
| 342 if (all_or_none) { | 349 if (all_or_none) { |
| 343 min_num_bytes_to_read = buffer_num_bytes.Get(); | 350 min_num_bytes_to_read = buffer_num_bytes.Get(); |
| 344 if (min_num_bytes_to_read % element_num_bytes_ != 0) | 351 if (min_num_bytes_to_read % element_num_bytes_ != 0) |
| 345 return MOJO_RESULT_INVALID_ARGUMENT; | 352 return MOJO_RESULT_INVALID_ARGUMENT; |
| 346 } | 353 } |
| 347 | 354 |
| 348 MojoResult rv = ConsumerBeginReadDataImplNoLock( | 355 MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes, |
| 349 buffer, buffer_num_bytes, min_num_bytes_to_read); | 356 min_num_bytes_to_read); |
| 350 if (rv != MOJO_RESULT_OK) | 357 if (rv != MOJO_RESULT_OK) |
| 351 return rv; | 358 return rv; |
| 352 DCHECK(consumer_in_two_phase_read_no_lock()); | 359 DCHECK(consumer_in_two_phase_read_no_lock()); |
| 353 return MOJO_RESULT_OK; | 360 return MOJO_RESULT_OK; |
| 354 } | 361 } |
| 355 | 362 |
| 356 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { | 363 MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { |
| 357 base::AutoLock locker(lock_); | 364 base::AutoLock locker(lock_); |
| 358 DCHECK(has_local_consumer_no_lock()); | 365 DCHECK(has_local_consumer_no_lock()); |
| 359 | 366 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock( | 472 void DataPipe::AwakeConsumerWaitersForStateChangeNoLock( |
| 466 const HandleSignalsState& new_consumer_state) { | 473 const HandleSignalsState& new_consumer_state) { |
| 467 lock_.AssertAcquired(); | 474 lock_.AssertAcquired(); |
| 468 if (!has_local_consumer_no_lock()) | 475 if (!has_local_consumer_no_lock()) |
| 469 return; | 476 return; |
| 470 consumer_waiter_list_->AwakeWaitersForStateChange(new_consumer_state); | 477 consumer_waiter_list_->AwakeWaitersForStateChange(new_consumer_state); |
| 471 } | 478 } |
| 472 | 479 |
| 473 } // namespace system | 480 } // namespace system |
| 474 } // namespace mojo | 481 } // namespace mojo |
| OLD | NEW |