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
3 // found in the LICENSE file.
4
5 #include "mojo/edk/system/core.h"
6
7 #include <string.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/containers/stack_container.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/rand_util.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/time/time.h"
21 #include "mojo/edk/embedder/embedder.h"
22 #include "mojo/edk/embedder/embedder_internal.h"
23 #include "mojo/edk/embedder/platform_shared_buffer.h"
24 #include "mojo/edk/system/channel.h"
25 #include "mojo/edk/system/configuration.h"
26 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
27 #include "mojo/edk/system/data_pipe_producer_dispatcher.h"
28 #include "mojo/edk/system/handle_signals_state.h"
29 #include "mojo/edk/system/message_for_transit.h"
30 #include "mojo/edk/system/message_pipe_dispatcher.h"
31 #include "mojo/edk/system/platform_handle_dispatcher.h"
32 #include "mojo/edk/system/ports/name.h"
33 #include "mojo/edk/system/ports/node.h"
34 #include "mojo/edk/system/request_context.h"
35 #include "mojo/edk/system/shared_buffer_dispatcher.h"
36 #include "mojo/edk/system/wait_set_dispatcher.h"
37 #include "mojo/edk/system/waiter.h"
38
39 namespace mojo {
40 namespace edk {
41
42 namespace {
43
44 // This is an unnecessarily large limit that is relatively easy to enforce.
45 const uint32_t kMaxHandlesPerMessage = 1024 * 1024;
46
47 // TODO: Maybe we could negotiate a debugging pipe ID for cross-process pipes
48 // too; for now we just use a constant. This only affects bootstrap pipes.
49 const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL;
50
CallWatchCallback(MojoWatchCallback callback,uintptr_t context,MojoResult result,const HandleSignalsState & signals_state,MojoWatchNotificationFlags flags)51 void CallWatchCallback(MojoWatchCallback callback,
52 uintptr_t context,
53 MojoResult result,
54 const HandleSignalsState& signals_state,
55 MojoWatchNotificationFlags flags) {
56 callback(context, result, static_cast<MojoHandleSignalsState>(signals_state),
57 flags);
58 }
59
MojoPlatformHandleToScopedPlatformHandle(const MojoPlatformHandle * platform_handle,ScopedPlatformHandle * out_handle)60 MojoResult MojoPlatformHandleToScopedPlatformHandle(
61 const MojoPlatformHandle* platform_handle,
62 ScopedPlatformHandle* out_handle) {
63 if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
64 return MOJO_RESULT_INVALID_ARGUMENT;
65
66 if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
67 out_handle->reset();
68 return MOJO_RESULT_OK;
69 }
70
71 PlatformHandle handle;
72 switch (platform_handle->type) {
73 #if defined(OS_POSIX)
74 case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
75 handle.handle = static_cast<int>(platform_handle->value);
76 break;
77 #endif
78
79 #if defined(OS_MACOSX) && !defined(OS_IOS)
80 case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT:
81 handle.type = PlatformHandle::Type::MACH;
82 handle.port = static_cast<mach_port_t>(platform_handle->value);
83 break;
84 #endif
85
86 #if defined(OS_WIN)
87 case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE:
88 handle.handle = reinterpret_cast<HANDLE>(platform_handle->value);
89 break;
90 #endif
91
92 default:
93 return MOJO_RESULT_INVALID_ARGUMENT;
94 }
95
96 out_handle->reset(handle);
97 return MOJO_RESULT_OK;
98 }
99
ScopedPlatformHandleToMojoPlatformHandle(ScopedPlatformHandle handle,MojoPlatformHandle * platform_handle)100 MojoResult ScopedPlatformHandleToMojoPlatformHandle(
101 ScopedPlatformHandle handle,
102 MojoPlatformHandle* platform_handle) {
103 if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
104 return MOJO_RESULT_INVALID_ARGUMENT;
105
106 if (!handle.is_valid()) {
107 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
108 return MOJO_RESULT_OK;
109 }
110
111 #if defined(OS_POSIX)
112 switch (handle.get().type) {
113 case PlatformHandle::Type::POSIX:
114 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
115 platform_handle->value = static_cast<uint64_t>(handle.release().handle);
116 break;
117
118 #if defined(OS_MACOSX) && !defined(OS_IOS)
119 case PlatformHandle::Type::MACH:
120 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
121 platform_handle->value = static_cast<uint64_t>(handle.release().port);
122 break;
123 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
124
125 default:
126 return MOJO_RESULT_INVALID_ARGUMENT;
127 }
128 #elif defined(OS_WIN)
129 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
130 platform_handle->value = reinterpret_cast<uint64_t>(handle.release().handle);
131 #endif // defined(OS_WIN)
132
133 return MOJO_RESULT_OK;
134 }
135
136 } // namespace
137
Core()138 Core::Core() {}
139
~Core()140 Core::~Core() {
141 if (node_controller_ && node_controller_->io_task_runner()) {
142 // If this races with IO thread shutdown the callback will be dropped and
143 // the NodeController will be shutdown on this thread anyway, which is also
144 // just fine.
145 scoped_refptr<base::TaskRunner> io_task_runner =
146 node_controller_->io_task_runner();
147 io_task_runner->PostTask(FROM_HERE,
148 base::Bind(&Core::PassNodeControllerToIOThread,
149 base::Passed(&node_controller_)));
150 }
151 }
152
SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner)153 void Core::SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner) {
154 GetNodeController()->SetIOTaskRunner(io_task_runner);
155 }
156
GetNodeController()157 NodeController* Core::GetNodeController() {
158 base::AutoLock lock(node_controller_lock_);
159 if (!node_controller_)
160 node_controller_.reset(new NodeController(this));
161 return node_controller_.get();
162 }
163
GetDispatcher(MojoHandle handle)164 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
165 base::AutoLock lock(handles_lock_);
166 return handles_.GetDispatcher(handle);
167 }
168
AddChild(base::ProcessHandle process_handle,ScopedPlatformHandle platform_handle,const std::string & child_token,const ProcessErrorCallback & process_error_callback)169 void Core::AddChild(base::ProcessHandle process_handle,
170 ScopedPlatformHandle platform_handle,
171 const std::string& child_token,
172 const ProcessErrorCallback& process_error_callback) {
173 GetNodeController()->ConnectToChild(process_handle,
174 std::move(platform_handle),
175 child_token,
176 process_error_callback);
177 }
178
ChildLaunchFailed(const std::string & child_token)179 void Core::ChildLaunchFailed(const std::string& child_token) {
180 RequestContext request_context;
181 GetNodeController()->CloseChildPorts(child_token);
182 }
183
InitChild(ScopedPlatformHandle platform_handle)184 void Core::InitChild(ScopedPlatformHandle platform_handle) {
185 GetNodeController()->ConnectToParent(std::move(platform_handle));
186 }
187
SetMachPortProvider(base::PortProvider * port_provider)188 void Core::SetMachPortProvider(base::PortProvider* port_provider) {
189 #if defined(OS_MACOSX) && !defined(OS_IOS)
190 GetNodeController()->CreateMachPortRelay(port_provider);
191 #endif
192 }
193
AddDispatcher(scoped_refptr<Dispatcher> dispatcher)194 MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
195 base::AutoLock lock(handles_lock_);
196 return handles_.AddDispatcher(dispatcher);
197 }
198
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)199 bool Core::AddDispatchersFromTransit(
200 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
201 MojoHandle* handles) {
202 bool failed = false;
203 {
204 base::AutoLock lock(handles_lock_);
205 if (!handles_.AddDispatchersFromTransit(dispatchers, handles))
206 failed = true;
207 }
208 if (failed) {
209 for (auto d : dispatchers)
210 d.dispatcher->Close();
211 return false;
212 }
213 return true;
214 }
215
CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,MojoHandle * wrapper_handle)216 MojoResult Core::CreatePlatformHandleWrapper(
217 ScopedPlatformHandle platform_handle,
218 MojoHandle* wrapper_handle) {
219 MojoHandle h = AddDispatcher(
220 PlatformHandleDispatcher::Create(std::move(platform_handle)));
221 if (h == MOJO_HANDLE_INVALID)
222 return MOJO_RESULT_RESOURCE_EXHAUSTED;
223 *wrapper_handle = h;
224 return MOJO_RESULT_OK;
225 }
226
PassWrappedPlatformHandle(MojoHandle wrapper_handle,ScopedPlatformHandle * platform_handle)227 MojoResult Core::PassWrappedPlatformHandle(
228 MojoHandle wrapper_handle,
229 ScopedPlatformHandle* platform_handle) {
230 base::AutoLock lock(handles_lock_);
231 scoped_refptr<Dispatcher> d;
232 MojoResult result = handles_.GetAndRemoveDispatcher(wrapper_handle, &d);
233 if (result != MOJO_RESULT_OK)
234 return result;
235 if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) {
236 PlatformHandleDispatcher* phd =
237 static_cast<PlatformHandleDispatcher*>(d.get());
238 *platform_handle = phd->PassPlatformHandle();
239 } else {
240 result = MOJO_RESULT_INVALID_ARGUMENT;
241 }
242 d->Close();
243 return result;
244 }
245
CreateSharedBufferWrapper(base::SharedMemoryHandle shared_memory_handle,size_t num_bytes,bool read_only,MojoHandle * mojo_wrapper_handle)246 MojoResult Core::CreateSharedBufferWrapper(
247 base::SharedMemoryHandle shared_memory_handle,
248 size_t num_bytes,
249 bool read_only,
250 MojoHandle* mojo_wrapper_handle) {
251 DCHECK(num_bytes);
252 scoped_refptr<PlatformSharedBuffer> platform_buffer =
253 PlatformSharedBuffer::CreateFromSharedMemoryHandle(num_bytes, read_only,
254 shared_memory_handle);
255 if (!platform_buffer)
256 return MOJO_RESULT_UNKNOWN;
257
258 scoped_refptr<SharedBufferDispatcher> dispatcher;
259 MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
260 platform_buffer, &dispatcher);
261 if (result != MOJO_RESULT_OK)
262 return result;
263 MojoHandle h = AddDispatcher(dispatcher);
264 if (h == MOJO_HANDLE_INVALID)
265 return MOJO_RESULT_RESOURCE_EXHAUSTED;
266 *mojo_wrapper_handle = h;
267 return MOJO_RESULT_OK;
268 }
269
PassSharedMemoryHandle(MojoHandle mojo_handle,base::SharedMemoryHandle * shared_memory_handle,size_t * num_bytes,bool * read_only)270 MojoResult Core::PassSharedMemoryHandle(
271 MojoHandle mojo_handle,
272 base::SharedMemoryHandle* shared_memory_handle,
273 size_t* num_bytes,
274 bool* read_only) {
275 if (!shared_memory_handle)
276 return MOJO_RESULT_INVALID_ARGUMENT;
277
278 scoped_refptr<Dispatcher> dispatcher;
279 MojoResult result = MOJO_RESULT_OK;
280 {
281 base::AutoLock lock(handles_lock_);
282 // Get the dispatcher and check it before removing it from the handle table
283 // to ensure that the dispatcher is of the correct type. This ensures we
284 // don't close and remove the wrong type of dispatcher.
285 dispatcher = handles_.GetDispatcher(mojo_handle);
286 if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER)
287 return MOJO_RESULT_INVALID_ARGUMENT;
288
289 result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
290 if (result != MOJO_RESULT_OK)
291 return result;
292 }
293
294 SharedBufferDispatcher* shm_dispatcher =
295 static_cast<SharedBufferDispatcher*>(dispatcher.get());
296 scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
297 shm_dispatcher->PassPlatformSharedBuffer();
298
299 if (!platform_shared_buffer)
300 return MOJO_RESULT_INVALID_ARGUMENT;
301
302 if (num_bytes)
303 *num_bytes = platform_shared_buffer->GetNumBytes();
304 if (read_only)
305 *read_only = platform_shared_buffer->IsReadOnly();
306 *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle();
307
308 shm_dispatcher->Close();
309 return result;
310 }
311
RequestShutdown(const base::Closure & callback)312 void Core::RequestShutdown(const base::Closure& callback) {
313 base::Closure on_shutdown;
314 if (base::ThreadTaskRunnerHandle::IsSet()) {
315 on_shutdown = base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask),
316 base::ThreadTaskRunnerHandle::Get(),
317 FROM_HERE, callback);
318 } else {
319 on_shutdown = callback;
320 }
321 GetNodeController()->RequestShutdown(on_shutdown);
322 }
323
CreateParentMessagePipe(const std::string & token,const std::string & child_token)324 ScopedMessagePipeHandle Core::CreateParentMessagePipe(
325 const std::string& token, const std::string& child_token) {
326 RequestContext request_context;
327 ports::PortRef port0, port1;
328 GetNodeController()->node()->CreatePortPair(&port0, &port1);
329 MojoHandle handle = AddDispatcher(
330 new MessagePipeDispatcher(GetNodeController(), port0,
331 kUnknownPipeIdForDebug, 0));
332 GetNodeController()->ReservePort(token, port1, child_token);
333 return ScopedMessagePipeHandle(MessagePipeHandle(handle));
334 }
335
CreateChildMessagePipe(const std::string & token)336 ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) {
337 RequestContext request_context;
338 ports::PortRef port0, port1;
339 GetNodeController()->node()->CreatePortPair(&port0, &port1);
340 MojoHandle handle = AddDispatcher(
341 new MessagePipeDispatcher(GetNodeController(), port0,
342 kUnknownPipeIdForDebug, 1));
343 GetNodeController()->MergePortIntoParent(token, port1);
344 return ScopedMessagePipeHandle(MessagePipeHandle(handle));
345 }
346
SetProperty(MojoPropertyType type,const void * value)347 MojoResult Core::SetProperty(MojoPropertyType type, const void* value) {
348 base::AutoLock locker(property_lock_);
349 switch (type) {
350 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
351 property_sync_call_allowed_ = *static_cast<const bool*>(value);
352 return MOJO_RESULT_OK;
353 default:
354 return MOJO_RESULT_INVALID_ARGUMENT;
355 }
356 }
357
GetTimeTicksNow()358 MojoTimeTicks Core::GetTimeTicksNow() {
359 return base::TimeTicks::Now().ToInternalValue();
360 }
361
Close(MojoHandle handle)362 MojoResult Core::Close(MojoHandle handle) {
363 RequestContext request_context;
364 scoped_refptr<Dispatcher> dispatcher;
365 {
366 base::AutoLock lock(handles_lock_);
367 MojoResult rv = handles_.GetAndRemoveDispatcher(handle, &dispatcher);
368 if (rv != MOJO_RESULT_OK)
369 return rv;
370 }
371 dispatcher->Close();
372 return MOJO_RESULT_OK;
373 }
374
Wait(MojoHandle handle,MojoHandleSignals signals,MojoDeadline deadline,MojoHandleSignalsState * signals_state)375 MojoResult Core::Wait(MojoHandle handle,
376 MojoHandleSignals signals,
377 MojoDeadline deadline,
378 MojoHandleSignalsState* signals_state) {
379 RequestContext request_context;
380 uint32_t unused = static_cast<uint32_t>(-1);
381 HandleSignalsState hss;
382 MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused,
383 signals_state ? &hss : nullptr);
384 if (rv != MOJO_RESULT_INVALID_ARGUMENT && signals_state)
385 *signals_state = hss;
386 return rv;
387 }
388
WaitMany(const MojoHandle * handles,const MojoHandleSignals * signals,uint32_t num_handles,MojoDeadline deadline,uint32_t * result_index,MojoHandleSignalsState * signals_state)389 MojoResult Core::WaitMany(const MojoHandle* handles,
390 const MojoHandleSignals* signals,
391 uint32_t num_handles,
392 MojoDeadline deadline,
393 uint32_t* result_index,
394 MojoHandleSignalsState* signals_state) {
395 RequestContext request_context;
396 if (num_handles < 1)
397 return MOJO_RESULT_INVALID_ARGUMENT;
398 if (num_handles > GetConfiguration().max_wait_many_num_handles)
399 return MOJO_RESULT_RESOURCE_EXHAUSTED;
400
401 uint32_t index = static_cast<uint32_t>(-1);
402 MojoResult rv;
403 if (!signals_state) {
404 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index,
405 nullptr);
406 } else {
407 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a
408 // subclass of |MojoHandleSignalsState| that doesn't add any data members.
409 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index,
410 reinterpret_cast<HandleSignalsState*>(signals_state));
411 }
412 if (index != static_cast<uint32_t>(-1) && result_index)
413 *result_index = index;
414 return rv;
415 }
416
Watch(MojoHandle handle,MojoHandleSignals signals,MojoWatchCallback callback,uintptr_t context)417 MojoResult Core::Watch(MojoHandle handle,
418 MojoHandleSignals signals,
419 MojoWatchCallback callback,
420 uintptr_t context) {
421 RequestContext request_context;
422 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
423 if (!dispatcher)
424 return MOJO_RESULT_INVALID_ARGUMENT;
425 return dispatcher->Watch(
426 signals, base::Bind(&CallWatchCallback, callback, context), context);
427 }
428
CancelWatch(MojoHandle handle,uintptr_t context)429 MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) {
430 RequestContext request_context;
431 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
432 if (!dispatcher)
433 return MOJO_RESULT_INVALID_ARGUMENT;
434 return dispatcher->CancelWatch(context);
435 }
436
AllocMessage(uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoAllocMessageFlags flags,MojoMessageHandle * message)437 MojoResult Core::AllocMessage(uint32_t num_bytes,
438 const MojoHandle* handles,
439 uint32_t num_handles,
440 MojoAllocMessageFlags flags,
441 MojoMessageHandle* message) {
442 if (!message)
443 return MOJO_RESULT_INVALID_ARGUMENT;
444
445 if (num_handles == 0) { // Fast path: no handles.
446 std::unique_ptr<MessageForTransit> msg;
447 MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0);
448 if (rv != MOJO_RESULT_OK)
449 return rv;
450
451 *message = reinterpret_cast<MojoMessageHandle>(msg.release());
452 return MOJO_RESULT_OK;
453 }
454
455 if (!handles)
456 return MOJO_RESULT_INVALID_ARGUMENT;
457
458 if (num_handles > kMaxHandlesPerMessage)
459 return MOJO_RESULT_RESOURCE_EXHAUSTED;
460
461 std::vector<Dispatcher::DispatcherInTransit> dispatchers;
462 {
463 base::AutoLock lock(handles_lock_);
464 MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers);
465 if (rv != MOJO_RESULT_OK) {
466 handles_.CancelTransit(dispatchers);
467 return rv;
468 }
469 }
470 DCHECK_EQ(num_handles, dispatchers.size());
471
472 std::unique_ptr<MessageForTransit> msg;
473 MojoResult rv = MessageForTransit::Create(
474 &msg, num_bytes, dispatchers.data(), num_handles);
475
476 {
477 base::AutoLock lock(handles_lock_);
478 if (rv == MOJO_RESULT_OK) {
479 handles_.CompleteTransitAndClose(dispatchers);
480 *message = reinterpret_cast<MojoMessageHandle>(msg.release());
481 } else {
482 handles_.CancelTransit(dispatchers);
483 }
484 }
485
486 return rv;
487 }
488
FreeMessage(MojoMessageHandle message)489 MojoResult Core::FreeMessage(MojoMessageHandle message) {
490 if (!message)
491 return MOJO_RESULT_INVALID_ARGUMENT;
492
493 delete reinterpret_cast<MessageForTransit*>(message);
494
495 return MOJO_RESULT_OK;
496 }
497
GetMessageBuffer(MojoMessageHandle message,void ** buffer)498 MojoResult Core::GetMessageBuffer(MojoMessageHandle message, void** buffer) {
499 if (!message)
500 return MOJO_RESULT_INVALID_ARGUMENT;
501
502 *buffer = reinterpret_cast<MessageForTransit*>(message)->mutable_bytes();
503
504 return MOJO_RESULT_OK;
505 }
506
GetProperty(MojoPropertyType type,void * value)507 MojoResult Core::GetProperty(MojoPropertyType type, void* value) {
508 base::AutoLock locker(property_lock_);
509 switch (type) {
510 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
511 *static_cast<bool*>(value) = property_sync_call_allowed_;
512 return MOJO_RESULT_OK;
513 default:
514 return MOJO_RESULT_INVALID_ARGUMENT;
515 }
516 }
517
CreateWaitSet(MojoHandle * wait_set_handle)518 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) {
519 RequestContext request_context;
520 if (!wait_set_handle)
521 return MOJO_RESULT_INVALID_ARGUMENT;
522
523 scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher();
524 MojoHandle h = AddDispatcher(dispatcher);
525 if (h == MOJO_HANDLE_INVALID) {
526 LOG(ERROR) << "Handle table full";
527 dispatcher->Close();
528 return MOJO_RESULT_RESOURCE_EXHAUSTED;
529 }
530
531 *wait_set_handle = h;
532 return MOJO_RESULT_OK;
533 }
534
AddHandle(MojoHandle wait_set_handle,MojoHandle handle,MojoHandleSignals signals)535 MojoResult Core::AddHandle(MojoHandle wait_set_handle,
536 MojoHandle handle,
537 MojoHandleSignals signals) {
538 RequestContext request_context;
539 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
540 if (!wait_set_dispatcher)
541 return MOJO_RESULT_INVALID_ARGUMENT;
542
543 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle));
544 if (!dispatcher)
545 return MOJO_RESULT_INVALID_ARGUMENT;
546
547 return wait_set_dispatcher->AddWaitingDispatcher(dispatcher, signals, handle);
548 }
549
RemoveHandle(MojoHandle wait_set_handle,MojoHandle handle)550 MojoResult Core::RemoveHandle(MojoHandle wait_set_handle,
551 MojoHandle handle) {
552 RequestContext request_context;
553 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
554 if (!wait_set_dispatcher)
555 return MOJO_RESULT_INVALID_ARGUMENT;
556
557 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle));
558 if (!dispatcher)
559 return MOJO_RESULT_INVALID_ARGUMENT;
560
561 return wait_set_dispatcher->RemoveWaitingDispatcher(dispatcher);
562 }
563
GetReadyHandles(MojoHandle wait_set_handle,uint32_t * count,MojoHandle * handles,MojoResult * results,MojoHandleSignalsState * signals_states)564 MojoResult Core::GetReadyHandles(MojoHandle wait_set_handle,
565 uint32_t* count,
566 MojoHandle* handles,
567 MojoResult* results,
568 MojoHandleSignalsState* signals_states) {
569 RequestContext request_context;
570 if (!handles || !count || !(*count) || !results)
571 return MOJO_RESULT_INVALID_ARGUMENT;
572
573 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle));
574 if (!wait_set_dispatcher)
575 return MOJO_RESULT_INVALID_ARGUMENT;
576
577 DispatcherVector awoken_dispatchers;
578 base::StackVector<uintptr_t, 16> contexts;
579 contexts->assign(*count, MOJO_HANDLE_INVALID);
580
581 MojoResult result = wait_set_dispatcher->GetReadyDispatchers(
582 count, &awoken_dispatchers, results, contexts->data());
583
584 if (result == MOJO_RESULT_OK) {
585 for (size_t i = 0; i < *count; i++) {
586 handles[i] = static_cast<MojoHandle>(contexts[i]);
587 if (signals_states)
588 signals_states[i] = awoken_dispatchers[i]->GetHandleSignalsState();
589 }
590 }
591
592 return result;
593 }
594
CreateMessagePipe(const MojoCreateMessagePipeOptions * options,MojoHandle * message_pipe_handle0,MojoHandle * message_pipe_handle1)595 MojoResult Core::CreateMessagePipe(
596 const MojoCreateMessagePipeOptions* options,
597 MojoHandle* message_pipe_handle0,
598 MojoHandle* message_pipe_handle1) {
599 RequestContext request_context;
600 ports::PortRef port0, port1;
601 GetNodeController()->node()->CreatePortPair(&port0, &port1);
602
603 CHECK(message_pipe_handle0);
604 CHECK(message_pipe_handle1);
605
606 uint64_t pipe_id = base::RandUint64();
607
608 *message_pipe_handle0 = AddDispatcher(
609 new MessagePipeDispatcher(GetNodeController(), port0, pipe_id, 0));
610 if (*message_pipe_handle0 == MOJO_HANDLE_INVALID)
611 return MOJO_RESULT_RESOURCE_EXHAUSTED;
612
613 *message_pipe_handle1 = AddDispatcher(
614 new MessagePipeDispatcher(GetNodeController(), port1, pipe_id, 1));
615 if (*message_pipe_handle1 == MOJO_HANDLE_INVALID) {
616 scoped_refptr<Dispatcher> unused;
617 unused->Close();
618
619 base::AutoLock lock(handles_lock_);
620 handles_.GetAndRemoveDispatcher(*message_pipe_handle0, &unused);
621 return MOJO_RESULT_RESOURCE_EXHAUSTED;
622 }
623
624 return MOJO_RESULT_OK;
625 }
626
WriteMessage(MojoHandle message_pipe_handle,const void * bytes,uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoWriteMessageFlags flags)627 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
628 const void* bytes,
629 uint32_t num_bytes,
630 const MojoHandle* handles,
631 uint32_t num_handles,
632 MojoWriteMessageFlags flags) {
633 if (num_bytes && !bytes)
634 return MOJO_RESULT_INVALID_ARGUMENT;
635
636 MojoMessageHandle message;
637 MojoResult rv = AllocMessage(num_bytes, handles, num_handles,
638 MOJO_ALLOC_MESSAGE_FLAG_NONE, &message);
639 if (rv != MOJO_RESULT_OK)
640 return rv;
641
642 if (num_bytes) {
643 void* buffer = nullptr;
644 rv = GetMessageBuffer(message, &buffer);
645 DCHECK_EQ(rv, MOJO_RESULT_OK);
646 memcpy(buffer, bytes, num_bytes);
647 }
648
649 return WriteMessageNew(message_pipe_handle, message, flags);
650 }
651
WriteMessageNew(MojoHandle message_pipe_handle,MojoMessageHandle message,MojoWriteMessageFlags flags)652 MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle,
653 MojoMessageHandle message,
654 MojoWriteMessageFlags flags) {
655 RequestContext request_context;
656 std::unique_ptr<MessageForTransit> message_for_transit(
657 reinterpret_cast<MessageForTransit*>(message));
658 auto dispatcher = GetDispatcher(message_pipe_handle);
659 if (!dispatcher)
660 return MOJO_RESULT_INVALID_ARGUMENT;
661
662 return dispatcher->WriteMessage(std::move(message_for_transit), flags);
663 }
664
ReadMessage(MojoHandle message_pipe_handle,void * bytes,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles,MojoReadMessageFlags flags)665 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
666 void* bytes,
667 uint32_t* num_bytes,
668 MojoHandle* handles,
669 uint32_t* num_handles,
670 MojoReadMessageFlags flags) {
671 CHECK((!num_handles || !*num_handles || handles) &&
672 (!num_bytes || !*num_bytes || bytes));
673 RequestContext request_context;
674 auto dispatcher = GetDispatcher(message_pipe_handle);
675 if (!dispatcher)
676 return MOJO_RESULT_INVALID_ARGUMENT;
677 std::unique_ptr<MessageForTransit> message;
678 MojoResult rv =
679 dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags,
680 false /* ignore_num_bytes */);
681 if (rv != MOJO_RESULT_OK)
682 return rv;
683
684 if (message && message->num_bytes())
685 memcpy(bytes, message->bytes(), message->num_bytes());
686
687 return MOJO_RESULT_OK;
688 }
689
ReadMessageNew(MojoHandle message_pipe_handle,MojoMessageHandle * message,uint32_t * num_bytes,MojoHandle * handles,uint32_t * num_handles,MojoReadMessageFlags flags)690 MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle,
691 MojoMessageHandle* message,
692 uint32_t* num_bytes,
693 MojoHandle* handles,
694 uint32_t* num_handles,
695 MojoReadMessageFlags flags) {
696 CHECK(message);
697 CHECK(!num_handles || !*num_handles || handles);
698 RequestContext request_context;
699 auto dispatcher = GetDispatcher(message_pipe_handle);
700 if (!dispatcher)
701 return MOJO_RESULT_INVALID_ARGUMENT;
702 std::unique_ptr<MessageForTransit> msg;
703 MojoResult rv =
704 dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags,
705 true /* ignore_num_bytes */);
706 if (rv != MOJO_RESULT_OK)
707 return rv;
708 *message = reinterpret_cast<MojoMessageHandle>(msg.release());
709 return MOJO_RESULT_OK;
710 }
711
FuseMessagePipes(MojoHandle handle0,MojoHandle handle1)712 MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) {
713 RequestContext request_context;
714 scoped_refptr<Dispatcher> dispatcher0;
715 scoped_refptr<Dispatcher> dispatcher1;
716
717 bool valid_handles = true;
718 {
719 base::AutoLock lock(handles_lock_);
720 MojoResult result0 = handles_.GetAndRemoveDispatcher(handle0, &dispatcher0);
721 MojoResult result1 = handles_.GetAndRemoveDispatcher(handle1, &dispatcher1);
722 if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK ||
723 dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE ||
724 dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE)
725 valid_handles = false;
726 }
727
728 if (!valid_handles) {
729 if (dispatcher0)
730 dispatcher0->Close();
731 if (dispatcher1)
732 dispatcher1->Close();
733 return MOJO_RESULT_INVALID_ARGUMENT;
734 }
735
736 MessagePipeDispatcher* mpd0 =
737 static_cast<MessagePipeDispatcher*>(dispatcher0.get());
738 MessagePipeDispatcher* mpd1 =
739 static_cast<MessagePipeDispatcher*>(dispatcher1.get());
740
741 if (!mpd0->Fuse(mpd1))
742 return MOJO_RESULT_FAILED_PRECONDITION;
743
744 return MOJO_RESULT_OK;
745 }
746
NotifyBadMessage(MojoMessageHandle message,const char * error,size_t error_num_bytes)747 MojoResult Core::NotifyBadMessage(MojoMessageHandle message,
748 const char* error,
749 size_t error_num_bytes) {
750 if (!message)
751 return MOJO_RESULT_INVALID_ARGUMENT;
752
753 const PortsMessage& ports_message =
754 reinterpret_cast<MessageForTransit*>(message)->ports_message();
755 if (ports_message.source_node() == ports::kInvalidNodeName) {
756 DVLOG(1) << "Received invalid message from unknown node.";
757 return MOJO_RESULT_OK;
758 }
759
760 GetNodeController()->NotifyBadMessageFrom(
761 ports_message.source_node(), std::string(error, error_num_bytes));
762 return MOJO_RESULT_OK;
763 }
764
CreateDataPipe(const MojoCreateDataPipeOptions * options,MojoHandle * data_pipe_producer_handle,MojoHandle * data_pipe_consumer_handle)765 MojoResult Core::CreateDataPipe(
766 const MojoCreateDataPipeOptions* options,
767 MojoHandle* data_pipe_producer_handle,
768 MojoHandle* data_pipe_consumer_handle) {
769 RequestContext request_context;
770 if (options && options->struct_size != sizeof(MojoCreateDataPipeOptions))
771 return MOJO_RESULT_INVALID_ARGUMENT;
772
773 MojoCreateDataPipeOptions create_options;
774 create_options.struct_size = sizeof(MojoCreateDataPipeOptions);
775 create_options.flags = options ? options->flags : 0;
776 create_options.element_num_bytes = options ? options->element_num_bytes : 1;
777 // TODO: Use Configuration to get default data pipe capacity.
778 create_options.capacity_num_bytes =
779 options && options->capacity_num_bytes ? options->capacity_num_bytes
780 : 64 * 1024;
781
782 // TODO: Broker through the parent when necessary.
783 scoped_refptr<PlatformSharedBuffer> ring_buffer =
784 GetNodeController()->CreateSharedBuffer(
785 create_options.capacity_num_bytes);
786 if (!ring_buffer)
787 return MOJO_RESULT_RESOURCE_EXHAUSTED;
788
789 ports::PortRef port0, port1;
790 GetNodeController()->node()->CreatePortPair(&port0, &port1);
791
792 CHECK(data_pipe_producer_handle);
793 CHECK(data_pipe_consumer_handle);
794
795 uint64_t pipe_id = base::RandUint64();
796
797 scoped_refptr<Dispatcher> producer = new DataPipeProducerDispatcher(
798 GetNodeController(), port0, ring_buffer, create_options,
799 true /* initialized */, pipe_id);
800 scoped_refptr<Dispatcher> consumer = new DataPipeConsumerDispatcher(
801 GetNodeController(), port1, ring_buffer, create_options,
802 true /* initialized */, pipe_id);
803
804 *data_pipe_producer_handle = AddDispatcher(producer);
805 *data_pipe_consumer_handle = AddDispatcher(consumer);
806 if (*data_pipe_producer_handle == MOJO_HANDLE_INVALID ||
807 *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) {
808 if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) {
809 scoped_refptr<Dispatcher> unused;
810 base::AutoLock lock(handles_lock_);
811 handles_.GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused);
812 }
813 producer->Close();
814 consumer->Close();
815 return MOJO_RESULT_RESOURCE_EXHAUSTED;
816 }
817
818 return MOJO_RESULT_OK;
819 }
820
WriteData(MojoHandle data_pipe_producer_handle,const void * elements,uint32_t * num_bytes,MojoWriteDataFlags flags)821 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
822 const void* elements,
823 uint32_t* num_bytes,
824 MojoWriteDataFlags flags) {
825 RequestContext request_context;
826 scoped_refptr<Dispatcher> dispatcher(
827 GetDispatcher(data_pipe_producer_handle));
828 if (!dispatcher)
829 return MOJO_RESULT_INVALID_ARGUMENT;
830
831 return dispatcher->WriteData(elements, num_bytes, flags);
832 }
833
BeginWriteData(MojoHandle data_pipe_producer_handle,void ** buffer,uint32_t * buffer_num_bytes,MojoWriteDataFlags flags)834 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
835 void** buffer,
836 uint32_t* buffer_num_bytes,
837 MojoWriteDataFlags flags) {
838 RequestContext request_context;
839 scoped_refptr<Dispatcher> dispatcher(
840 GetDispatcher(data_pipe_producer_handle));
841 if (!dispatcher)
842 return MOJO_RESULT_INVALID_ARGUMENT;
843
844 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags);
845 }
846
EndWriteData(MojoHandle data_pipe_producer_handle,uint32_t num_bytes_written)847 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
848 uint32_t num_bytes_written) {
849 RequestContext request_context;
850 scoped_refptr<Dispatcher> dispatcher(
851 GetDispatcher(data_pipe_producer_handle));
852 if (!dispatcher)
853 return MOJO_RESULT_INVALID_ARGUMENT;
854
855 return dispatcher->EndWriteData(num_bytes_written);
856 }
857
ReadData(MojoHandle data_pipe_consumer_handle,void * elements,uint32_t * num_bytes,MojoReadDataFlags flags)858 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
859 void* elements,
860 uint32_t* num_bytes,
861 MojoReadDataFlags flags) {
862 RequestContext request_context;
863 scoped_refptr<Dispatcher> dispatcher(
864 GetDispatcher(data_pipe_consumer_handle));
865 if (!dispatcher)
866 return MOJO_RESULT_INVALID_ARGUMENT;
867
868 return dispatcher->ReadData(elements, num_bytes, flags);
869 }
870
BeginReadData(MojoHandle data_pipe_consumer_handle,const void ** buffer,uint32_t * buffer_num_bytes,MojoReadDataFlags flags)871 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
872 const void** buffer,
873 uint32_t* buffer_num_bytes,
874 MojoReadDataFlags flags) {
875 RequestContext request_context;
876 scoped_refptr<Dispatcher> dispatcher(
877 GetDispatcher(data_pipe_consumer_handle));
878 if (!dispatcher)
879 return MOJO_RESULT_INVALID_ARGUMENT;
880
881 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags);
882 }
883
EndReadData(MojoHandle data_pipe_consumer_handle,uint32_t num_bytes_read)884 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
885 uint32_t num_bytes_read) {
886 RequestContext request_context;
887 scoped_refptr<Dispatcher> dispatcher(
888 GetDispatcher(data_pipe_consumer_handle));
889 if (!dispatcher)
890 return MOJO_RESULT_INVALID_ARGUMENT;
891
892 return dispatcher->EndReadData(num_bytes_read);
893 }
894
CreateSharedBuffer(const MojoCreateSharedBufferOptions * options,uint64_t num_bytes,MojoHandle * shared_buffer_handle)895 MojoResult Core::CreateSharedBuffer(
896 const MojoCreateSharedBufferOptions* options,
897 uint64_t num_bytes,
898 MojoHandle* shared_buffer_handle) {
899 RequestContext request_context;
900 MojoCreateSharedBufferOptions validated_options = {};
901 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions(
902 options, &validated_options);
903 if (result != MOJO_RESULT_OK)
904 return result;
905
906 scoped_refptr<SharedBufferDispatcher> dispatcher;
907 result = SharedBufferDispatcher::Create(
908 validated_options, GetNodeController(), num_bytes, &dispatcher);
909 if (result != MOJO_RESULT_OK) {
910 DCHECK(!dispatcher);
911 return result;
912 }
913
914 *shared_buffer_handle = AddDispatcher(dispatcher);
915 if (*shared_buffer_handle == MOJO_HANDLE_INVALID) {
916 LOG(ERROR) << "Handle table full";
917 dispatcher->Close();
918 return MOJO_RESULT_RESOURCE_EXHAUSTED;
919 }
920
921 return MOJO_RESULT_OK;
922 }
923
DuplicateBufferHandle(MojoHandle buffer_handle,const MojoDuplicateBufferHandleOptions * options,MojoHandle * new_buffer_handle)924 MojoResult Core::DuplicateBufferHandle(
925 MojoHandle buffer_handle,
926 const MojoDuplicateBufferHandleOptions* options,
927 MojoHandle* new_buffer_handle) {
928 RequestContext request_context;
929 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
930 if (!dispatcher)
931 return MOJO_RESULT_INVALID_ARGUMENT;
932
933 // Don't verify |options| here; that's the dispatcher's job.
934 scoped_refptr<Dispatcher> new_dispatcher;
935 MojoResult result =
936 dispatcher->DuplicateBufferHandle(options, &new_dispatcher);
937 if (result != MOJO_RESULT_OK)
938 return result;
939
940 *new_buffer_handle = AddDispatcher(new_dispatcher);
941 if (*new_buffer_handle == MOJO_HANDLE_INVALID) {
942 LOG(ERROR) << "Handle table full";
943 dispatcher->Close();
944 return MOJO_RESULT_RESOURCE_EXHAUSTED;
945 }
946
947 return MOJO_RESULT_OK;
948 }
949
MapBuffer(MojoHandle buffer_handle,uint64_t offset,uint64_t num_bytes,void ** buffer,MojoMapBufferFlags flags)950 MojoResult Core::MapBuffer(MojoHandle buffer_handle,
951 uint64_t offset,
952 uint64_t num_bytes,
953 void** buffer,
954 MojoMapBufferFlags flags) {
955 RequestContext request_context;
956 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
957 if (!dispatcher)
958 return MOJO_RESULT_INVALID_ARGUMENT;
959
960 std::unique_ptr<PlatformSharedBufferMapping> mapping;
961 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
962 if (result != MOJO_RESULT_OK)
963 return result;
964
965 DCHECK(mapping);
966 void* address = mapping->GetBase();
967 {
968 base::AutoLock locker(mapping_table_lock_);
969 result = mapping_table_.AddMapping(std::move(mapping));
970 }
971 if (result != MOJO_RESULT_OK)
972 return result;
973
974 *buffer = address;
975 return MOJO_RESULT_OK;
976 }
977
UnmapBuffer(void * buffer)978 MojoResult Core::UnmapBuffer(void* buffer) {
979 RequestContext request_context;
980 base::AutoLock lock(mapping_table_lock_);
981 return mapping_table_.RemoveMapping(buffer);
982 }
983
WrapPlatformHandle(const MojoPlatformHandle * platform_handle,MojoHandle * mojo_handle)984 MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
985 MojoHandle* mojo_handle) {
986 ScopedPlatformHandle handle;
987 MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle,
988 &handle);
989 if (result != MOJO_RESULT_OK)
990 return result;
991
992 return CreatePlatformHandleWrapper(std::move(handle), mojo_handle);
993 }
994
UnwrapPlatformHandle(MojoHandle mojo_handle,MojoPlatformHandle * platform_handle)995 MojoResult Core::UnwrapPlatformHandle(MojoHandle mojo_handle,
996 MojoPlatformHandle* platform_handle) {
997 ScopedPlatformHandle handle;
998 MojoResult result = PassWrappedPlatformHandle(mojo_handle, &handle);
999 if (result != MOJO_RESULT_OK)
1000 return result;
1001
1002 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
1003 platform_handle);
1004 }
1005
WrapPlatformSharedBufferHandle(const MojoPlatformHandle * platform_handle,size_t size,MojoPlatformSharedBufferHandleFlags flags,MojoHandle * mojo_handle)1006 MojoResult Core::WrapPlatformSharedBufferHandle(
1007 const MojoPlatformHandle* platform_handle,
1008 size_t size,
1009 MojoPlatformSharedBufferHandleFlags flags,
1010 MojoHandle* mojo_handle) {
1011 DCHECK(size);
1012 ScopedPlatformHandle handle;
1013 MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle,
1014 &handle);
1015 if (result != MOJO_RESULT_OK)
1016 return result;
1017
1018 bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
1019 scoped_refptr<PlatformSharedBuffer> platform_buffer =
1020 PlatformSharedBuffer::CreateFromPlatformHandle(size, read_only,
1021 std::move(handle));
1022 if (!platform_buffer)
1023 return MOJO_RESULT_UNKNOWN;
1024
1025 scoped_refptr<SharedBufferDispatcher> dispatcher;
1026 result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
1027 platform_buffer, &dispatcher);
1028 if (result != MOJO_RESULT_OK)
1029 return result;
1030
1031 MojoHandle h = AddDispatcher(dispatcher);
1032 if (h == MOJO_HANDLE_INVALID) {
1033 dispatcher->Close();
1034 return MOJO_RESULT_RESOURCE_EXHAUSTED;
1035 }
1036
1037 *mojo_handle = h;
1038 return MOJO_RESULT_OK;
1039 }
1040
UnwrapPlatformSharedBufferHandle(MojoHandle mojo_handle,MojoPlatformHandle * platform_handle,size_t * size,MojoPlatformSharedBufferHandleFlags * flags)1041 MojoResult Core::UnwrapPlatformSharedBufferHandle(
1042 MojoHandle mojo_handle,
1043 MojoPlatformHandle* platform_handle,
1044 size_t* size,
1045 MojoPlatformSharedBufferHandleFlags* flags) {
1046 scoped_refptr<Dispatcher> dispatcher;
1047 MojoResult result = MOJO_RESULT_OK;
1048 {
1049 base::AutoLock lock(handles_lock_);
1050 result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher);
1051 if (result != MOJO_RESULT_OK)
1052 return result;
1053 }
1054
1055 if (dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) {
1056 dispatcher->Close();
1057 return MOJO_RESULT_INVALID_ARGUMENT;
1058 }
1059
1060 SharedBufferDispatcher* shm_dispatcher =
1061 static_cast<SharedBufferDispatcher*>(dispatcher.get());
1062 scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
1063 shm_dispatcher->PassPlatformSharedBuffer();
1064 CHECK(platform_shared_buffer);
1065
1066 CHECK(size);
1067 *size = platform_shared_buffer->GetNumBytes();
1068
1069 CHECK(flags);
1070 *flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
1071 if (platform_shared_buffer->IsReadOnly())
1072 *flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
1073
1074 ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle();
1075 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
1076 platform_handle);
1077 }
1078
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)1079 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
1080 base::AutoLock lock(handles_lock_);
1081 handles_.GetActiveHandlesForTest(handles);
1082 }
1083
WaitManyInternal(const MojoHandle * handles,const MojoHandleSignals * signals,uint32_t num_handles,MojoDeadline deadline,uint32_t * result_index,HandleSignalsState * signals_states)1084 MojoResult Core::WaitManyInternal(const MojoHandle* handles,
1085 const MojoHandleSignals* signals,
1086 uint32_t num_handles,
1087 MojoDeadline deadline,
1088 uint32_t *result_index,
1089 HandleSignalsState* signals_states) {
1090 CHECK(handles);
1091 CHECK(signals);
1092 DCHECK_GT(num_handles, 0u);
1093 if (result_index) {
1094 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1));
1095 }
1096
1097 // The primary caller of |WaitManyInternal()| is |Wait()|, which only waits on
1098 // a single handle. In the common case of a single handle, this avoid a heap
1099 // allocation.
1100 base::StackVector<scoped_refptr<Dispatcher>, 1> dispatchers;
1101 dispatchers->reserve(num_handles);
1102 for (uint32_t i = 0; i < num_handles; i++) {
1103 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]);
1104 if (!dispatcher) {
1105 if (result_index)
1106 *result_index = i;
1107 return MOJO_RESULT_INVALID_ARGUMENT;
1108 }
1109 dispatchers->push_back(dispatcher);
1110 }
1111
1112 // TODO(vtl): Should make the waiter live (permanently) in TLS.
1113 Waiter waiter;
1114 waiter.Init();
1115
1116 uint32_t i;
1117 MojoResult rv = MOJO_RESULT_OK;
1118 for (i = 0; i < num_handles; i++) {
1119 rv = dispatchers[i]->AddAwakable(
1120 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr);
1121 if (rv != MOJO_RESULT_OK) {
1122 if (result_index)
1123 *result_index = i;
1124 break;
1125 }
1126 }
1127 uint32_t num_added = i;
1128
1129 if (rv == MOJO_RESULT_ALREADY_EXISTS) {
1130 rv = MOJO_RESULT_OK; // The i-th one is already "triggered".
1131 } else if (rv == MOJO_RESULT_OK) {
1132 uintptr_t uintptr_result = *result_index;
1133 rv = waiter.Wait(deadline, &uintptr_result);
1134 *result_index = static_cast<uint32_t>(uintptr_result);
1135 }
1136
1137 // Make sure no other dispatchers try to wake |waiter| for the current
1138 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
1139 // destroyed, but this would still be required if the waiter were in TLS.)
1140 for (i = 0; i < num_added; i++) {
1141 dispatchers[i]->RemoveAwakable(
1142 &waiter, signals_states ? &signals_states[i] : nullptr);
1143 }
1144 if (signals_states) {
1145 for (; i < num_handles; i++)
1146 signals_states[i] = dispatchers[i]->GetHandleSignalsState();
1147 }
1148
1149 return rv;
1150 }
1151
1152 // static
PassNodeControllerToIOThread(std::unique_ptr<NodeController> node_controller)1153 void Core::PassNodeControllerToIOThread(
1154 std::unique_ptr<NodeController> node_controller) {
1155 // It's OK to leak this reference. At this point we know the IO loop is still
1156 // running, and we know the NodeController will observe its eventual
1157 // destruction. This tells the NodeController to delete itself when that
1158 // happens.
1159 node_controller.release()->DestroyOnIOThreadShutdown();
1160 }
1161
1162 } // namespace edk
1163 } // namespace mojo
1164