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) |
brucedawson
2015/10/05 16:50:26
The /analyze builder points out that this line of
| |
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 |