| 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/core.h" | 5 #include "mojo/system/core.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| 11 #include "mojo/public/c/system/macros.h" | 11 #include "mojo/public/c/system/macros.h" |
| 12 #include "mojo/system/constants.h" | 12 #include "mojo/system/constants.h" |
| 13 #include "mojo/system/data_pipe.h" | 13 #include "mojo/system/data_pipe.h" |
| 14 #include "mojo/system/data_pipe_consumer_dispatcher.h" | 14 #include "mojo/system/data_pipe_consumer_dispatcher.h" |
| 15 #include "mojo/system/data_pipe_producer_dispatcher.h" | 15 #include "mojo/system/data_pipe_producer_dispatcher.h" |
| 16 #include "mojo/system/dispatcher.h" | 16 #include "mojo/system/dispatcher.h" |
| 17 #include "mojo/system/handle_signals_state.h" |
| 17 #include "mojo/system/local_data_pipe.h" | 18 #include "mojo/system/local_data_pipe.h" |
| 18 #include "mojo/system/memory.h" | 19 #include "mojo/system/memory.h" |
| 19 #include "mojo/system/message_pipe.h" | 20 #include "mojo/system/message_pipe.h" |
| 20 #include "mojo/system/message_pipe_dispatcher.h" | 21 #include "mojo/system/message_pipe_dispatcher.h" |
| 21 #include "mojo/system/raw_shared_buffer.h" | 22 #include "mojo/system/raw_shared_buffer.h" |
| 22 #include "mojo/system/shared_buffer_dispatcher.h" | 23 #include "mojo/system/shared_buffer_dispatcher.h" |
| 23 #include "mojo/system/waiter.h" | 24 #include "mojo/system/waiter.h" |
| 24 | 25 |
| 25 namespace mojo { | 26 namespace mojo { |
| 26 namespace system { | 27 namespace system { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 112 |
| 112 // The dispatcher doesn't have a say in being closed, but gets notified of it. | 113 // The dispatcher doesn't have a say in being closed, but gets notified of it. |
| 113 // Note: This is done outside of |handle_table_lock_|. As a result, there's a | 114 // Note: This is done outside of |handle_table_lock_|. As a result, there's a |
| 114 // race condition that the dispatcher must handle; see the comment in | 115 // race condition that the dispatcher must handle; see the comment in |
| 115 // |Dispatcher| in dispatcher.h. | 116 // |Dispatcher| in dispatcher.h. |
| 116 return dispatcher->Close(); | 117 return dispatcher->Close(); |
| 117 } | 118 } |
| 118 | 119 |
| 119 MojoResult Core::Wait(MojoHandle handle, | 120 MojoResult Core::Wait(MojoHandle handle, |
| 120 MojoHandleSignals signals, | 121 MojoHandleSignals signals, |
| 121 MojoDeadline deadline) { | 122 MojoDeadline deadline, |
| 123 UserPointer<MojoHandleSignalsState> signals_state) { |
| 122 uint32_t unused = static_cast<uint32_t>(-1); | 124 uint32_t unused = static_cast<uint32_t>(-1); |
| 123 return WaitManyInternal(&handle, &signals, 1, deadline, &unused); | 125 HandleSignalsState hss; |
| 126 MojoResult rv = WaitManyInternal(&handle, |
| 127 &signals, |
| 128 1, |
| 129 deadline, |
| 130 &unused, |
| 131 signals_state.IsNull() ? NULL : &hss); |
| 132 if (rv != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull()) |
| 133 signals_state.Put(hss); |
| 134 return rv; |
| 124 } | 135 } |
| 125 | 136 |
| 126 MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, | 137 MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, |
| 127 UserPointer<const MojoHandleSignals> signals, | 138 UserPointer<const MojoHandleSignals> signals, |
| 128 uint32_t num_handles, | 139 uint32_t num_handles, |
| 129 MojoDeadline deadline) { | 140 MojoDeadline deadline, |
| 141 UserPointer<uint32_t> result_index, |
| 142 UserPointer<MojoHandleSignalsState> signals_states) { |
| 130 if (num_handles < 1) | 143 if (num_handles < 1) |
| 131 return MOJO_RESULT_INVALID_ARGUMENT; | 144 return MOJO_RESULT_INVALID_ARGUMENT; |
| 132 if (num_handles > kMaxWaitManyNumHandles) | 145 if (num_handles > kMaxWaitManyNumHandles) |
| 133 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 146 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 134 | 147 |
| 135 UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); | 148 UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); |
| 136 UserPointer<const MojoHandleSignals>::Reader signals_reader(signals, | 149 UserPointer<const MojoHandleSignals>::Reader signals_reader(signals, |
| 137 num_handles); | 150 num_handles); |
| 138 uint32_t result_index = static_cast<uint32_t>(-1); | 151 uint32_t index = static_cast<uint32_t>(-1); |
| 139 MojoResult result = WaitManyInternal(handles_reader.GetPointer(), | 152 MojoResult rv; |
| 140 signals_reader.GetPointer(), | 153 if (signals_states.IsNull()) { |
| 141 num_handles, | 154 rv = WaitManyInternal(handles_reader.GetPointer(), |
| 142 deadline, | 155 signals_reader.GetPointer(), |
| 143 &result_index); | 156 num_handles, |
| 144 return (result == MOJO_RESULT_OK) ? static_cast<MojoResult>(result_index) | 157 deadline, |
| 145 : result; | 158 &index, |
| 159 NULL); |
| 160 } else { |
| 161 UserPointer<MojoHandleSignalsState>::Writer signals_states_writer( |
| 162 signals_states, num_handles); |
| 163 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a |
| 164 // subclass of |MojoHandleSignalsState| that doesn't add any data members. |
| 165 rv = WaitManyInternal(handles_reader.GetPointer(), |
| 166 signals_reader.GetPointer(), |
| 167 num_handles, |
| 168 deadline, |
| 169 &index, |
| 170 reinterpret_cast<HandleSignalsState*>( |
| 171 signals_states_writer.GetPointer())); |
| 172 if (rv != MOJO_RESULT_INVALID_ARGUMENT) |
| 173 signals_states_writer.Commit(); |
| 174 } |
| 175 if (index != static_cast<uint32_t>(-1) && !result_index.IsNull()) |
| 176 result_index.Put(index); |
| 177 return rv; |
| 146 } | 178 } |
| 147 | 179 |
| 148 MojoResult Core::CreateMessagePipe( | 180 MojoResult Core::CreateMessagePipe( |
| 149 UserPointer<const MojoCreateMessagePipeOptions> options, | 181 UserPointer<const MojoCreateMessagePipeOptions> options, |
| 150 UserPointer<MojoHandle> message_pipe_handle0, | 182 UserPointer<MojoHandle> message_pipe_handle0, |
| 151 UserPointer<MojoHandle> message_pipe_handle1) { | 183 UserPointer<MojoHandle> message_pipe_handle1) { |
| 152 MojoCreateMessagePipeOptions validated_options = {}; | 184 MojoCreateMessagePipeOptions validated_options = {}; |
| 153 MojoResult result = | 185 MojoResult result = |
| 154 MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options); | 186 MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options); |
| 155 if (result != MOJO_RESULT_OK) | 187 if (result != MOJO_RESULT_OK) |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 } | 540 } |
| 509 | 541 |
| 510 // Note: We allow |handles| to repeat the same handle multiple times, since | 542 // Note: We allow |handles| to repeat the same handle multiple times, since |
| 511 // different flags may be specified. | 543 // different flags may be specified. |
| 512 // TODO(vtl): This incurs a performance cost in |RemoveWaiter()|. Analyze this | 544 // TODO(vtl): This incurs a performance cost in |RemoveWaiter()|. Analyze this |
| 513 // more carefully and address it if necessary. | 545 // more carefully and address it if necessary. |
| 514 MojoResult Core::WaitManyInternal(const MojoHandle* handles, | 546 MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
| 515 const MojoHandleSignals* signals, | 547 const MojoHandleSignals* signals, |
| 516 uint32_t num_handles, | 548 uint32_t num_handles, |
| 517 MojoDeadline deadline, | 549 MojoDeadline deadline, |
| 518 uint32_t* result_index) { | 550 uint32_t* result_index, |
| 551 HandleSignalsState* signals_states) { |
| 519 DCHECK_GT(num_handles, 0u); | 552 DCHECK_GT(num_handles, 0u); |
| 520 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); | 553 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); |
| 521 | 554 |
| 522 DispatcherVector dispatchers; | 555 DispatcherVector dispatchers; |
| 523 dispatchers.reserve(num_handles); | 556 dispatchers.reserve(num_handles); |
| 524 for (uint32_t i = 0; i < num_handles; i++) { | 557 for (uint32_t i = 0; i < num_handles; i++) { |
| 525 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); | 558 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); |
| 526 if (!dispatcher) { | 559 if (!dispatcher) { |
| 527 *result_index = i; | 560 *result_index = i; |
| 528 return MOJO_RESULT_INVALID_ARGUMENT; | 561 return MOJO_RESULT_INVALID_ARGUMENT; |
| 529 } | 562 } |
| 530 dispatchers.push_back(dispatcher); | 563 dispatchers.push_back(dispatcher); |
| 531 } | 564 } |
| 532 | 565 |
| 533 // TODO(vtl): Should make the waiter live (permanently) in TLS. | 566 // TODO(vtl): Should make the waiter live (permanently) in TLS. |
| 534 Waiter waiter; | 567 Waiter waiter; |
| 535 waiter.Init(); | 568 waiter.Init(); |
| 536 | 569 |
| 537 uint32_t i; | 570 uint32_t i; |
| 538 MojoResult rv = MOJO_RESULT_OK; | 571 MojoResult rv = MOJO_RESULT_OK; |
| 539 for (i = 0; i < num_handles; i++) { | 572 for (i = 0; i < num_handles; i++) { |
| 540 rv = dispatchers[i]->AddWaiter(&waiter, signals[i], i, NULL); | 573 rv = dispatchers[i]->AddWaiter( |
| 574 &waiter, signals[i], i, signals_states ? &signals_states[i] : NULL); |
| 541 if (rv != MOJO_RESULT_OK) { | 575 if (rv != MOJO_RESULT_OK) { |
| 542 *result_index = i; | 576 *result_index = i; |
| 543 break; | 577 break; |
| 544 } | 578 } |
| 545 } | 579 } |
| 546 uint32_t num_added = i; | 580 uint32_t num_added = i; |
| 547 | 581 |
| 548 if (rv == MOJO_RESULT_ALREADY_EXISTS) | 582 if (rv == MOJO_RESULT_ALREADY_EXISTS) |
| 549 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". | 583 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". |
| 550 else if (rv == MOJO_RESULT_OK) | 584 else if (rv == MOJO_RESULT_OK) |
| 551 rv = waiter.Wait(deadline, result_index); | 585 rv = waiter.Wait(deadline, result_index); |
| 552 | 586 |
| 553 // Make sure no other dispatchers try to wake |waiter| for the current | 587 // Make sure no other dispatchers try to wake |waiter| for the current |
| 554 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be | 588 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be |
| 555 // destroyed, but this would still be required if the waiter were in TLS.) | 589 // destroyed, but this would still be required if the waiter were in TLS.) |
| 556 for (i = 0; i < num_added; i++) | 590 for (i = 0; i < num_added; i++) { |
| 557 dispatchers[i]->RemoveWaiter(&waiter, NULL); | 591 dispatchers[i]->RemoveWaiter(&waiter, |
| 592 signals_states ? &signals_states[i] : NULL); |
| 593 } |
| 594 if (signals_states) { |
| 595 for (; i < num_handles; i++) |
| 596 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); |
| 597 } |
| 558 | 598 |
| 559 return rv; | 599 return rv; |
| 560 } | 600 } |
| 561 | 601 |
| 562 } // namespace system | 602 } // namespace system |
| 563 } // namespace mojo | 603 } // namespace mojo |
| OLD | NEW |