OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/edk/system/core.h" | 5 #include "mojo/edk/system/core.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" | 26 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" |
27 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" | 27 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" |
28 #include "mojo/edk/system/handle_signals_state.h" | 28 #include "mojo/edk/system/handle_signals_state.h" |
29 #include "mojo/edk/system/message_for_transit.h" | 29 #include "mojo/edk/system/message_for_transit.h" |
30 #include "mojo/edk/system/message_pipe_dispatcher.h" | 30 #include "mojo/edk/system/message_pipe_dispatcher.h" |
31 #include "mojo/edk/system/platform_handle_dispatcher.h" | 31 #include "mojo/edk/system/platform_handle_dispatcher.h" |
32 #include "mojo/edk/system/ports/name.h" | 32 #include "mojo/edk/system/ports/name.h" |
33 #include "mojo/edk/system/ports/node.h" | 33 #include "mojo/edk/system/ports/node.h" |
34 #include "mojo/edk/system/request_context.h" | 34 #include "mojo/edk/system/request_context.h" |
35 #include "mojo/edk/system/shared_buffer_dispatcher.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 #include "mojo/edk/system/watcher_dispatcher.h" | 36 #include "mojo/edk/system/watcher_dispatcher.h" |
39 | 37 |
40 namespace mojo { | 38 namespace mojo { |
41 namespace edk { | 39 namespace edk { |
42 | 40 |
43 namespace { | 41 namespace { |
44 | 42 |
45 // This is an unnecessarily large limit that is relatively easy to enforce. | 43 // This is an unnecessarily large limit that is relatively easy to enforce. |
46 const uint32_t kMaxHandlesPerMessage = 1024 * 1024; | 44 const uint32_t kMaxHandlesPerMessage = 1024 * 1024; |
47 | 45 |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 MojoHandle handle, | 380 MojoHandle handle, |
383 MojoHandleSignalsState* signals_state) { | 381 MojoHandleSignalsState* signals_state) { |
384 RequestContext request_context; | 382 RequestContext request_context; |
385 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); | 383 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); |
386 if (!dispatcher || !signals_state) | 384 if (!dispatcher || !signals_state) |
387 return MOJO_RESULT_INVALID_ARGUMENT; | 385 return MOJO_RESULT_INVALID_ARGUMENT; |
388 *signals_state = dispatcher->GetHandleSignalsState(); | 386 *signals_state = dispatcher->GetHandleSignalsState(); |
389 return MOJO_RESULT_OK; | 387 return MOJO_RESULT_OK; |
390 } | 388 } |
391 | 389 |
392 MojoResult Core::Wait(MojoHandle handle, | |
393 MojoHandleSignals signals, | |
394 MojoDeadline deadline, | |
395 MojoHandleSignalsState* signals_state) { | |
396 RequestContext request_context; | |
397 uint32_t unused = static_cast<uint32_t>(-1); | |
398 HandleSignalsState hss; | |
399 MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused, | |
400 signals_state ? &hss : nullptr); | |
401 if (rv != MOJO_RESULT_INVALID_ARGUMENT && signals_state) | |
402 *signals_state = hss; | |
403 return rv; | |
404 } | |
405 | |
406 MojoResult Core::WaitMany(const MojoHandle* handles, | |
407 const MojoHandleSignals* signals, | |
408 uint32_t num_handles, | |
409 MojoDeadline deadline, | |
410 uint32_t* result_index, | |
411 MojoHandleSignalsState* signals_state) { | |
412 RequestContext request_context; | |
413 if (num_handles < 1) | |
414 return MOJO_RESULT_INVALID_ARGUMENT; | |
415 if (num_handles > GetConfiguration().max_wait_many_num_handles) | |
416 return MOJO_RESULT_RESOURCE_EXHAUSTED; | |
417 | |
418 uint32_t index = static_cast<uint32_t>(-1); | |
419 MojoResult rv; | |
420 if (!signals_state) { | |
421 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index, | |
422 nullptr); | |
423 } else { | |
424 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a | |
425 // subclass of |MojoHandleSignalsState| that doesn't add any data members. | |
426 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index, | |
427 reinterpret_cast<HandleSignalsState*>(signals_state)); | |
428 } | |
429 if (index != static_cast<uint32_t>(-1) && result_index) | |
430 *result_index = index; | |
431 return rv; | |
432 } | |
433 | |
434 MojoResult Core::CreateWatcher(MojoWatcherCallback callback, | 390 MojoResult Core::CreateWatcher(MojoWatcherCallback callback, |
435 MojoHandle* watcher_handle) { | 391 MojoHandle* watcher_handle) { |
436 RequestContext request_context; | 392 RequestContext request_context; |
437 if (!watcher_handle) | 393 if (!watcher_handle) |
438 return MOJO_RESULT_INVALID_ARGUMENT; | 394 return MOJO_RESULT_INVALID_ARGUMENT; |
439 *watcher_handle = AddDispatcher(new WatcherDispatcher(callback)); | 395 *watcher_handle = AddDispatcher(new WatcherDispatcher(callback)); |
440 if (*watcher_handle == MOJO_HANDLE_INVALID) | 396 if (*watcher_handle == MOJO_HANDLE_INVALID) |
441 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 397 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
442 return MOJO_RESULT_OK; | 398 return MOJO_RESULT_OK; |
443 } | 399 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 base::AutoLock locker(property_lock_); | 507 base::AutoLock locker(property_lock_); |
552 switch (type) { | 508 switch (type) { |
553 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED: | 509 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED: |
554 *static_cast<bool*>(value) = property_sync_call_allowed_; | 510 *static_cast<bool*>(value) = property_sync_call_allowed_; |
555 return MOJO_RESULT_OK; | 511 return MOJO_RESULT_OK; |
556 default: | 512 default: |
557 return MOJO_RESULT_INVALID_ARGUMENT; | 513 return MOJO_RESULT_INVALID_ARGUMENT; |
558 } | 514 } |
559 } | 515 } |
560 | 516 |
561 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) { | |
562 RequestContext request_context; | |
563 if (!wait_set_handle) | |
564 return MOJO_RESULT_INVALID_ARGUMENT; | |
565 | |
566 scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher(); | |
567 MojoHandle h = AddDispatcher(dispatcher); | |
568 if (h == MOJO_HANDLE_INVALID) { | |
569 LOG(ERROR) << "Handle table full"; | |
570 dispatcher->Close(); | |
571 return MOJO_RESULT_RESOURCE_EXHAUSTED; | |
572 } | |
573 | |
574 *wait_set_handle = h; | |
575 return MOJO_RESULT_OK; | |
576 } | |
577 | |
578 MojoResult Core::AddHandle(MojoHandle wait_set_handle, | |
579 MojoHandle handle, | |
580 MojoHandleSignals signals) { | |
581 RequestContext request_context; | |
582 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); | |
583 if (!wait_set_dispatcher) | |
584 return MOJO_RESULT_INVALID_ARGUMENT; | |
585 | |
586 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); | |
587 if (!dispatcher) | |
588 return MOJO_RESULT_INVALID_ARGUMENT; | |
589 | |
590 return wait_set_dispatcher->AddWaitingDispatcher(dispatcher, signals, handle); | |
591 } | |
592 | |
593 MojoResult Core::RemoveHandle(MojoHandle wait_set_handle, | |
594 MojoHandle handle) { | |
595 RequestContext request_context; | |
596 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); | |
597 if (!wait_set_dispatcher) | |
598 return MOJO_RESULT_INVALID_ARGUMENT; | |
599 | |
600 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); | |
601 if (!dispatcher) | |
602 return MOJO_RESULT_INVALID_ARGUMENT; | |
603 | |
604 return wait_set_dispatcher->RemoveWaitingDispatcher(dispatcher); | |
605 } | |
606 | |
607 MojoResult Core::GetReadyHandles(MojoHandle wait_set_handle, | |
608 uint32_t* count, | |
609 MojoHandle* handles, | |
610 MojoResult* results, | |
611 MojoHandleSignalsState* signals_states) { | |
612 RequestContext request_context; | |
613 if (!handles || !count || !(*count) || !results) | |
614 return MOJO_RESULT_INVALID_ARGUMENT; | |
615 | |
616 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); | |
617 if (!wait_set_dispatcher) | |
618 return MOJO_RESULT_INVALID_ARGUMENT; | |
619 | |
620 DispatcherVector awoken_dispatchers; | |
621 base::StackVector<uintptr_t, 16> contexts; | |
622 contexts->assign(*count, MOJO_HANDLE_INVALID); | |
623 | |
624 MojoResult result = wait_set_dispatcher->GetReadyDispatchers( | |
625 count, &awoken_dispatchers, results, contexts->data()); | |
626 | |
627 if (result == MOJO_RESULT_OK) { | |
628 for (size_t i = 0; i < *count; i++) { | |
629 handles[i] = static_cast<MojoHandle>(contexts[i]); | |
630 if (signals_states) | |
631 signals_states[i] = awoken_dispatchers[i]->GetHandleSignalsState(); | |
632 } | |
633 } | |
634 | |
635 return result; | |
636 } | |
637 | |
638 MojoResult Core::CreateMessagePipe( | 517 MojoResult Core::CreateMessagePipe( |
639 const MojoCreateMessagePipeOptions* options, | 518 const MojoCreateMessagePipeOptions* options, |
640 MojoHandle* message_pipe_handle0, | 519 MojoHandle* message_pipe_handle0, |
641 MojoHandle* message_pipe_handle1) { | 520 MojoHandle* message_pipe_handle1) { |
642 RequestContext request_context; | 521 RequestContext request_context; |
643 ports::PortRef port0, port1; | 522 ports::PortRef port0, port1; |
644 GetNodeController()->node()->CreatePortPair(&port0, &port1); | 523 GetNodeController()->node()->CreatePortPair(&port0, &port1); |
645 | 524 |
646 CHECK(message_pipe_handle0); | 525 CHECK(message_pipe_handle0); |
647 CHECK(message_pipe_handle1); | 526 CHECK(message_pipe_handle1); |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle(); | 998 ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle(); |
1120 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle), | 999 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle), |
1121 platform_handle); | 1000 platform_handle); |
1122 } | 1001 } |
1123 | 1002 |
1124 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) { | 1003 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) { |
1125 base::AutoLock lock(handles_lock_); | 1004 base::AutoLock lock(handles_lock_); |
1126 handles_.GetActiveHandlesForTest(handles); | 1005 handles_.GetActiveHandlesForTest(handles); |
1127 } | 1006 } |
1128 | 1007 |
1129 MojoResult Core::WaitManyInternal(const MojoHandle* handles, | |
1130 const MojoHandleSignals* signals, | |
1131 uint32_t num_handles, | |
1132 MojoDeadline deadline, | |
1133 uint32_t* result_index, | |
1134 HandleSignalsState* signals_states) { | |
1135 CHECK(handles); | |
1136 CHECK(signals); | |
1137 DCHECK_GT(num_handles, 0u); | |
1138 if (result_index) { | |
1139 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); | |
1140 } | |
1141 | |
1142 // The primary caller of |WaitManyInternal()| is |Wait()|, which only waits on | |
1143 // a single handle. In the common case of a single handle, this avoid a heap | |
1144 // allocation. | |
1145 base::StackVector<scoped_refptr<Dispatcher>, 1> dispatchers; | |
1146 dispatchers->reserve(num_handles); | |
1147 for (uint32_t i = 0; i < num_handles; i++) { | |
1148 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); | |
1149 if (!dispatcher) { | |
1150 if (result_index) | |
1151 *result_index = i; | |
1152 return MOJO_RESULT_INVALID_ARGUMENT; | |
1153 } | |
1154 dispatchers->push_back(dispatcher); | |
1155 } | |
1156 | |
1157 // TODO(vtl): Should make the waiter live (permanently) in TLS. | |
1158 Waiter waiter; | |
1159 waiter.Init(); | |
1160 | |
1161 uint32_t i; | |
1162 MojoResult rv = MOJO_RESULT_OK; | |
1163 for (i = 0; i < num_handles; i++) { | |
1164 rv = dispatchers[i]->AddAwakable( | |
1165 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); | |
1166 if (rv != MOJO_RESULT_OK) { | |
1167 if (result_index) | |
1168 *result_index = i; | |
1169 break; | |
1170 } | |
1171 } | |
1172 uint32_t num_added = i; | |
1173 | |
1174 if (rv == MOJO_RESULT_ALREADY_EXISTS) { | |
1175 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". | |
1176 } else if (rv == MOJO_RESULT_OK) { | |
1177 uintptr_t uintptr_result = *result_index; | |
1178 rv = waiter.Wait(deadline, &uintptr_result); | |
1179 *result_index = static_cast<uint32_t>(uintptr_result); | |
1180 } | |
1181 | |
1182 // Make sure no other dispatchers try to wake |waiter| for the current | |
1183 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be | |
1184 // destroyed, but this would still be required if the waiter were in TLS.) | |
1185 for (i = 0; i < num_added; i++) { | |
1186 dispatchers[i]->RemoveAwakable( | |
1187 &waiter, signals_states ? &signals_states[i] : nullptr); | |
1188 } | |
1189 if (signals_states) { | |
1190 for (; i < num_handles; i++) | |
1191 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); | |
1192 } | |
1193 | |
1194 return rv; | |
1195 } | |
1196 | |
1197 // static | 1008 // static |
1198 void Core::PassNodeControllerToIOThread( | 1009 void Core::PassNodeControllerToIOThread( |
1199 std::unique_ptr<NodeController> node_controller) { | 1010 std::unique_ptr<NodeController> node_controller) { |
1200 // It's OK to leak this reference. At this point we know the IO loop is still | 1011 // It's OK to leak this reference. At this point we know the IO loop is still |
1201 // running, and we know the NodeController will observe its eventual | 1012 // running, and we know the NodeController will observe its eventual |
1202 // destruction. This tells the NodeController to delete itself when that | 1013 // destruction. This tells the NodeController to delete itself when that |
1203 // happens. | 1014 // happens. |
1204 node_controller.release()->DestroyOnIOThreadShutdown(); | 1015 node_controller.release()->DestroyOnIOThreadShutdown(); |
1205 } | 1016 } |
1206 | 1017 |
1207 } // namespace edk | 1018 } // namespace edk |
1208 } // namespace mojo | 1019 } // namespace mojo |
OLD | NEW |