| 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 "third_party/mojo/src/mojo/edk/system/core.h" | 5 #include "mojo/edk/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/edk/embedder/platform_channel_pair.h" |
| 12 #include "mojo/edk/embedder/platform_shared_buffer.h" |
| 13 #include "mojo/edk/embedder/platform_support.h" |
| 14 #include "mojo/edk/system/async_waiter.h" |
| 15 #include "mojo/edk/system/configuration.h" |
| 16 #include "mojo/edk/system/data_pipe.h" |
| 17 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" |
| 18 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" |
| 19 #include "mojo/edk/system/dispatcher.h" |
| 20 #include "mojo/edk/system/handle_signals_state.h" |
| 21 #include "mojo/edk/system/message_pipe_dispatcher.h" |
| 22 #include "mojo/edk/system/shared_buffer_dispatcher.h" |
| 23 #include "mojo/edk/system/waiter.h" |
| 11 #include "mojo/public/c/system/macros.h" | 24 #include "mojo/public/c/system/macros.h" |
| 12 #include "mojo/public/cpp/system/macros.h" | 25 #include "mojo/public/cpp/system/macros.h" |
| 13 #include "third_party/mojo/src/mojo/edk/embedder/platform_shared_buffer.h" | |
| 14 #include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" | |
| 15 #include "third_party/mojo/src/mojo/edk/system/async_waiter.h" | |
| 16 #include "third_party/mojo/src/mojo/edk/system/configuration.h" | |
| 17 #include "third_party/mojo/src/mojo/edk/system/data_pipe.h" | |
| 18 #include "third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h" | |
| 19 #include "third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h" | |
| 20 #include "third_party/mojo/src/mojo/edk/system/dispatcher.h" | |
| 21 #include "third_party/mojo/src/mojo/edk/system/handle_signals_state.h" | |
| 22 #include "third_party/mojo/src/mojo/edk/system/memory.h" | |
| 23 #include "third_party/mojo/src/mojo/edk/system/message_pipe.h" | |
| 24 #include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" | |
| 25 #include "third_party/mojo/src/mojo/edk/system/shared_buffer_dispatcher.h" | |
| 26 #include "third_party/mojo/src/mojo/edk/system/waiter.h" | |
| 27 | 26 |
| 28 namespace mojo { | 27 namespace mojo { |
| 29 namespace system { | 28 namespace edk { |
| 30 | 29 |
| 31 // Implementation notes | 30 // Implementation notes |
| 32 // | 31 // |
| 33 // Mojo primitives are implemented by the singleton |Core| object. Most calls | 32 // Mojo primitives are implemented by the singleton |Core| object. Most calls |
| 34 // are for a "primary" handle (the first argument). |Core::GetDispatcher()| is | 33 // are for a "primary" handle (the first argument). |Core::GetDispatcher()| is |
| 35 // used to look up a |Dispatcher| object for a given handle. That object | 34 // used to look up a |Dispatcher| object for a given handle. That object |
| 36 // implements most primitives for that object. The wait primitives are not | 35 // implements most primitives for that object. The wait primitives are not |
| 37 // attached to objects and are implemented by |Core| itself. | 36 // attached to objects and are implemented by |Core| itself. |
| 38 // | 37 // |
| 39 // Some objects have multiple handles associated to them, e.g., message pipes | 38 // Some objects have multiple handles associated to them, e.g., message pipes |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 // | 70 // |
| 72 // Notes: | 71 // Notes: |
| 73 // - While holding a |Dispatcher| lock, you may not unconditionally attempt | 72 // - While holding a |Dispatcher| lock, you may not unconditionally attempt |
| 74 // to take another |Dispatcher| lock. (This has consequences on the | 73 // to take another |Dispatcher| lock. (This has consequences on the |
| 75 // concurrency semantics of |MojoWriteMessage()| when passing handles.) | 74 // concurrency semantics of |MojoWriteMessage()| when passing handles.) |
| 76 // Doing so would lead to deadlock. | 75 // Doing so would lead to deadlock. |
| 77 // - Locks at the "INF" level may not have any locks taken while they are | 76 // - Locks at the "INF" level may not have any locks taken while they are |
| 78 // held. | 77 // held. |
| 79 | 78 |
| 80 // TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter. | 79 // TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter. |
| 81 Core::Core(embedder::PlatformSupport* platform_support) | 80 Core::Core(PlatformSupport* platform_support) |
| 82 : platform_support_(platform_support) { | 81 : platform_support_(platform_support) { |
| 83 } | 82 } |
| 84 | 83 |
| 85 Core::~Core() { | 84 Core::~Core() { |
| 86 } | 85 } |
| 87 | 86 |
| 88 MojoHandle Core::AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher) { | 87 MojoHandle Core::AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher) { |
| 89 MutexLocker locker(&handle_table_mutex_); | 88 base::AutoLock locker(handle_table_lock_); |
| 90 return handle_table_.AddDispatcher(dispatcher); | 89 return handle_table_.AddDispatcher(dispatcher); |
| 91 } | 90 } |
| 92 | 91 |
| 93 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) { | 92 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) { |
| 94 if (handle == MOJO_HANDLE_INVALID) | 93 if (handle == MOJO_HANDLE_INVALID) |
| 95 return nullptr; | 94 return nullptr; |
| 96 | 95 |
| 97 MutexLocker locker(&handle_table_mutex_); | 96 base::AutoLock locker(handle_table_lock_); |
| 98 return handle_table_.GetDispatcher(handle); | 97 return handle_table_.GetDispatcher(handle); |
| 99 } | 98 } |
| 100 | 99 |
| 101 MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, | 100 MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, |
| 102 scoped_refptr<Dispatcher>* dispatcher) { | 101 scoped_refptr<Dispatcher>* dispatcher) { |
| 103 if (handle == MOJO_HANDLE_INVALID) | 102 if (handle == MOJO_HANDLE_INVALID) |
| 104 return MOJO_RESULT_INVALID_ARGUMENT; | 103 return MOJO_RESULT_INVALID_ARGUMENT; |
| 105 | 104 |
| 106 MutexLocker locker(&handle_table_mutex_); | 105 base::AutoLock locker(handle_table_lock_); |
| 107 return handle_table_.GetAndRemoveDispatcher(handle, dispatcher); | 106 return handle_table_.GetAndRemoveDispatcher(handle, dispatcher); |
| 108 } | 107 } |
| 109 | 108 |
| 110 MojoResult Core::AsyncWait(MojoHandle handle, | 109 MojoResult Core::AsyncWait(MojoHandle handle, |
| 111 MojoHandleSignals signals, | 110 MojoHandleSignals signals, |
| 112 const base::Callback<void(MojoResult)>& callback) { | 111 const base::Callback<void(MojoResult)>& callback) { |
| 113 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); | 112 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); |
| 114 DCHECK(dispatcher); | 113 DCHECK(dispatcher); |
| 115 | 114 |
| 116 scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback)); | 115 scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback)); |
| 117 MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); | 116 MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); |
| 118 if (rv == MOJO_RESULT_OK) | 117 if (rv == MOJO_RESULT_OK) |
| 119 ignore_result(waiter.release()); | 118 ignore_result(waiter.release()); |
| 120 return rv; | 119 return rv; |
| 121 } | 120 } |
| 122 | 121 |
| 123 MojoTimeTicks Core::GetTimeTicksNow() { | 122 MojoTimeTicks Core::GetTimeTicksNow() { |
| 124 return base::TimeTicks::Now().ToInternalValue(); | 123 return base::TimeTicks::Now().ToInternalValue(); |
| 125 } | 124 } |
| 126 | 125 |
| 127 MojoResult Core::Close(MojoHandle handle) { | 126 MojoResult Core::Close(MojoHandle handle) { |
| 128 if (handle == MOJO_HANDLE_INVALID) | 127 if (handle == MOJO_HANDLE_INVALID) |
| 129 return MOJO_RESULT_INVALID_ARGUMENT; | 128 return MOJO_RESULT_INVALID_ARGUMENT; |
| 130 | 129 |
| 131 scoped_refptr<Dispatcher> dispatcher; | 130 scoped_refptr<Dispatcher> dispatcher; |
| 132 { | 131 { |
| 133 MutexLocker locker(&handle_table_mutex_); | 132 base::AutoLock locker(handle_table_lock_); |
| 134 MojoResult result = | 133 MojoResult result = |
| 135 handle_table_.GetAndRemoveDispatcher(handle, &dispatcher); | 134 handle_table_.GetAndRemoveDispatcher(handle, &dispatcher); |
| 136 if (result != MOJO_RESULT_OK) | 135 if (result != MOJO_RESULT_OK) |
| 137 return result; | 136 return result; |
| 138 } | 137 } |
| 139 | 138 |
| 140 // The dispatcher doesn't have a say in being closed, but gets notified of it. | 139 // The dispatcher doesn't have a say in being closed, but gets notified of it. |
| 141 // Note: This is done outside of |handle_table_mutex_|. As a result, there's a | 140 // Note: This is done outside of |handle_table_lock_|. As a result, there's a |
| 142 // race condition that the dispatcher must handle; see the comment in | 141 // race condition that the dispatcher must handle; see the comment in |
| 143 // |Dispatcher| in dispatcher.h. | 142 // |Dispatcher| in dispatcher.h. |
| 144 return dispatcher->Close(); | 143 return dispatcher->Close(); |
| 145 } | 144 } |
| 146 | 145 |
| 147 MojoResult Core::Wait(MojoHandle handle, | 146 MojoResult Core::Wait(MojoHandle handle, |
| 148 MojoHandleSignals signals, | 147 MojoHandleSignals signals, |
| 149 MojoDeadline deadline, | 148 MojoDeadline deadline, |
| 150 UserPointer<MojoHandleSignalsState> signals_state) { | 149 MojoHandleSignalsState* signals_state) { |
| 151 uint32_t unused = static_cast<uint32_t>(-1); | 150 uint32_t unused = static_cast<uint32_t>(-1); |
| 152 HandleSignalsState hss; | 151 HandleSignalsState hss; |
| 153 MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused, | 152 MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused, |
| 154 signals_state.IsNull() ? nullptr : &hss); | 153 signals_state ? &hss : nullptr); |
| 155 if (rv != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull()) | 154 if (rv != MOJO_RESULT_INVALID_ARGUMENT && signals_state) |
| 156 signals_state.Put(hss); | 155 *signals_state = hss; |
| 157 return rv; | 156 return rv; |
| 158 } | 157 } |
| 159 | 158 |
| 160 MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, | 159 MojoResult Core::WaitMany(const MojoHandle* handles, |
| 161 UserPointer<const MojoHandleSignals> signals, | 160 const MojoHandleSignals* signals, |
| 162 uint32_t num_handles, | 161 uint32_t num_handles, |
| 163 MojoDeadline deadline, | 162 MojoDeadline deadline, |
| 164 UserPointer<uint32_t> result_index, | 163 uint32_t* result_index, |
| 165 UserPointer<MojoHandleSignalsState> signals_states) { | 164 MojoHandleSignalsState* signals_state) { |
| 166 if (num_handles < 1) | 165 if (num_handles < 1) |
| 167 return MOJO_RESULT_INVALID_ARGUMENT; | 166 return MOJO_RESULT_INVALID_ARGUMENT; |
| 168 if (num_handles > GetConfiguration().max_wait_many_num_handles) | 167 if (num_handles > GetConfiguration().max_wait_many_num_handles) |
| 169 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 168 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 170 | 169 |
| 171 UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); | |
| 172 UserPointer<const MojoHandleSignals>::Reader signals_reader(signals, | |
| 173 num_handles); | |
| 174 uint32_t index = static_cast<uint32_t>(-1); | 170 uint32_t index = static_cast<uint32_t>(-1); |
| 175 MojoResult rv; | 171 MojoResult rv; |
| 176 if (signals_states.IsNull()) { | 172 if (!signals_state) { |
| 177 rv = WaitManyInternal(handles_reader.GetPointer(), | 173 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index, |
| 178 signals_reader.GetPointer(), num_handles, deadline, | 174 nullptr); |
| 179 &index, nullptr); | |
| 180 } else { | 175 } else { |
| 181 UserPointer<MojoHandleSignalsState>::Writer signals_states_writer( | |
| 182 signals_states, num_handles); | |
| 183 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a | 176 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a |
| 184 // subclass of |MojoHandleSignalsState| that doesn't add any data members. | 177 // subclass of |MojoHandleSignalsState| that doesn't add any data members. |
| 185 rv = WaitManyInternal(handles_reader.GetPointer(), | 178 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index, |
| 186 signals_reader.GetPointer(), num_handles, deadline, | 179 reinterpret_cast<HandleSignalsState*>(signals_state)); |
| 187 &index, reinterpret_cast<HandleSignalsState*>( | |
| 188 signals_states_writer.GetPointer())); | |
| 189 if (rv != MOJO_RESULT_INVALID_ARGUMENT) | |
| 190 signals_states_writer.Commit(); | |
| 191 } | 180 } |
| 192 if (index != static_cast<uint32_t>(-1) && !result_index.IsNull()) | 181 if (index != static_cast<uint32_t>(-1) && result_index) |
| 193 result_index.Put(index); | 182 *result_index = index; |
| 194 return rv; | 183 return rv; |
| 195 } | 184 } |
| 196 | 185 |
| 197 MojoResult Core::CreateMessagePipe( | 186 MojoResult Core::CreateMessagePipe( |
| 198 UserPointer<const MojoCreateMessagePipeOptions> options, | 187 const MojoCreateMessagePipeOptions* options, |
| 199 UserPointer<MojoHandle> message_pipe_handle0, | 188 MojoHandle* message_pipe_handle0, |
| 200 UserPointer<MojoHandle> message_pipe_handle1) { | 189 MojoHandle* message_pipe_handle1) { |
| 190 CHECK(message_pipe_handle0); |
| 191 CHECK(message_pipe_handle1); |
| 201 MojoCreateMessagePipeOptions validated_options = {}; | 192 MojoCreateMessagePipeOptions validated_options = {}; |
| 202 MojoResult result = | 193 MojoResult result = |
| 203 MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options); | 194 MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options); |
| 204 if (result != MOJO_RESULT_OK) | 195 if (result != MOJO_RESULT_OK) |
| 205 return result; | 196 return result; |
| 206 | 197 |
| 207 scoped_refptr<MessagePipeDispatcher> dispatcher0 = | 198 scoped_refptr<MessagePipeDispatcher> dispatcher0 = |
| 208 MessagePipeDispatcher::Create(validated_options); | 199 MessagePipeDispatcher::Create(validated_options); |
| 209 scoped_refptr<MessagePipeDispatcher> dispatcher1 = | 200 scoped_refptr<MessagePipeDispatcher> dispatcher1 = |
| 210 MessagePipeDispatcher::Create(validated_options); | 201 MessagePipeDispatcher::Create(validated_options); |
| 211 | 202 |
| 212 std::pair<MojoHandle, MojoHandle> handle_pair; | 203 std::pair<MojoHandle, MojoHandle> handle_pair; |
| 213 { | 204 { |
| 214 MutexLocker locker(&handle_table_mutex_); | 205 base::AutoLock locker(handle_table_lock_); |
| 215 handle_pair = handle_table_.AddDispatcherPair(dispatcher0, dispatcher1); | 206 handle_pair = handle_table_.AddDispatcherPair(dispatcher0, dispatcher1); |
| 216 } | 207 } |
| 217 if (handle_pair.first == MOJO_HANDLE_INVALID) { | 208 if (handle_pair.first == MOJO_HANDLE_INVALID) { |
| 218 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); | 209 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); |
| 219 LOG(ERROR) << "Handle table full"; | 210 LOG(ERROR) << "Handle table full"; |
| 220 dispatcher0->Close(); | 211 dispatcher0->Close(); |
| 221 dispatcher1->Close(); | 212 dispatcher1->Close(); |
| 222 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 213 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 223 } | 214 } |
| 224 | 215 |
| 225 scoped_refptr<MessagePipe> message_pipe(MessagePipe::CreateLocalLocal()); | 216 PlatformChannelPair channel_pair; |
| 226 dispatcher0->Init(message_pipe, 0); | 217 dispatcher0->Init(channel_pair.PassServerHandle()); |
| 227 dispatcher1->Init(message_pipe, 1); | 218 dispatcher1->Init(channel_pair.PassClientHandle()); |
| 228 | 219 |
| 229 message_pipe_handle0.Put(handle_pair.first); | 220 *message_pipe_handle0 = handle_pair.first; |
| 230 message_pipe_handle1.Put(handle_pair.second); | 221 *message_pipe_handle1 = handle_pair.second; |
| 231 return MOJO_RESULT_OK; | 222 return MOJO_RESULT_OK; |
| 232 } | 223 } |
| 233 | 224 |
| 234 // Implementation note: To properly cancel waiters and avoid other races, this | 225 // Implementation note: To properly cancel waiters and avoid other races, this |
| 235 // does not transfer dispatchers from one handle to another, even when sending a | 226 // does not transfer dispatchers from one handle to another, even when sending a |
| 236 // message in-process. Instead, it must transfer the "contents" of the | 227 // message in-process. Instead, it must transfer the "contents" of the |
| 237 // dispatcher to a new dispatcher, and then close the old dispatcher. If this | 228 // dispatcher to a new dispatcher, and then close the old dispatcher. If this |
| 238 // isn't done, in the in-process case, calls on the old handle may complete | 229 // isn't done, in the in-process case, calls on the old handle may complete |
| 239 // after the the message has been received and a new handle created (and | 230 // after the the message has been received and a new handle created (and |
| 240 // possibly even after calls have been made on the new handle). | 231 // possibly even after calls have been made on the new handle). |
| 241 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, | 232 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, |
| 242 UserPointer<const void> bytes, | 233 const void* bytes, |
| 243 uint32_t num_bytes, | 234 uint32_t num_bytes, |
| 244 UserPointer<const MojoHandle> handles, | 235 const MojoHandle* handles, |
| 245 uint32_t num_handles, | 236 uint32_t num_handles, |
| 246 MojoWriteMessageFlags flags) { | 237 MojoWriteMessageFlags flags) { |
| 247 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); | 238 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); |
| 248 if (!dispatcher) | 239 if (!dispatcher) |
| 249 return MOJO_RESULT_INVALID_ARGUMENT; | 240 return MOJO_RESULT_INVALID_ARGUMENT; |
| 250 | 241 |
| 251 // Easy case: not sending any handles. | 242 // Easy case: not sending any handles. |
| 252 if (num_handles == 0) | 243 if (num_handles == 0) |
| 253 return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags); | 244 return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags); |
| 254 | 245 |
| 255 // We have to handle |handles| here, since we have to mark them busy in the | 246 // We have to handle |handles| here, since we have to mark them busy in the |
| 256 // global handle table. We can't delegate this to the dispatcher, since the | 247 // global handle table. We can't delegate this to the dispatcher, since the |
| 257 // handle table lock must be acquired before the dispatcher lock. | 248 // handle table lock must be acquired before the dispatcher lock. |
| 258 // | 249 // |
| 259 // (This leads to an oddity: |handles|/|num_handles| are always verified for | 250 // (This leads to an oddity: |handles|/|num_handles| are always verified for |
| 260 // validity, even for dispatchers that don't support |WriteMessage()| and will | 251 // validity, even for dispatchers that don't support |WriteMessage()| and will |
| 261 // simply return failure unconditionally. It also breaks the usual | 252 // simply return failure unconditionally. It also breaks the usual |
| 262 // left-to-right verification order of arguments.) | 253 // left-to-right verification order of arguments.) |
| 263 if (num_handles > GetConfiguration().max_message_num_handles) | 254 if (num_handles > GetConfiguration().max_message_num_handles) |
| 264 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 255 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 265 | 256 |
| 266 UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); | |
| 267 | |
| 268 // We'll need to hold on to the dispatchers so that we can pass them on to | 257 // We'll need to hold on to the dispatchers so that we can pass them on to |
| 269 // |WriteMessage()| and also so that we can unlock their locks afterwards | 258 // |WriteMessage()| and also so that we can unlock their locks afterwards |
| 270 // without accessing the handle table. These can be dumb pointers, since their | 259 // without accessing the handle table. These can be dumb pointers, since their |
| 271 // entries in the handle table won't get removed (since they'll be marked as | 260 // entries in the handle table won't get removed (since they'll be marked as |
| 272 // busy). | 261 // busy). |
| 273 std::vector<DispatcherTransport> transports(num_handles); | 262 std::vector<DispatcherTransport> transports(num_handles); |
| 274 | 263 |
| 275 // When we pass handles, we have to try to take all their dispatchers' locks | 264 // When we pass handles, we have to try to take all their dispatchers' locks |
| 276 // and mark the handles as busy. If the call succeeds, we then remove the | 265 // and mark the handles as busy. If the call succeeds, we then remove the |
| 277 // handles from the handle table. | 266 // handles from the handle table. |
| 278 { | 267 { |
| 279 MutexLocker locker(&handle_table_mutex_); | 268 base::AutoLock locker(handle_table_lock_); |
| 280 MojoResult result = handle_table_.MarkBusyAndStartTransport( | 269 MojoResult result = handle_table_.MarkBusyAndStartTransport( |
| 281 message_pipe_handle, handles_reader.GetPointer(), num_handles, | 270 message_pipe_handle, handles, num_handles, &transports); |
| 282 &transports); | |
| 283 if (result != MOJO_RESULT_OK) | 271 if (result != MOJO_RESULT_OK) |
| 284 return result; | 272 return result; |
| 285 } | 273 } |
| 286 | 274 |
| 287 MojoResult rv = | 275 MojoResult rv = |
| 288 dispatcher->WriteMessage(bytes, num_bytes, &transports, flags); | 276 dispatcher->WriteMessage(bytes, num_bytes, &transports, flags); |
| 289 | 277 |
| 290 // We need to release the dispatcher locks before we take the handle table | 278 // We need to release the dispatcher locks before we take the handle table |
| 291 // lock. | 279 // lock. |
| 292 for (uint32_t i = 0; i < num_handles; i++) | 280 for (uint32_t i = 0; i < num_handles; i++) |
| 293 transports[i].End(); | 281 transports[i].End(); |
| 294 | 282 |
| 295 { | 283 { |
| 296 MutexLocker locker(&handle_table_mutex_); | 284 base::AutoLock locker(handle_table_lock_); |
| 297 if (rv == MOJO_RESULT_OK) { | 285 if (rv == MOJO_RESULT_OK) { |
| 298 handle_table_.RemoveBusyHandles(handles_reader.GetPointer(), num_handles); | 286 handle_table_.RemoveBusyHandles(handles, num_handles); |
| 299 } else { | 287 } else { |
| 300 handle_table_.RestoreBusyHandles(handles_reader.GetPointer(), | 288 handle_table_.RestoreBusyHandles(handles, num_handles); |
| 301 num_handles); | |
| 302 } | 289 } |
| 303 } | 290 } |
| 304 | 291 |
| 305 return rv; | 292 return rv; |
| 306 } | 293 } |
| 307 | 294 |
| 308 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, | 295 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, |
| 309 UserPointer<void> bytes, | 296 void* bytes, |
| 310 UserPointer<uint32_t> num_bytes, | 297 uint32_t* num_bytes, |
| 311 UserPointer<MojoHandle> handles, | 298 MojoHandle* handles, |
| 312 UserPointer<uint32_t> num_handles, | 299 uint32_t* num_handles, |
| 313 MojoReadMessageFlags flags) { | 300 MojoReadMessageFlags flags) { |
| 314 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); | 301 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); |
| 315 if (!dispatcher) | 302 if (!dispatcher) |
| 316 return MOJO_RESULT_INVALID_ARGUMENT; | 303 return MOJO_RESULT_INVALID_ARGUMENT; |
| 317 | 304 |
| 318 uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get(); | |
| 319 | |
| 320 MojoResult rv; | 305 MojoResult rv; |
| 306 uint32_t num_handles_value = num_handles ? *num_handles : 0; |
| 321 if (num_handles_value == 0) { | 307 if (num_handles_value == 0) { |
| 322 // Easy case: won't receive any handles. | 308 // Easy case: won't receive any handles. |
| 323 rv = dispatcher->ReadMessage(bytes, num_bytes, nullptr, &num_handles_value, | 309 rv = dispatcher->ReadMessage(bytes, num_bytes, nullptr, &num_handles_value, |
| 324 flags); | 310 flags); |
| 325 } else { | 311 } else { |
| 326 DispatcherVector dispatchers; | 312 DispatcherVector dispatchers; |
| 327 rv = dispatcher->ReadMessage(bytes, num_bytes, &dispatchers, | 313 rv = dispatcher->ReadMessage(bytes, num_bytes, &dispatchers, |
| 328 &num_handles_value, flags); | 314 &num_handles_value, flags); |
| 329 if (!dispatchers.empty()) { | 315 if (!dispatchers.empty()) { |
| 330 DCHECK_EQ(rv, MOJO_RESULT_OK); | 316 DCHECK_EQ(rv, MOJO_RESULT_OK); |
| 331 DCHECK(!num_handles.IsNull()); | 317 DCHECK(num_handles); |
| 332 DCHECK_LE(dispatchers.size(), static_cast<size_t>(num_handles_value)); | 318 DCHECK_LE(dispatchers.size(), static_cast<size_t>(num_handles_value)); |
| 333 | 319 |
| 334 bool success; | 320 bool success; |
| 335 UserPointer<MojoHandle>::Writer handles_writer(handles, | |
| 336 dispatchers.size()); | |
| 337 { | 321 { |
| 338 MutexLocker locker(&handle_table_mutex_); | 322 base::AutoLock locker(handle_table_lock_); |
| 339 success = handle_table_.AddDispatcherVector( | 323 success = handle_table_.AddDispatcherVector(dispatchers, handles); |
| 340 dispatchers, handles_writer.GetPointer()); | |
| 341 } | 324 } |
| 342 if (success) { | 325 if (!success) { |
| 343 handles_writer.Commit(); | |
| 344 } else { | |
| 345 LOG(ERROR) << "Received message with " << dispatchers.size() | 326 LOG(ERROR) << "Received message with " << dispatchers.size() |
| 346 << " handles, but handle table full"; | 327 << " handles, but handle table full"; |
| 347 // Close dispatchers (outside the lock). | 328 // Close dispatchers (outside the lock). |
| 348 for (size_t i = 0; i < dispatchers.size(); i++) { | 329 for (size_t i = 0; i < dispatchers.size(); i++) { |
| 349 if (dispatchers[i]) | 330 if (dispatchers[i]) |
| 350 dispatchers[i]->Close(); | 331 dispatchers[i]->Close(); |
| 351 } | 332 } |
| 352 if (rv == MOJO_RESULT_OK) | 333 if (rv == MOJO_RESULT_OK) |
| 353 rv = MOJO_RESULT_RESOURCE_EXHAUSTED; | 334 rv = MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 354 } | 335 } |
| 355 } | 336 } |
| 356 } | 337 } |
| 357 | 338 |
| 358 if (!num_handles.IsNull()) | 339 if (num_handles) |
| 359 num_handles.Put(num_handles_value); | 340 *num_handles = num_handles_value; |
| 360 return rv; | 341 return rv; |
| 361 } | 342 } |
| 362 | 343 |
| 363 MojoResult Core::CreateDataPipe( | 344 MojoResult Core::CreateDataPipe( |
| 364 UserPointer<const MojoCreateDataPipeOptions> options, | 345 const MojoCreateDataPipeOptions* options, |
| 365 UserPointer<MojoHandle> data_pipe_producer_handle, | 346 MojoHandle* data_pipe_producer_handle, |
| 366 UserPointer<MojoHandle> data_pipe_consumer_handle) { | 347 MojoHandle* data_pipe_consumer_handle) { |
| 367 MojoCreateDataPipeOptions validated_options = {}; | 348 MojoCreateDataPipeOptions validated_options = {}; |
| 368 MojoResult result = | 349 MojoResult result = |
| 369 DataPipe::ValidateCreateOptions(options, &validated_options); | 350 DataPipe::ValidateCreateOptions(options, &validated_options); |
| 370 if (result != MOJO_RESULT_OK) | 351 if (result != MOJO_RESULT_OK) |
| 371 return result; | 352 return result; |
| 372 | 353 |
| 373 scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher = | 354 scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher = |
| 374 DataPipeProducerDispatcher::Create(); | 355 DataPipeProducerDispatcher::Create(validated_options); |
| 375 scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher = | 356 scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher = |
| 376 DataPipeConsumerDispatcher::Create(); | 357 DataPipeConsumerDispatcher::Create(validated_options); |
| 377 | 358 |
| 378 std::pair<MojoHandle, MojoHandle> handle_pair; | 359 std::pair<MojoHandle, MojoHandle> handle_pair; |
| 379 { | 360 { |
| 380 MutexLocker locker(&handle_table_mutex_); | 361 base::AutoLock locker(handle_table_lock_); |
| 381 handle_pair = handle_table_.AddDispatcherPair(producer_dispatcher, | 362 handle_pair = handle_table_.AddDispatcherPair(producer_dispatcher, |
| 382 consumer_dispatcher); | 363 consumer_dispatcher); |
| 383 } | 364 } |
| 384 if (handle_pair.first == MOJO_HANDLE_INVALID) { | 365 if (handle_pair.first == MOJO_HANDLE_INVALID) { |
| 385 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); | 366 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); |
| 386 LOG(ERROR) << "Handle table full"; | 367 LOG(ERROR) << "Handle table full"; |
| 387 producer_dispatcher->Close(); | 368 producer_dispatcher->Close(); |
| 388 consumer_dispatcher->Close(); | 369 consumer_dispatcher->Close(); |
| 389 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 370 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 390 } | 371 } |
| 391 DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID); | 372 DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID); |
| 392 | 373 |
| 393 scoped_refptr<DataPipe> data_pipe(DataPipe::CreateLocal(validated_options)); | 374 PlatformChannelPair channel_pair; |
| 394 producer_dispatcher->Init(data_pipe); | 375 producer_dispatcher->Init(channel_pair.PassServerHandle()); |
| 395 consumer_dispatcher->Init(data_pipe); | 376 consumer_dispatcher->Init(channel_pair.PassClientHandle()); |
| 396 | 377 |
| 397 data_pipe_producer_handle.Put(handle_pair.first); | 378 *data_pipe_producer_handle = handle_pair.first; |
| 398 data_pipe_consumer_handle.Put(handle_pair.second); | 379 *data_pipe_consumer_handle = handle_pair.second; |
| 399 return MOJO_RESULT_OK; | 380 return MOJO_RESULT_OK; |
| 400 } | 381 } |
| 401 | 382 |
| 402 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, | 383 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, |
| 403 UserPointer<const void> elements, | 384 const void* elements, |
| 404 UserPointer<uint32_t> num_bytes, | 385 uint32_t* num_bytes, |
| 405 MojoWriteDataFlags flags) { | 386 MojoWriteDataFlags flags) { |
| 406 scoped_refptr<Dispatcher> dispatcher( | 387 scoped_refptr<Dispatcher> dispatcher( |
| 407 GetDispatcher(data_pipe_producer_handle)); | 388 GetDispatcher(data_pipe_producer_handle)); |
| 408 if (!dispatcher) | 389 if (!dispatcher) |
| 409 return MOJO_RESULT_INVALID_ARGUMENT; | 390 return MOJO_RESULT_INVALID_ARGUMENT; |
| 410 | 391 |
| 411 return dispatcher->WriteData(elements, num_bytes, flags); | 392 return dispatcher->WriteData(elements, num_bytes, flags); |
| 412 } | 393 } |
| 413 | 394 |
| 414 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, | 395 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, |
| 415 UserPointer<void*> buffer, | 396 void** buffer, |
| 416 UserPointer<uint32_t> buffer_num_bytes, | 397 uint32_t* buffer_num_bytes, |
| 417 MojoWriteDataFlags flags) { | 398 MojoWriteDataFlags flags) { |
| 418 scoped_refptr<Dispatcher> dispatcher( | 399 scoped_refptr<Dispatcher> dispatcher( |
| 419 GetDispatcher(data_pipe_producer_handle)); | 400 GetDispatcher(data_pipe_producer_handle)); |
| 420 if (!dispatcher) | 401 if (!dispatcher) |
| 421 return MOJO_RESULT_INVALID_ARGUMENT; | 402 return MOJO_RESULT_INVALID_ARGUMENT; |
| 422 | 403 |
| 423 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); | 404 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); |
| 424 } | 405 } |
| 425 | 406 |
| 426 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, | 407 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, |
| 427 uint32_t num_bytes_written) { | 408 uint32_t num_bytes_written) { |
| 428 scoped_refptr<Dispatcher> dispatcher( | 409 scoped_refptr<Dispatcher> dispatcher( |
| 429 GetDispatcher(data_pipe_producer_handle)); | 410 GetDispatcher(data_pipe_producer_handle)); |
| 430 if (!dispatcher) | 411 if (!dispatcher) |
| 431 return MOJO_RESULT_INVALID_ARGUMENT; | 412 return MOJO_RESULT_INVALID_ARGUMENT; |
| 432 | 413 |
| 433 return dispatcher->EndWriteData(num_bytes_written); | 414 return dispatcher->EndWriteData(num_bytes_written); |
| 434 } | 415 } |
| 435 | 416 |
| 436 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, | 417 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, |
| 437 UserPointer<void> elements, | 418 void* elements, |
| 438 UserPointer<uint32_t> num_bytes, | 419 uint32_t* num_bytes, |
| 439 MojoReadDataFlags flags) { | 420 MojoReadDataFlags flags) { |
| 440 scoped_refptr<Dispatcher> dispatcher( | 421 scoped_refptr<Dispatcher> dispatcher( |
| 441 GetDispatcher(data_pipe_consumer_handle)); | 422 GetDispatcher(data_pipe_consumer_handle)); |
| 442 if (!dispatcher) | 423 if (!dispatcher) |
| 443 return MOJO_RESULT_INVALID_ARGUMENT; | 424 return MOJO_RESULT_INVALID_ARGUMENT; |
| 444 | 425 |
| 445 return dispatcher->ReadData(elements, num_bytes, flags); | 426 return dispatcher->ReadData(elements, num_bytes, flags); |
| 446 } | 427 } |
| 447 | 428 |
| 448 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, | 429 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, |
| 449 UserPointer<const void*> buffer, | 430 const void** buffer, |
| 450 UserPointer<uint32_t> buffer_num_bytes, | 431 uint32_t* buffer_num_bytes, |
| 451 MojoReadDataFlags flags) { | 432 MojoReadDataFlags flags) { |
| 452 scoped_refptr<Dispatcher> dispatcher( | 433 scoped_refptr<Dispatcher> dispatcher( |
| 453 GetDispatcher(data_pipe_consumer_handle)); | 434 GetDispatcher(data_pipe_consumer_handle)); |
| 454 if (!dispatcher) | 435 if (!dispatcher) |
| 455 return MOJO_RESULT_INVALID_ARGUMENT; | 436 return MOJO_RESULT_INVALID_ARGUMENT; |
| 456 | 437 |
| 457 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); | 438 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); |
| 458 } | 439 } |
| 459 | 440 |
| 460 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, | 441 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, |
| 461 uint32_t num_bytes_read) { | 442 uint32_t num_bytes_read) { |
| 462 scoped_refptr<Dispatcher> dispatcher( | 443 scoped_refptr<Dispatcher> dispatcher( |
| 463 GetDispatcher(data_pipe_consumer_handle)); | 444 GetDispatcher(data_pipe_consumer_handle)); |
| 464 if (!dispatcher) | 445 if (!dispatcher) |
| 465 return MOJO_RESULT_INVALID_ARGUMENT; | 446 return MOJO_RESULT_INVALID_ARGUMENT; |
| 466 | 447 |
| 467 return dispatcher->EndReadData(num_bytes_read); | 448 return dispatcher->EndReadData(num_bytes_read); |
| 468 } | 449 } |
| 469 | 450 |
| 470 MojoResult Core::CreateSharedBuffer( | 451 MojoResult Core::CreateSharedBuffer( |
| 471 UserPointer<const MojoCreateSharedBufferOptions> options, | 452 const MojoCreateSharedBufferOptions* options, |
| 472 uint64_t num_bytes, | 453 uint64_t num_bytes, |
| 473 UserPointer<MojoHandle> shared_buffer_handle) { | 454 MojoHandle* shared_buffer_handle) { |
| 474 MojoCreateSharedBufferOptions validated_options = {}; | 455 MojoCreateSharedBufferOptions validated_options = {}; |
| 475 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( | 456 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( |
| 476 options, &validated_options); | 457 options, &validated_options); |
| 477 if (result != MOJO_RESULT_OK) | 458 if (result != MOJO_RESULT_OK) |
| 478 return result; | 459 return result; |
| 479 | 460 |
| 480 scoped_refptr<SharedBufferDispatcher> dispatcher; | 461 scoped_refptr<SharedBufferDispatcher> dispatcher; |
| 481 result = SharedBufferDispatcher::Create(platform_support_, validated_options, | 462 result = SharedBufferDispatcher::Create(platform_support_, validated_options, |
| 482 num_bytes, &dispatcher); | 463 num_bytes, &dispatcher); |
| 483 if (result != MOJO_RESULT_OK) { | 464 if (result != MOJO_RESULT_OK) { |
| 484 DCHECK(!dispatcher); | 465 DCHECK(!dispatcher); |
| 485 return result; | 466 return result; |
| 486 } | 467 } |
| 487 | 468 |
| 488 MojoHandle h = AddDispatcher(dispatcher); | 469 *shared_buffer_handle = AddDispatcher(dispatcher); |
| 489 if (h == MOJO_HANDLE_INVALID) { | 470 if (*shared_buffer_handle == MOJO_HANDLE_INVALID) { |
| 490 LOG(ERROR) << "Handle table full"; | 471 LOG(ERROR) << "Handle table full"; |
| 491 dispatcher->Close(); | 472 dispatcher->Close(); |
| 492 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 473 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 493 } | 474 } |
| 494 | 475 |
| 495 shared_buffer_handle.Put(h); | |
| 496 return MOJO_RESULT_OK; | 476 return MOJO_RESULT_OK; |
| 497 } | 477 } |
| 498 | 478 |
| 499 MojoResult Core::DuplicateBufferHandle( | 479 MojoResult Core::DuplicateBufferHandle( |
| 500 MojoHandle buffer_handle, | 480 MojoHandle buffer_handle, |
| 501 UserPointer<const MojoDuplicateBufferHandleOptions> options, | 481 const MojoDuplicateBufferHandleOptions* options, |
| 502 UserPointer<MojoHandle> new_buffer_handle) { | 482 MojoHandle* new_buffer_handle) { |
| 503 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); | 483 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); |
| 504 if (!dispatcher) | 484 if (!dispatcher) |
| 505 return MOJO_RESULT_INVALID_ARGUMENT; | 485 return MOJO_RESULT_INVALID_ARGUMENT; |
| 506 | 486 |
| 507 // Don't verify |options| here; that's the dispatcher's job. | 487 // Don't verify |options| here; that's the dispatcher's job. |
| 508 scoped_refptr<Dispatcher> new_dispatcher; | 488 scoped_refptr<Dispatcher> new_dispatcher; |
| 509 MojoResult result = | 489 MojoResult result = |
| 510 dispatcher->DuplicateBufferHandle(options, &new_dispatcher); | 490 dispatcher->DuplicateBufferHandle(options, &new_dispatcher); |
| 511 if (result != MOJO_RESULT_OK) | 491 if (result != MOJO_RESULT_OK) |
| 512 return result; | 492 return result; |
| 513 | 493 |
| 514 MojoHandle new_handle = AddDispatcher(new_dispatcher); | 494 *new_buffer_handle = AddDispatcher(new_dispatcher); |
| 515 if (new_handle == MOJO_HANDLE_INVALID) { | 495 if (*new_buffer_handle == MOJO_HANDLE_INVALID) { |
| 516 LOG(ERROR) << "Handle table full"; | 496 LOG(ERROR) << "Handle table full"; |
| 517 dispatcher->Close(); | 497 dispatcher->Close(); |
| 518 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 498 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 519 } | 499 } |
| 520 | 500 |
| 521 new_buffer_handle.Put(new_handle); | |
| 522 return MOJO_RESULT_OK; | 501 return MOJO_RESULT_OK; |
| 523 } | 502 } |
| 524 | 503 |
| 525 MojoResult Core::MapBuffer(MojoHandle buffer_handle, | 504 MojoResult Core::MapBuffer(MojoHandle buffer_handle, |
| 526 uint64_t offset, | 505 uint64_t offset, |
| 527 uint64_t num_bytes, | 506 uint64_t num_bytes, |
| 528 UserPointer<void*> buffer, | 507 void** buffer, |
| 529 MojoMapBufferFlags flags) { | 508 MojoMapBufferFlags flags) { |
| 530 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); | 509 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); |
| 531 if (!dispatcher) | 510 if (!dispatcher) |
| 532 return MOJO_RESULT_INVALID_ARGUMENT; | 511 return MOJO_RESULT_INVALID_ARGUMENT; |
| 533 | 512 |
| 534 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; | 513 scoped_ptr<PlatformSharedBufferMapping> mapping; |
| 535 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); | 514 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); |
| 536 if (result != MOJO_RESULT_OK) | 515 if (result != MOJO_RESULT_OK) |
| 537 return result; | 516 return result; |
| 538 | 517 |
| 539 DCHECK(mapping); | 518 DCHECK(mapping); |
| 540 void* address = mapping->GetBase(); | 519 void* address = mapping->GetBase(); |
| 541 { | 520 { |
| 542 MutexLocker locker(&mapping_table_mutex_); | 521 base::AutoLock locker(mapping_table_lock_); |
| 543 result = mapping_table_.AddMapping(mapping.Pass()); | 522 result = mapping_table_.AddMapping(mapping.Pass()); |
| 544 } | 523 } |
| 545 if (result != MOJO_RESULT_OK) | 524 if (result != MOJO_RESULT_OK) |
| 546 return result; | 525 return result; |
| 547 | 526 |
| 548 buffer.Put(address); | 527 *buffer = address; |
| 549 return MOJO_RESULT_OK; | 528 return MOJO_RESULT_OK; |
| 550 } | 529 } |
| 551 | 530 |
| 552 MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { | 531 MojoResult Core::UnmapBuffer(void* buffer) { |
| 553 MutexLocker locker(&mapping_table_mutex_); | 532 base::AutoLock locker(mapping_table_lock_); |
| 554 return mapping_table_.RemoveMapping(buffer.GetPointerValue()); | 533 return mapping_table_.RemoveMapping(buffer); |
| 555 } | 534 } |
| 556 | 535 |
| 557 // Note: We allow |handles| to repeat the same handle multiple times, since | 536 // Note: We allow |handles| to repeat the same handle multiple times, since |
| 558 // different flags may be specified. | 537 // different flags may be specified. |
| 559 // TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this | 538 // TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this |
| 560 // more carefully and address it if necessary. | 539 // more carefully and address it if necessary. |
| 561 MojoResult Core::WaitManyInternal(const MojoHandle* handles, | 540 MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
| 562 const MojoHandleSignals* signals, | 541 const MojoHandleSignals* signals, |
| 563 uint32_t num_handles, | 542 uint32_t num_handles, |
| 564 MojoDeadline deadline, | 543 MojoDeadline deadline, |
| 565 uint32_t* result_index, | 544 uint32_t* result_index, |
| 566 HandleSignalsState* signals_states) { | 545 HandleSignalsState* signals_states) { |
| 546 CHECK(handles); |
| 547 CHECK(signals); |
| 567 DCHECK_GT(num_handles, 0u); | 548 DCHECK_GT(num_handles, 0u); |
| 568 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); | 549 if (result_index) { |
| 550 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); |
| 551 } |
| 569 | 552 |
| 570 DispatcherVector dispatchers; | 553 DispatcherVector dispatchers; |
| 571 dispatchers.reserve(num_handles); | 554 dispatchers.reserve(num_handles); |
| 572 for (uint32_t i = 0; i < num_handles; i++) { | 555 for (uint32_t i = 0; i < num_handles; i++) { |
| 573 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); | 556 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); |
| 574 if (!dispatcher) { | 557 if (!dispatcher) { |
| 575 *result_index = i; | 558 if (result_index && result_index) |
| 559 *result_index = i; |
| 576 return MOJO_RESULT_INVALID_ARGUMENT; | 560 return MOJO_RESULT_INVALID_ARGUMENT; |
| 577 } | 561 } |
| 578 dispatchers.push_back(dispatcher); | 562 dispatchers.push_back(dispatcher); |
| 579 } | 563 } |
| 580 | 564 |
| 581 // TODO(vtl): Should make the waiter live (permanently) in TLS. | 565 // TODO(vtl): Should make the waiter live (permanently) in TLS. |
| 582 Waiter waiter; | 566 Waiter waiter; |
| 583 waiter.Init(); | 567 waiter.Init(); |
| 584 | 568 |
| 585 uint32_t i; | 569 uint32_t i; |
| 586 MojoResult rv = MOJO_RESULT_OK; | 570 MojoResult rv = MOJO_RESULT_OK; |
| 587 for (i = 0; i < num_handles; i++) { | 571 for (i = 0; i < num_handles; i++) { |
| 588 rv = dispatchers[i]->AddAwakable( | 572 rv = dispatchers[i]->AddAwakable( |
| 589 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); | 573 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); |
| 590 if (rv != MOJO_RESULT_OK) { | 574 if (rv != MOJO_RESULT_OK) { |
| 591 *result_index = i; | 575 if (result_index) |
| 576 *result_index = i; |
| 592 break; | 577 break; |
| 593 } | 578 } |
| 594 } | 579 } |
| 595 uint32_t num_added = i; | 580 uint32_t num_added = i; |
| 596 | 581 |
| 597 if (rv == MOJO_RESULT_ALREADY_EXISTS) | 582 if (rv == MOJO_RESULT_ALREADY_EXISTS) |
| 598 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". | 583 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". |
| 599 else if (rv == MOJO_RESULT_OK) | 584 else if (rv == MOJO_RESULT_OK) |
| 600 rv = waiter.Wait(deadline, result_index); | 585 rv = waiter.Wait(deadline, result_index); |
| 601 | 586 |
| 602 // 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 |
| 603 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be | 588 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be |
| 604 // 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.) |
| 605 for (i = 0; i < num_added; i++) { | 590 for (i = 0; i < num_added; i++) { |
| 606 dispatchers[i]->RemoveAwakable( | 591 dispatchers[i]->RemoveAwakable( |
| 607 &waiter, signals_states ? &signals_states[i] : nullptr); | 592 &waiter, signals_states ? &signals_states[i] : nullptr); |
| 608 } | 593 } |
| 609 if (signals_states) { | 594 if (signals_states) { |
| 610 for (; i < num_handles; i++) | 595 for (; i < num_handles; i++) |
| 611 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); | 596 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); |
| 612 } | 597 } |
| 613 | 598 |
| 614 return rv; | 599 return rv; |
| 615 } | 600 } |
| 616 | 601 |
| 617 } // namespace system | 602 } // namespace edk |
| 618 } // namespace mojo | 603 } // namespace mojo |
| OLD | NEW |