| 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 |