Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: mojo/edk/system/core.cc

Issue 2744943002: Mojo: Move waiting APIs to public library (Closed)
Patch Set: . Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/system/core.h ('k') | mojo/edk/system/core_test_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « mojo/edk/system/core.h ('k') | mojo/edk/system/core_test_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698