Mojo: Plumb new Wait/WaitMany API out to Core.

We still need to expose these to apps, and transition things
appropriately.

R=darin@chromium.org

Review URL: https://codereview.chromium.org/454603002

Cr-Commit-Position: refs/heads/master@{#288453}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288453 0039d316-1c4b-4281-b951-d872f2087c98
parent d3607a09
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "mojo/system/data_pipe_consumer_dispatcher.h" #include "mojo/system/data_pipe_consumer_dispatcher.h"
#include "mojo/system/data_pipe_producer_dispatcher.h" #include "mojo/system/data_pipe_producer_dispatcher.h"
#include "mojo/system/dispatcher.h" #include "mojo/system/dispatcher.h"
#include "mojo/system/handle_signals_state.h"
#include "mojo/system/local_data_pipe.h" #include "mojo/system/local_data_pipe.h"
#include "mojo/system/memory.h" #include "mojo/system/memory.h"
#include "mojo/system/message_pipe.h" #include "mojo/system/message_pipe.h"
...@@ -118,15 +119,27 @@ MojoResult Core::Close(MojoHandle handle) { ...@@ -118,15 +119,27 @@ MojoResult Core::Close(MojoHandle handle) {
MojoResult Core::Wait(MojoHandle handle, MojoResult Core::Wait(MojoHandle handle,
MojoHandleSignals signals, MojoHandleSignals signals,
MojoDeadline deadline) { MojoDeadline deadline,
UserPointer<MojoHandleSignalsState> signals_state) {
uint32_t unused = static_cast<uint32_t>(-1); uint32_t unused = static_cast<uint32_t>(-1);
return WaitManyInternal(&handle, &signals, 1, deadline, &unused); HandleSignalsState hss;
MojoResult rv = WaitManyInternal(&handle,
&signals,
1,
deadline,
&unused,
signals_state.IsNull() ? NULL : &hss);
if (rv != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull())
signals_state.Put(hss);
return rv;
} }
MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles,
UserPointer<const MojoHandleSignals> signals, UserPointer<const MojoHandleSignals> signals,
uint32_t num_handles, uint32_t num_handles,
MojoDeadline deadline) { MojoDeadline deadline,
UserPointer<uint32_t> result_index,
UserPointer<MojoHandleSignalsState> signals_states) {
if (num_handles < 1) if (num_handles < 1)
return MOJO_RESULT_INVALID_ARGUMENT; return MOJO_RESULT_INVALID_ARGUMENT;
if (num_handles > kMaxWaitManyNumHandles) if (num_handles > kMaxWaitManyNumHandles)
...@@ -135,14 +148,33 @@ MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, ...@@ -135,14 +148,33 @@ MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles,
UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles);
UserPointer<const MojoHandleSignals>::Reader signals_reader(signals, UserPointer<const MojoHandleSignals>::Reader signals_reader(signals,
num_handles); num_handles);
uint32_t result_index = static_cast<uint32_t>(-1); uint32_t index = static_cast<uint32_t>(-1);
MojoResult result = WaitManyInternal(handles_reader.GetPointer(), MojoResult rv;
if (signals_states.IsNull()) {
rv = WaitManyInternal(handles_reader.GetPointer(),
signals_reader.GetPointer(), signals_reader.GetPointer(),
num_handles, num_handles,
deadline, deadline,
&result_index); &index,
return (result == MOJO_RESULT_OK) ? static_cast<MojoResult>(result_index) NULL);
: result; } else {
UserPointer<MojoHandleSignalsState>::Writer signals_states_writer(
signals_states, num_handles);
// Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a
// subclass of |MojoHandleSignalsState| that doesn't add any data members.
rv = WaitManyInternal(handles_reader.GetPointer(),
signals_reader.GetPointer(),
num_handles,
deadline,
&index,
reinterpret_cast<HandleSignalsState*>(
signals_states_writer.GetPointer()));
if (rv != MOJO_RESULT_INVALID_ARGUMENT)
signals_states_writer.Commit();
}
if (index != static_cast<uint32_t>(-1) && !result_index.IsNull())
result_index.Put(index);
return rv;
} }
MojoResult Core::CreateMessagePipe( MojoResult Core::CreateMessagePipe(
...@@ -515,7 +547,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, ...@@ -515,7 +547,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles,
const MojoHandleSignals* signals, const MojoHandleSignals* signals,
uint32_t num_handles, uint32_t num_handles,
MojoDeadline deadline, MojoDeadline deadline,
uint32_t* result_index) { uint32_t* result_index,
HandleSignalsState* signals_states) {
DCHECK_GT(num_handles, 0u); DCHECK_GT(num_handles, 0u);
DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); DCHECK_EQ(*result_index, static_cast<uint32_t>(-1));
...@@ -537,7 +570,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, ...@@ -537,7 +570,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles,
uint32_t i; uint32_t i;
MojoResult rv = MOJO_RESULT_OK; MojoResult rv = MOJO_RESULT_OK;
for (i = 0; i < num_handles; i++) { for (i = 0; i < num_handles; i++) {
rv = dispatchers[i]->AddWaiter(&waiter, signals[i], i, NULL); rv = dispatchers[i]->AddWaiter(
&waiter, signals[i], i, signals_states ? &signals_states[i] : NULL);
if (rv != MOJO_RESULT_OK) { if (rv != MOJO_RESULT_OK) {
*result_index = i; *result_index = i;
break; break;
...@@ -553,8 +587,14 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, ...@@ -553,8 +587,14 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles,
// Make sure no other dispatchers try to wake |waiter| for the current // Make sure no other dispatchers try to wake |waiter| for the current
// |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
// destroyed, but this would still be required if the waiter were in TLS.) // destroyed, but this would still be required if the waiter were in TLS.)
for (i = 0; i < num_added; i++) for (i = 0; i < num_added; i++) {
dispatchers[i]->RemoveWaiter(&waiter, NULL); dispatchers[i]->RemoveWaiter(&waiter,
signals_states ? &signals_states[i] : NULL);
}
if (signals_states) {
for (; i < num_handles; i++)
signals_states[i] = dispatchers[i]->GetHandleSignalsState();
}
return rv; return rv;
} }
......
...@@ -23,6 +23,7 @@ namespace mojo { ...@@ -23,6 +23,7 @@ namespace mojo {
namespace system { namespace system {
class Dispatcher; class Dispatcher;
struct HandleSignalsState;
// |Core| is an object that implements the Mojo system calls. All public methods // |Core| is an object that implements the Mojo system calls. All public methods
// are thread-safe. // are thread-safe.
...@@ -45,11 +46,14 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { ...@@ -45,11 +46,14 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoResult Close(MojoHandle handle); MojoResult Close(MojoHandle handle);
MojoResult Wait(MojoHandle handle, MojoResult Wait(MojoHandle handle,
MojoHandleSignals signals, MojoHandleSignals signals,
MojoDeadline deadline); MojoDeadline deadline,
UserPointer<MojoHandleSignalsState> signals_state);
MojoResult WaitMany(UserPointer<const MojoHandle> handles, MojoResult WaitMany(UserPointer<const MojoHandle> handles,
UserPointer<const MojoHandleSignals> signals, UserPointer<const MojoHandleSignals> signals,
uint32_t num_handles, uint32_t num_handles,
MojoDeadline deadline); MojoDeadline deadline,
UserPointer<uint32_t> result_index,
UserPointer<MojoHandleSignalsState> signals_states);
MojoResult CreateMessagePipe( MojoResult CreateMessagePipe(
UserPointer<const MojoCreateMessagePipeOptions> options, UserPointer<const MojoCreateMessagePipeOptions> options,
UserPointer<MojoHandle> message_pipe_handle0, UserPointer<MojoHandle> message_pipe_handle0,
...@@ -116,7 +120,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { ...@@ -116,7 +120,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
const MojoHandleSignals* signals, const MojoHandleSignals* signals,
uint32_t num_handles, uint32_t num_handles,
MojoDeadline deadline, MojoDeadline deadline,
uint32_t* result_index); uint32_t* result_index,
HandleSignalsState* signals_states);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
......
...@@ -16,6 +16,9 @@ namespace mojo { ...@@ -16,6 +16,9 @@ namespace mojo {
namespace system { namespace system {
namespace { namespace {
const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
typedef test::CoreTestBase CoreTest; typedef test::CoreTestBase CoreTest;
TEST_F(CoreTest, GetTimeTicksNow) { TEST_F(CoreTest, GetTimeTicksNow) {
...@@ -103,23 +106,79 @@ TEST_F(CoreTest, Basic) { ...@@ -103,23 +106,79 @@ TEST_F(CoreTest, Basic) {
EXPECT_EQ(1u, info.GetEndReadDataCallCount()); EXPECT_EQ(1u, info.GetEndReadDataCallCount());
EXPECT_EQ(0u, info.GetAddWaiterCallCount()); EXPECT_EQ(0u, info.GetAddWaiterCallCount());
EXPECT_EQ( EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
MOJO_RESULT_FAILED_PRECONDITION, core()->Wait(h,
core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE)); ~MOJO_HANDLE_SIGNAL_NONE,
MOJO_DEADLINE_INDEFINITE,
NullUserPointer()));
EXPECT_EQ(1u, info.GetAddWaiterCallCount()); EXPECT_EQ(1u, info.GetAddWaiterCallCount());
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0)); core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0, NullUserPointer()));
EXPECT_EQ(2u, info.GetAddWaiterCallCount()); EXPECT_EQ(2u, info.GetAddWaiterCallCount());
MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000)); core()->Wait(h,
~MOJO_HANDLE_SIGNAL_NONE,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&hss)));
EXPECT_EQ(3u, info.GetAddWaiterCallCount()); EXPECT_EQ(3u, info.GetAddWaiterCallCount());
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
EXPECT_EQ(
MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, NullUserPointer()));
EXPECT_EQ(4u, info.GetAddWaiterCallCount());
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(
h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, MakeUserPointer(&hss)));
EXPECT_EQ(5u, info.GetAddWaiterCallCount());
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
MojoHandleSignals handle_signals = ~MOJO_HANDLE_SIGNAL_NONE; MojoHandleSignals handle_signals = ~MOJO_HANDLE_SIGNAL_NONE;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->WaitMany(MakeUserPointer(&h), core()->WaitMany(MakeUserPointer(&h),
MakeUserPointer(&handle_signals), MakeUserPointer(&handle_signals),
1, 1,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
EXPECT_EQ(4u, info.GetAddWaiterCallCount()); NullUserPointer(),
NullUserPointer()));
EXPECT_EQ(6u, info.GetAddWaiterCallCount());
uint32_t result_index = static_cast<uint32_t>(-1);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->WaitMany(MakeUserPointer(&h),
MakeUserPointer(&handle_signals),
1,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
NullUserPointer()));
EXPECT_EQ(7u, info.GetAddWaiterCallCount());
EXPECT_EQ(0u, result_index);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->WaitMany(MakeUserPointer(&h),
MakeUserPointer(&handle_signals),
1,
MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
MakeUserPointer(&hss)));
EXPECT_EQ(8u, info.GetAddWaiterCallCount());
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
result_index = static_cast<uint32_t>(-1);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->WaitMany(MakeUserPointer(&h),
MakeUserPointer(&handle_signals),
1,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(&hss)));
EXPECT_EQ(9u, info.GetAddWaiterCallCount());
EXPECT_EQ(0u, result_index);
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
EXPECT_EQ(0u, info.GetDtorCallCount()); EXPECT_EQ(0u, info.GetDtorCallCount());
EXPECT_EQ(0u, info.GetCloseCallCount()); EXPECT_EQ(0u, info.GetCloseCallCount());
...@@ -154,10 +213,36 @@ TEST_F(CoreTest, InvalidArguments) { ...@@ -154,10 +213,36 @@ TEST_F(CoreTest, InvalidArguments) {
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->Wait(MOJO_HANDLE_INVALID, core()->Wait(MOJO_HANDLE_INVALID,
~MOJO_HANDLE_SIGNAL_NONE, ~MOJO_HANDLE_SIGNAL_NONE,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
EXPECT_EQ( NullUserPointer()));
MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE)); core()->Wait(10,
~MOJO_HANDLE_SIGNAL_NONE,
MOJO_DEADLINE_INDEFINITE,
NullUserPointer()));
MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->Wait(MOJO_HANDLE_INVALID,
~MOJO_HANDLE_SIGNAL_NONE,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&hss)));
// On invalid argument, it shouldn't modify the handle signals state.
EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
hss.satisfied_signals);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
hss.satisfiable_signals);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->Wait(10,
~MOJO_HANDLE_SIGNAL_NONE,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&hss)));
// On invalid argument, it shouldn't modify the handle signals state.
EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
hss.satisfied_signals);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
hss.satisfiable_signals);
} }
// |WaitMany()|: // |WaitMany()|:
...@@ -169,48 +254,115 @@ TEST_F(CoreTest, InvalidArguments) { ...@@ -169,48 +254,115 @@ TEST_F(CoreTest, InvalidArguments) {
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
0, 0,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()));
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(NullUserPointer(), core()->WaitMany(NullUserPointer(),
MakeUserPointer(signals), MakeUserPointer(signals),
0, 0,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()));
// If |num_handles| is invalid, it should leave |result_index| and
// |signals_states| alone.
// (We use -1 internally; make sure that doesn't leak.)
uint32_t result_index = 123;
MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(NullUserPointer(),
MakeUserPointer(signals),
0,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(&hss)));
EXPECT_EQ(123u, result_index);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
hss.satisfied_signals);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
hss.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
NullUserPointer(), NullUserPointer(),
0, 0,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()));
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
1, 1,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()));
// But if a handle is bad, then it should set |result_index| but still leave
// |signals_states| alone.
result_index = static_cast<uint32_t>(-1);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals),
1,
MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(&hss)));
EXPECT_EQ(0u, result_index);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
hss.satisfied_signals);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
hss.satisfiable_signals);
MockHandleInfo info[2]; MockHandleInfo info[2];
handles[0] = CreateMockHandle(&info[0]); handles[0] = CreateMockHandle(&info[0]);
result_index = static_cast<uint32_t>(-1);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
1, 1,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(&hss)));
EXPECT_EQ(0u, result_index);
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
// On invalid argument, it'll leave |signals_states| alone.
result_index = static_cast<uint32_t>(-1);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
2, 2,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(&hss)));
EXPECT_EQ(1u, result_index);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
hss.satisfied_signals);
EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
hss.satisfiable_signals);
handles[1] = handles[0] + 1; // Invalid handle. handles[1] = handles[0] + 1; // Invalid handle.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
2, 2,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()));
handles[1] = CreateMockHandle(&info[1]); handles[1] = CreateMockHandle(&info[1]);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->WaitMany(MakeUserPointer(handles), core()->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
2, 2,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()));
// TODO(vtl): Test one where we get "failed precondition" only for the
// second handle (and the first one is valid to wait on).
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[0])); EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[0]));
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1])); EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1]));
...@@ -386,19 +538,24 @@ TEST_F(CoreTest, InvalidArgumentsDeath) { ...@@ -386,19 +538,24 @@ TEST_F(CoreTest, InvalidArgumentsDeath) {
// |WaitMany()|: // |WaitMany()|:
{ {
MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; MojoHandle handle = MOJO_HANDLE_INVALID;
MojoHandleSignals signals[2] = {~MOJO_HANDLE_SIGNAL_NONE, MojoHandleSignals signals = ~MOJO_HANDLE_SIGNAL_NONE;
~MOJO_HANDLE_SIGNAL_NONE};
EXPECT_DEATH_IF_SUPPORTED(core()->WaitMany(NullUserPointer(), EXPECT_DEATH_IF_SUPPORTED(core()->WaitMany(NullUserPointer(),
MakeUserPointer(signals), MakeUserPointer(&signals),
1, 1,
MOJO_DEADLINE_INDEFINITE), MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()),
kMemoryCheckFailedRegex); kMemoryCheckFailedRegex);
EXPECT_DEATH_IF_SUPPORTED(core()->WaitMany(MakeUserPointer(handles), EXPECT_DEATH_IF_SUPPORTED(core()->WaitMany(MakeUserPointer(&handle),
NullUserPointer(), NullUserPointer(),
1, 1,
MOJO_DEADLINE_INDEFINITE), MOJO_DEADLINE_INDEFINITE,
NullUserPointer(),
NullUserPointer()),
kMemoryCheckFailedRegex); kMemoryCheckFailedRegex);
// TODO(vtl): |result_index| and |signals_states| are optional. Test them
// with non-null invalid pointers?
} }
// |CreateMessagePipe()|: // |CreateMessagePipe()|:
...@@ -465,6 +622,8 @@ TEST_F(CoreTest, InvalidArgumentsDeath) { ...@@ -465,6 +622,8 @@ TEST_F(CoreTest, InvalidArgumentsDeath) {
TEST_F(CoreTest, MessagePipe) { TEST_F(CoreTest, MessagePipe) {
MojoHandle h[2]; MojoHandle h[2];
MojoHandleSignalsState hss[2];
uint32_t result_index;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
...@@ -478,9 +637,23 @@ TEST_F(CoreTest, MessagePipe) { ...@@ -478,9 +637,23 @@ TEST_F(CoreTest, MessagePipe) {
// Neither should be readable. // Neither should be readable.
MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE,
MOJO_HANDLE_SIGNAL_READABLE}; MOJO_HANDLE_SIGNAL_READABLE};
EXPECT_EQ( result_index = static_cast<uint32_t>(-1);
MOJO_RESULT_DEADLINE_EXCEEDED, hss[0] = kEmptyMojoHandleSignalsState;
core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, 0)); hss[1] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
core()->WaitMany(MakeUserPointer(h),
MakeUserPointer(signals),
2,
0,
MakeUserPointer(&result_index),
MakeUserPointer(hss)));
EXPECT_EQ(static_cast<uint32_t>(-1), result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[1].satisfiable_signals);
// Try to read anyway. // Try to read anyway.
char buffer[1] = {'a'}; char buffer[1] = {'a'};
...@@ -497,19 +670,45 @@ TEST_F(CoreTest, MessagePipe) { ...@@ -497,19 +670,45 @@ TEST_F(CoreTest, MessagePipe) {
EXPECT_EQ(1u, buffer_size); EXPECT_EQ(1u, buffer_size);
// Both should be writable. // Both should be writable.
hss[0] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h[0], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000)); core()->Wait(h[0],
MOJO_HANDLE_SIGNAL_WRITABLE,
1000000000,
MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfiable_signals);
hss[0] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000)); core()->Wait(h[1],
MOJO_HANDLE_SIGNAL_WRITABLE,
1000000000,
MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfiable_signals);
// Also check that |h[1]| is writable using |WaitMany()|. // Also check that |h[1]| is writable using |WaitMany()|.
signals[0] = MOJO_HANDLE_SIGNAL_READABLE; signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
signals[1] = MOJO_HANDLE_SIGNAL_WRITABLE; signals[1] = MOJO_HANDLE_SIGNAL_WRITABLE;
EXPECT_EQ(1, result_index = static_cast<uint32_t>(-1);
hss[0] = kEmptyMojoHandleSignalsState;
hss[1] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK,
core()->WaitMany(MakeUserPointer(h), core()->WaitMany(MakeUserPointer(h),
MakeUserPointer(signals), MakeUserPointer(signals),
2, 2,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(hss)));
EXPECT_EQ(1u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[1].satisfiable_signals);
// Write to |h[1]|. // Write to |h[1]|.
buffer[0] = 'b'; buffer[0] = 'b';
...@@ -524,11 +723,24 @@ TEST_F(CoreTest, MessagePipe) { ...@@ -524,11 +723,24 @@ TEST_F(CoreTest, MessagePipe) {
// Check that |h[0]| is now readable. // Check that |h[0]| is now readable.
signals[0] = MOJO_HANDLE_SIGNAL_READABLE; signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
signals[1] = MOJO_HANDLE_SIGNAL_READABLE; signals[1] = MOJO_HANDLE_SIGNAL_READABLE;
EXPECT_EQ(0, result_index = static_cast<uint32_t>(-1);
hss[0] = kEmptyMojoHandleSignalsState;
hss[1] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK,
core()->WaitMany(MakeUserPointer(h), core()->WaitMany(MakeUserPointer(h),
MakeUserPointer(signals), MakeUserPointer(signals),
2, 2,
MOJO_DEADLINE_INDEFINITE)); MOJO_DEADLINE_INDEFINITE,
MakeUserPointer(&result_index),
MakeUserPointer(hss)));
EXPECT_EQ(0u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[1].satisfiable_signals);
// Read from |h[0]|. // Read from |h[0]|.
// First, get only the size. // First, get only the size.
...@@ -555,8 +767,14 @@ TEST_F(CoreTest, MessagePipe) { ...@@ -555,8 +767,14 @@ TEST_F(CoreTest, MessagePipe) {
EXPECT_EQ(1u, buffer_size); EXPECT_EQ(1u, buffer_size);
// |h[0]| should no longer be readable. // |h[0]| should no longer be readable.
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, hss[0] = kEmptyMojoHandleSignalsState;
core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0)); EXPECT_EQ(
MOJO_RESULT_DEADLINE_EXCEEDED,
core()->Wait(
h[0], MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfiable_signals);
// Write to |h[0]|. // Write to |h[0]|.
buffer[0] = 'd'; buffer[0] = 'd';
...@@ -572,12 +790,24 @@ TEST_F(CoreTest, MessagePipe) { ...@@ -572,12 +790,24 @@ TEST_F(CoreTest, MessagePipe) {
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[0])); EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[0]));
// Check that |h[1]| is no longer writable (and will never be). // Check that |h[1]| is no longer writable (and will never be).
hss[0] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000)); core()->Wait(h[1],
MOJO_HANDLE_SIGNAL_WRITABLE,
1000000000,
MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
// Check that |h[1]| is still readable (for the moment). // Check that |h[1]| is still readable (for the moment).
hss[0] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
// Discard a message from |h[1]|. // Discard a message from |h[1]|.
EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
...@@ -589,8 +819,14 @@ TEST_F(CoreTest, MessagePipe) { ...@@ -589,8 +819,14 @@ TEST_F(CoreTest, MessagePipe) {
MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
// |h[1]| is no longer readable (and will never be). // |h[1]| is no longer readable (and will never be).
hss[0] = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss[0])));
EXPECT_EQ(0u, hss[0].satisfied_signals);
EXPECT_EQ(0u, hss[0].satisfiable_signals);
// Try writing to |h[1]|. // Try writing to |h[1]|.
buffer[0] = 'e'; buffer[0] = 'e';
...@@ -616,6 +852,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { ...@@ -616,6 +852,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
uint32_t num_bytes; uint32_t num_bytes;
MojoHandle handles[10]; MojoHandle handles[10];
uint32_t num_handles; uint32_t num_handles;
MojoHandleSignalsState hss;
MojoHandle h_received; MojoHandle h_received;
MojoHandle h_passing[2]; MojoHandle h_passing[2];
...@@ -632,9 +869,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { ...@@ -632,9 +869,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
NullUserPointer(), NullUserPointer(),
0, 0,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
EXPECT_EQ( hss = kEmptyMojoHandleSignalsState;
MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_passing[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -679,8 +923,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { ...@@ -679,8 +923,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
NullUserPointer(), NullUserPointer(),
0, 0,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_passed[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_passed[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -702,9 +954,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { ...@@ -702,9 +954,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
MakeUserPointer(&h_passed[1]), MakeUserPointer(&h_passed[1]),
1, 1,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
EXPECT_EQ( hss = kEmptyMojoHandleSignalsState;
MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_passing[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -738,8 +997,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { ...@@ -738,8 +997,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
NullUserPointer(), NullUserPointer(),
0, 0,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_received,
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -761,6 +1028,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { ...@@ -761,6 +1028,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
TEST_F(CoreTest, DataPipe) { TEST_F(CoreTest, DataPipe) {
MojoHandle ph, ch; // p is for producer and c is for consumer. MojoHandle ph, ch; // p is for producer and c is for consumer.
MojoHandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->CreateDataPipe( core()->CreateDataPipe(
...@@ -771,15 +1039,32 @@ TEST_F(CoreTest, DataPipe) { ...@@ -771,15 +1039,32 @@ TEST_F(CoreTest, DataPipe) {
EXPECT_NE(ph, ch); EXPECT_NE(ph, ch);
// Producer should be never-readable, but already writable. // Producer should be never-readable, but already writable.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, hss = kEmptyMojoHandleSignalsState;
core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0)); EXPECT_EQ(
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(
MOJO_RESULT_OK,
core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
// Consumer should be never-writable, and not yet readable. // Consumer should be never-writable, and not yet readable.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, hss = kFullMojoHandleSignalsState;
core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); EXPECT_EQ(
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0)); core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(
MOJO_RESULT_DEADLINE_EXCEEDED,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
// Write. // Write.
char elements[2] = {'A', 'B'}; char elements[2] = {'A', 'B'};
...@@ -792,7 +1077,12 @@ TEST_F(CoreTest, DataPipe) { ...@@ -792,7 +1077,12 @@ TEST_F(CoreTest, DataPipe) {
EXPECT_EQ(2u, num_bytes); EXPECT_EQ(2u, num_bytes);
// Consumer should now be readable. // Consumer should now be readable.
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0)); hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(
MOJO_RESULT_OK,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
// Read one character. // Read one character.
elements[0] = -1; elements[0] = -1;
...@@ -884,8 +1174,12 @@ TEST_F(CoreTest, DataPipe) { ...@@ -884,8 +1174,12 @@ TEST_F(CoreTest, DataPipe) {
EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 2u)); EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 2u));
// Consumer should now be no longer readable. // Consumer should now be no longer readable.
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, hss = kFullMojoHandleSignalsState;
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0)); EXPECT_EQ(
MOJO_RESULT_DEADLINE_EXCEEDED,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
// TODO(vtl): More. // TODO(vtl): More.
...@@ -893,8 +1187,12 @@ TEST_F(CoreTest, DataPipe) { ...@@ -893,8 +1187,12 @@ TEST_F(CoreTest, DataPipe) {
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph)); EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph));
// The consumer should now be never-readable. // The consumer should now be never-readable.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, hss = kFullMojoHandleSignalsState;
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0)); EXPECT_EQ(
MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch)); EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch));
} }
...@@ -910,6 +1208,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -910,6 +1208,7 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
uint32_t num_bytes; uint32_t num_bytes;
MojoHandle handles[10]; MojoHandle handles[10];
uint32_t num_handles; uint32_t num_handles;
MojoHandleSignalsState hss;
MojoHandle h_passing[2]; MojoHandle h_passing[2];
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -930,9 +1229,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -930,9 +1229,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
MakeUserPointer(&ch), MakeUserPointer(&ch),
1, 1,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
EXPECT_EQ( hss = kEmptyMojoHandleSignalsState;
MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_passing[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -965,8 +1271,14 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -965,8 +1271,14 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
UserPointer<const void>(kWorld), UserPointer<const void>(kWorld),
MakeUserPointer(&num_bytes), MakeUserPointer(&num_bytes),
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(ch_received,
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->ReadData(ch_received, core()->ReadData(ch_received,
...@@ -984,9 +1296,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -984,9 +1296,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
MakeUserPointer(&ph), MakeUserPointer(&ph),
1, 1,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
EXPECT_EQ( hss = kEmptyMojoHandleSignalsState;
MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_passing[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -1019,8 +1338,14 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -1019,8 +1338,14 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
UserPointer<const void>(kHello), UserPointer<const void>(kHello),
MakeUserPointer(&num_bytes), MakeUserPointer(&num_bytes),
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(ch_received,
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->ReadData(ch_received, core()->ReadData(ch_received,
...@@ -1061,9 +1386,11 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -1061,9 +1386,11 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
1, 1,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
ch = MOJO_HANDLE_INVALID; ch = MOJO_HANDLE_INVALID;
EXPECT_EQ( EXPECT_EQ(MOJO_RESULT_OK,
MOJO_RESULT_OK, core()->Wait(h_passing[1],
core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
NullUserPointer()));
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
...@@ -1084,8 +1411,13 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -1084,8 +1411,13 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1)); EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1));
// Wait for |ch| to be readable. // Wait for |ch| to be readable.
EXPECT_EQ(MOJO_RESULT_OK, hss = kEmptyMojoHandleSignalsState;
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); EXPECT_EQ(
MOJO_RESULT_OK,
core()->Wait(
ch, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
// Make sure that |ch| can't be sent if it's in a two-phase read. // Make sure that |ch| can't be sent if it's in a two-phase read.
const void* read_ptr = NULL; const void* read_ptr = NULL;
...@@ -1112,9 +1444,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { ...@@ -1112,9 +1444,16 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
1, 1,
MOJO_WRITE_MESSAGE_FLAG_NONE)); MOJO_WRITE_MESSAGE_FLAG_NONE));
ph = MOJO_HANDLE_INVALID; ph = MOJO_HANDLE_INVALID;
EXPECT_EQ( hss = kEmptyMojoHandleSignalsState;
MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000)); core()->Wait(h_passing[1],
MOJO_HANDLE_SIGNAL_READABLE,
1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfiable_signals);
num_bytes = kBufferSize; num_bytes = kBufferSize;
num_handles = arraysize(handles); num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "mojo/system/entrypoints.h" #include "mojo/system/entrypoints.h"
#include "base/logging.h"
#include "mojo/public/c/system/buffer.h" #include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h" #include "mojo/public/c/system/functions.h"
...@@ -43,17 +44,23 @@ MojoResult MojoClose(MojoHandle handle) { ...@@ -43,17 +44,23 @@ MojoResult MojoClose(MojoHandle handle) {
MojoResult MojoWait(MojoHandle handle, MojoResult MojoWait(MojoHandle handle,
MojoHandleSignals signals, MojoHandleSignals signals,
MojoDeadline deadline) { MojoDeadline deadline) {
return g_core->Wait(handle, signals, deadline); return g_core->Wait(
handle, signals, deadline, mojo::system::NullUserPointer());
} }
MojoResult MojoWaitMany(const MojoHandle* handles, MojoResult MojoWaitMany(const MojoHandle* handles,
const MojoHandleSignals* signals, const MojoHandleSignals* signals,
uint32_t num_handles, uint32_t num_handles,
MojoDeadline deadline) { MojoDeadline deadline) {
return g_core->WaitMany(MakeUserPointer(handles), uint32_t result_index = static_cast<uint32_t>(-1);
MojoResult result = g_core->WaitMany(MakeUserPointer(handles),
MakeUserPointer(signals), MakeUserPointer(signals),
num_handles, num_handles,
deadline); deadline,
MakeUserPointer(&result_index),
mojo::system::NullUserPointer());
return (result == MOJO_RESULT_OK) ? static_cast<MojoResult>(result_index)
: result;
} }
MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options,
......
...@@ -35,6 +35,7 @@ void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer) { ...@@ -35,6 +35,7 @@ void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer) {
// Explicitly instantiate the sizes we need. Add instantiations as needed. // Explicitly instantiate the sizes we need. Add instantiations as needed.
template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<1, 1>(const void*); template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<1, 1>(const void*);
template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 4>(const void*); template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 4>(const void*);
template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 4>(const void*);
template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 8>(const void*); template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 8>(const void*);
template <size_t size, size_t alignment> template <size_t size, size_t alignment>
...@@ -49,6 +50,8 @@ template void MOJO_SYSTEM_IMPL_EXPORT ...@@ -49,6 +50,8 @@ template void MOJO_SYSTEM_IMPL_EXPORT
CheckUserPointerWithCount<1, 1>(const void*, size_t); CheckUserPointerWithCount<1, 1>(const void*, size_t);
template void MOJO_SYSTEM_IMPL_EXPORT template void MOJO_SYSTEM_IMPL_EXPORT
CheckUserPointerWithCount<4, 4>(const void*, size_t); CheckUserPointerWithCount<4, 4>(const void*, size_t);
template void MOJO_SYSTEM_IMPL_EXPORT
CheckUserPointerWithCount<8, 4>(const void*, size_t);
template void MOJO_SYSTEM_IMPL_EXPORT template void MOJO_SYSTEM_IMPL_EXPORT
CheckUserPointerWithCount<8, 8>(const void*, size_t); CheckUserPointerWithCount<8, 8>(const void*, size_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment