Add thunks for wait set operations, together with public tests. R=vardhan@google.com BUG=#350 Review URL: https://codereview.chromium.org/2106433002 .
diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc index c636e44..7f29a5c 100644 --- a/mojo/edk/embedder/entrypoints.cc +++ b/mojo/edk/embedder/entrypoints.cc
@@ -218,4 +218,33 @@ return g_core->UnmapBuffer(MakeUserPointer(buffer)); } +MojoResult MojoCreateWaitSet(const struct MojoCreateWaitSetOptions* options, + MojoHandle* handle) { + return g_core->CreateWaitSet(MakeUserPointer(options), + MakeUserPointer(handle)); +} + +MojoResult MojoWaitSetAdd(MojoHandle wait_set_handle, + MojoHandle handle, + MojoHandleSignals signals, + uint64_t cookie, + const struct MojoWaitSetAddOptions* options) { + return g_core->WaitSetAdd(wait_set_handle, handle, signals, cookie, + MakeUserPointer(options)); +} + +MojoResult MojoWaitSetRemove(MojoHandle wait_set_handle, uint64_t cookie) { + return g_core->WaitSetRemove(wait_set_handle, cookie); +} + +MojoResult MojoWaitSetWait(MojoHandle wait_set_handle, + MojoDeadline deadline, + uint32_t* num_results, + struct MojoWaitSetResult* results, + uint32_t* max_results) { + return g_core->WaitSetWait( + wait_set_handle, deadline, MakeUserPointer(num_results), + MakeUserPointer(results), MakeUserPointer(max_results)); +} + } // extern "C"
diff --git a/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc b/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc index 33d7269..baad030 100644 --- a/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc +++ b/mojo/nacl/nonsfi/irt_mojo_nonsfi.cc
@@ -49,6 +49,10 @@ MojoGetBufferInformation, MojoMapBuffer, MojoUnmapBuffer, + MojoCreateWaitSet, + MojoWaitSetAdd, + MojoWaitSetRemove, + MojoWaitSetWait, }; const struct nacl_irt_mgl kIrtMGL = {
diff --git a/mojo/public/c/system/tests/BUILD.gn b/mojo/public/c/system/tests/BUILD.gn index 95c8f4e..6703571 100644 --- a/mojo/public/c/system/tests/BUILD.gn +++ b/mojo/public/c/system/tests/BUILD.gn
@@ -21,6 +21,7 @@ "message_pipe_unittest.cc", "result_unittest.cc", "time_unittest.cc", + "wait_set_unittest.cc", "wait_unittest.cc", ]
diff --git a/mojo/public/c/system/tests/buffer_unittest.cc b/mojo/public/c/system/tests/buffer_unittest.cc index 6e32f2c..9d29dc9 100644 --- a/mojo/public/c/system/tests/buffer_unittest.cc +++ b/mojo/public/c/system/tests/buffer_unittest.cc
@@ -6,6 +6,7 @@ // mojo/public/c/system/buffer.h). #include "mojo/public/c/system/buffer.h" + #include "mojo/public/c/system/handle.h" #include "mojo/public/c/system/result.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/mojo/public/c/system/tests/data_pipe_unittest.cc b/mojo/public/c/system/tests/data_pipe_unittest.cc index c319c36..fb89e31 100644 --- a/mojo/public/c/system/tests/data_pipe_unittest.cc +++ b/mojo/public/c/system/tests/data_pipe_unittest.cc
@@ -5,9 +5,10 @@ // This file tests the C data pipe API (the functions declared in // mojo/public/c/system/data_pipe.h). +#include "mojo/public/c/system/data_pipe.h" + #include <string.h> -#include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/handle.h" #include "mojo/public/c/system/result.h" #include "mojo/public/c/system/wait.h"
diff --git a/mojo/public/c/system/tests/handle_unittest.cc b/mojo/public/c/system/tests/handle_unittest.cc index 0de5748..22098ea 100644 --- a/mojo/public/c/system/tests/handle_unittest.cc +++ b/mojo/public/c/system/tests/handle_unittest.cc
@@ -8,6 +8,7 @@ // handles. #include "mojo/public/c/system/handle.h" + #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/result.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/mojo/public/c/system/tests/message_pipe_unittest.cc b/mojo/public/c/system/tests/message_pipe_unittest.cc index 9f6166f..2c61f9f 100644 --- a/mojo/public/c/system/tests/message_pipe_unittest.cc +++ b/mojo/public/c/system/tests/message_pipe_unittest.cc
@@ -5,9 +5,10 @@ // This file tests the C message pipe API (the functions declared in // mojo/public/c/system/message_pipe.h). +#include "mojo/public/c/system/message_pipe.h" + #include "mojo/public/c/system/buffer.h" #include "mojo/public/c/system/handle.h" -#include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/result.h" #include "mojo/public/c/system/wait.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/mojo/public/c/system/tests/result_unittest.cc b/mojo/public/c/system/tests/result_unittest.cc index fca6f04..1aa7934 100644 --- a/mojo/public/c/system/tests/result_unittest.cc +++ b/mojo/public/c/system/tests/result_unittest.cc
@@ -6,6 +6,7 @@ // mojo/public/c/system/result.h). #include "mojo/public/c/system/result.h" + #include "testing/gtest/include/gtest/gtest.h" namespace {
diff --git a/mojo/public/c/system/tests/time_unittest.cc b/mojo/public/c/system/tests/time_unittest.cc index cbf2c61..4a6467e 100644 --- a/mojo/public/c/system/tests/time_unittest.cc +++ b/mojo/public/c/system/tests/time_unittest.cc
@@ -6,6 +6,7 @@ // mojo/public/c/system/time.h). #include "mojo/public/c/system/time.h" + #include "testing/gtest/include/gtest/gtest.h" namespace {
diff --git a/mojo/public/c/system/tests/wait_set_unittest.cc b/mojo/public/c/system/tests/wait_set_unittest.cc new file mode 100644 index 0000000..91ca6dc --- /dev/null +++ b/mojo/public/c/system/tests/wait_set_unittest.cc
@@ -0,0 +1,390 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file tests the C wait set API (the functions declared in +// mojo/public/c/system/wait_set.h). + +#include "mojo/public/c/system/wait_set.h" + +#include "mojo/public/c/system/handle.h" +#include "mojo/public/c/system/message_pipe.h" +#include "mojo/public/c/system/result.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const MojoHandleRights kDefaultWaitSetHandleRights = + MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; + +TEST(WaitSetTest, InvalidHandle) { + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoWaitSetAdd(MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID, + MOJO_HANDLE_SIGNAL_READABLE, 123u, nullptr)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoWaitSetRemove(MOJO_HANDLE_INVALID, 123u)); + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoWaitSetWait(MOJO_HANDLE_INVALID, MOJO_DEADLINE_INDEFINITE, + &num_results, results, nullptr)); + + // Also check |MojoWaitSetAdd()| with a valid handle to be added. + MojoHandle mph0 = MOJO_HANDLE_INVALID; + MojoHandle mph1 = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoWaitSetAdd(MOJO_HANDLE_INVALID, mph0, + MOJO_HANDLE_SIGNAL_READABLE, 123u, nullptr)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); +} + +TEST(WaitSetTest, Create) { + // Invalid options. + { + static constexpr MojoCreateWaitSetOptions kOptions = {}; + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCreateWaitSet(&kOptions, &h)); + EXPECT_EQ(MOJO_HANDLE_INVALID, h); + } + + // Options with unknown flags. + { + static constexpr MojoCreateWaitSetOptions kOptions = { + static_cast<uint32_t>(sizeof(MojoCreateWaitSetOptions)), + ~static_cast<MojoCreateWaitSetOptionsFlags>(0), + }; + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, MojoCreateWaitSet(&kOptions, &h)); + EXPECT_EQ(MOJO_HANDLE_INVALID, h); + } + + // With non-null options. + { + static constexpr MojoCreateWaitSetOptions kOptions = { + static_cast<uint32_t>(sizeof(MojoCreateWaitSetOptions)), + static_cast<MojoCreateWaitSetOptionsFlags>(0), + }; + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(&kOptions, &h)); + EXPECT_NE(h, MOJO_HANDLE_INVALID); + + // Should have the correct rights. + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h, &rights)); + EXPECT_EQ(kDefaultWaitSetHandleRights, rights); + + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); + } + + // With null options. + { + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); + EXPECT_NE(h, MOJO_HANDLE_INVALID); + + // Should have the correct rights. + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h, &rights)); + EXPECT_EQ(kDefaultWaitSetHandleRights, rights); + + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); + } +} + +TEST(WaitSetTest, Add) { + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); + EXPECT_NE(h, MOJO_HANDLE_INVALID); + + // Add invalid handle. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoWaitSetAdd(h, MOJO_HANDLE_INVALID, MOJO_HANDLE_SIGNAL_READABLE, + 0u, nullptr)); + + // Some handles that we can add. + MojoHandle mph0 = MOJO_HANDLE_INVALID; + MojoHandle mph1 = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); + + // Add with invalid options. + { + static constexpr MojoWaitSetAddOptions kOptions = {}; + EXPECT_EQ( + MOJO_RESULT_INVALID_ARGUMENT, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 0u, &kOptions)); + } + + // Add with options with unknown flags. + { + static constexpr MojoWaitSetAddOptions kOptions = { + static_cast<uint32_t>(sizeof(MojoWaitSetAddOptions)), + ~static_cast<MojoWaitSetAddOptionsFlags>(0), + }; + EXPECT_EQ( + MOJO_RESULT_UNIMPLEMENTED, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 0u, &kOptions)); + } + + // Add with options. + { + static constexpr MojoWaitSetAddOptions kOptions = { + static_cast<uint32_t>(sizeof(MojoWaitSetAddOptions)), + static_cast<MojoWaitSetAddOptionsFlags>(0), + }; + EXPECT_EQ( + MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 0u, &kOptions)); + } + + // Add with null options. + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_WRITABLE, 1u, nullptr)); + + // Add a handle that's already present, with a different cookie. + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 2u, nullptr)); + + // Try to add a cookie that's already present. + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_READABLE, 0u, nullptr)); + + // Can close things in a wait set. + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); + + // Can close a wait set with unclosed handles in it. + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); + + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); +} + +TEST(WaitSetTest, Remove) { + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); + EXPECT_NE(h, MOJO_HANDLE_INVALID); + + // Some handles that we can add. + MojoHandle mph0 = MOJO_HANDLE_INVALID; + MojoHandle mph1 = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); + + // Try to remove something that's not there. + EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoWaitSetRemove(h, 12u)); + + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 12u, nullptr)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_READABLE, 34u, nullptr)); + + // Remove something. + EXPECT_EQ(MOJO_RESULT_OK, MojoWaitSetRemove(h, 12u)); + + // Can't remove it again. + EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoWaitSetRemove(h, 12u)); + + // Now can add it again. + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_WRITABLE, 12u, nullptr)); + + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); +} + +// Helper to check if an array of |MojoWaitSetResult|s has a result |r| for the +// given cookie, in which case: +// - |r.wait_result| must equal |wait_result|. +// - If |wait_result| is |MOJO_RESULT_OK| or +// |MOJO_RESULT_FAILED_PRECONDITION|, then +// - |r.signals_state.satisfied_signals & signals| must equal +// |signals_state.satisfied_signals & signals|, and +// - |r.signals_state.satisfiable & signals| must equal +// |signals_state.satisfiable_signals & signals|. +// - Otherwise, |r.signals_state| must equals |signals_state|. +// (This doesn't check that the result is unique; you should check |num_results| +// versus the expect number and exhaustively check every expected result.) +bool CheckHasResult(uint32_t num_results, + const MojoWaitSetResult* results, + uint64_t cookie, + MojoHandleSignals signals, + MojoResult wait_result, + const MojoHandleSignalsState& signals_state) { + for (uint32_t i = 0; i < num_results; i++) { + if (results[i].cookie == cookie) { + EXPECT_EQ(wait_result, results[i].wait_result) << cookie; + EXPECT_EQ(0u, results[i].reserved) << cookie; + if (wait_result == MOJO_RESULT_OK || + wait_result == MOJO_RESULT_FAILED_PRECONDITION) { + EXPECT_EQ(signals_state.satisfied_signals & signals, + results[i].signals_state.satisfied_signals & signals) + << cookie; + EXPECT_EQ(signals_state.satisfiable_signals & signals, + results[i].signals_state.satisfiable_signals & signals) + << cookie; + } else { + EXPECT_EQ(signals_state.satisfied_signals, + results[i].signals_state.satisfied_signals) + << cookie; + EXPECT_EQ(signals_state.satisfiable_signals, + results[i].signals_state.satisfiable_signals) + << cookie; + } + return true; + } + } + return false; +} + +TEST(WaitSetTest, Wait) { + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); + EXPECT_NE(h, MOJO_HANDLE_INVALID); + + // Nothing in the wait set. + { + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + uint32_t max_results = 1234u; + EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, + MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, + results, &max_results)); + EXPECT_EQ(10u, num_results); + EXPECT_EQ(1234u, max_results); + } + + // Ditto, with non-zero deadline and null |max_results|. + { + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, + MojoWaitSetWait(h, static_cast<MojoDeadline>(1000), &num_results, + results, nullptr)); + EXPECT_EQ(10u, num_results); + } + + // Some handles that we can add. + MojoHandle mph0 = MOJO_HANDLE_INVALID; + MojoHandle mph1 = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); + + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 1u, nullptr)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_READABLE, 2u, nullptr)); + + // Will still time out. + { + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, + MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, + results, nullptr)); + EXPECT_EQ(10u, num_results); + } + + // Write to |mph1|. + EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(mph1, nullptr, 0, nullptr, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE)); + + // Should get cookie 1. + { + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + uint32_t max_results = 1234u; + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, + results, &max_results)); + EXPECT_EQ(1u, num_results); + EXPECT_TRUE(CheckHasResult( + num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, MOJO_RESULT_OK, + MojoHandleSignalsState{ + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); + EXPECT_EQ(1u, max_results); + } + + // Non-zero deadline, null |max_results|; should still get cookie 1. + { + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetWait(h, static_cast<MojoDeadline>(1000), &num_results, + results, nullptr)); + EXPECT_EQ(1u, num_results); + EXPECT_TRUE(CheckHasResult( + num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, MOJO_RESULT_OK, + MojoHandleSignalsState{ + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); + } + + // Zero |num_results|. + { + uint32_t num_results = 0u; + uint32_t max_results = 1234u; + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, + nullptr, &max_results)); + EXPECT_EQ(0u, num_results); + EXPECT_EQ(1u, max_results); + } + + // Add another entry waiting for readability on |mph0|. + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE | + MOJO_HANDLE_SIGNAL_WRITABLE, + 3u, nullptr)); + + { + uint32_t num_results = 10u; + uint32_t max_results = 1234u; + MojoWaitSetResult results[10] = {}; + EXPECT_EQ(MOJO_RESULT_OK, + MojoWaitSetWait(h, MOJO_DEADLINE_INDEFINITE, &num_results, + results, &max_results)); + EXPECT_EQ(2u, num_results); + EXPECT_TRUE(CheckHasResult( + num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, MOJO_RESULT_OK, + MojoHandleSignalsState{ + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); + EXPECT_TRUE(CheckHasResult( + num_results, results, 3u, + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_RESULT_OK, + MojoHandleSignalsState{ + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); + EXPECT_EQ(2u, max_results); + } + + // Close |mph0|. + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); + + { + uint32_t num_results = 10u; + MojoWaitSetResult results[10] = {}; + EXPECT_EQ(MOJO_RESULT_OK, MojoWaitSetWait(h, MOJO_DEADLINE_INDEFINITE, + &num_results, results, nullptr)); + EXPECT_EQ(3u, num_results); + EXPECT_TRUE( + CheckHasResult(num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_RESULT_CANCELLED, MojoHandleSignalsState())); + EXPECT_TRUE(CheckHasResult( + num_results, results, 2u, MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_RESULT_FAILED_PRECONDITION, MojoHandleSignalsState())); + EXPECT_TRUE(CheckHasResult( + num_results, results, 3u, + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_RESULT_CANCELLED, MojoHandleSignalsState())); + } + + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); +} + +// TODO(vtl): Add threaded tests, especially those that actually ... wait. + +} // namespace
diff --git a/mojo/public/c/system/tests/wait_unittest.cc b/mojo/public/c/system/tests/wait_unittest.cc index 1d26faa..541043e 100644 --- a/mojo/public/c/system/tests/wait_unittest.cc +++ b/mojo/public/c/system/tests/wait_unittest.cc
@@ -5,9 +5,10 @@ // This file tests the C wait API (the functions declared in // mojo/public/c/system/wait.h). +#include "mojo/public/c/system/wait.h" + #include "mojo/public/c/system/handle.h" #include "mojo/public/c/system/result.h" -#include "mojo/public/c/system/wait.h" #include "testing/gtest/include/gtest/gtest.h" namespace {
diff --git a/mojo/public/c/system/wait_set.h b/mojo/public/c/system/wait_set.h index 4fe91ca..10e82b7 100644 --- a/mojo/public/c/system/wait_set.h +++ b/mojo/public/c/system/wait_set.h
@@ -81,6 +81,8 @@ // |options| is non null and |*options| is invalid). // |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has // been reached. +// |MOJO_ERROR_CODE_UNIMPLEMENTED| if some unknown/unsupported option has been +// specified in |*options|. MojoResult MojoCreateWaitSet(const struct MojoCreateWaitSetOptions* MOJO_RESTRICT options, // Optional in. MojoHandle* handle); // Out. @@ -108,6 +110,8 @@ // some transaction. // |MOJO_RESULT_RESOURCE_EXHAUSTED| if the handle could not be added due to // hitting a system or quota limitation. +// |MOJO_ERROR_CODE_UNIMPLEMENTED| if some unknown/unsupported option has been +// specified in |*options|. MojoResult MojoWaitSetAdd(MojoHandle wait_set_handle, // In. MojoHandle handle, // In. MojoHandleSignals signals, // In.
diff --git a/mojo/public/platform/nacl/libmojo.cc b/mojo/public/platform/nacl/libmojo.cc index 81fb436..7dbdff8 100644 --- a/mojo/public/platform/nacl/libmojo.cc +++ b/mojo/public/platform/nacl/libmojo.cc
@@ -14,6 +14,7 @@ #include "mojo/public/c/system/result.h" #include "mojo/public/c/system/time.h" #include "mojo/public/c/system/wait.h" +#include "mojo/public/c/system/wait_set.h" #include "mojo/public/platform/nacl/mojo_irt.h" #include "native_client/src/untrusted/irt/irt.h" @@ -312,3 +313,41 @@ return irt_mojo->MojoUnmapBuffer(buffer); } +MojoResult MojoCreateWaitSet(const struct MojoCreateWaitSetOptions* options, + MojoHandle* handle) { + struct nacl_irt_mojo* irt_mojo = get_irt_mojo(); + if (!irt_mojo) + abort(); + return irt_mojo->MojoCreateWaitSet(options, handle); +} + +MojoResult MojoWaitSetAdd(MojoHandle wait_set_handle, + MojoHandle handle, + MojoHandleSignals signals, + uint64_t cookie, + const struct MojoWaitSetAddOptions* options) { + struct nacl_irt_mojo* irt_mojo = get_irt_mojo(); + if (!irt_mojo) + abort(); + return irt_mojo->MojoWaitSetAdd(wait_set_handle, handle, signals, cookie, + options); +} + +MojoResult MojoWaitSetRemove(MojoHandle wait_set_handle, uint64_t cookie) { + struct nacl_irt_mojo* irt_mojo = get_irt_mojo(); + if (!irt_mojo) + abort(); + return irt_mojo->MojoWaitSetRemove(wait_set_handle, cookie); +} + +MojoResult MojoWaitSetWait(MojoHandle wait_set_handle, + MojoDeadline deadline, + uint32_t* num_results, + struct MojoWaitSetResult* results, + uint32_t* max_results) { + struct nacl_irt_mojo* irt_mojo = get_irt_mojo(); + if (!irt_mojo) + abort(); + return irt_mojo->MojoWaitSetWait(wait_set_handle, deadline, num_results, + results, max_results); +}
diff --git a/mojo/public/platform/nacl/mojo_irt.h b/mojo/public/platform/nacl/mojo_irt.h index bc84139..ad23993 100644 --- a/mojo/public/platform/nacl/mojo_irt.h +++ b/mojo/public/platform/nacl/mojo_irt.h
@@ -11,6 +11,7 @@ #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/result.h" #include "mojo/public/c/system/time.h" +#include "mojo/public/c/system/wait_set.h" #define NACL_IRT_MOJO_v0_1 "nacl-irt-mojo-0.1" @@ -109,6 +110,20 @@ void** buffer, MojoMapBufferFlags flags); MojoResult (*MojoUnmapBuffer)(void* buffer); + MojoResult (*MojoCreateWaitSet)( + const struct MojoCreateWaitSetOptions* options, + MojoHandle* handle); + MojoResult (*MojoWaitSetAdd)(MojoHandle wait_set_handle, + MojoHandle handle, + MojoHandleSignals signals, + uint64_t cookie, + const struct MojoWaitSetAddOptions* options); + MojoResult (*MojoWaitSetRemove)(MojoHandle wait_set_handle, uint64_t cookie); + MojoResult (*MojoWaitSetWait)(MojoHandle wait_set_handle, + MojoDeadline deadline, + uint32_t* num_results, + struct MojoWaitSetResult* results, + uint32_t* max_results); }; #endif // MOJO_PUBLIC_PLATFORM_NACL_MOJO_IRT_H_
diff --git a/mojo/public/platform/native/system_thunks.c b/mojo/public/platform/native/system_thunks.c index c9517ff..2223c5c 100644 --- a/mojo/public/platform/native/system_thunks.c +++ b/mojo/public/platform/native/system_thunks.c
@@ -226,6 +226,36 @@ return g_thunks.UnmapBuffer(buffer); } +MojoResult MojoCreateWaitSet(const struct MojoCreateWaitSetOptions* options, + MojoHandle* handle) { + assert(g_thunks.CreateWaitSet); + return g_thunks.CreateWaitSet(options, handle); +} + +MojoResult MojoWaitSetAdd(MojoHandle wait_set_handle, + MojoHandle handle, + MojoHandleSignals signals, + uint64_t cookie, + const struct MojoWaitSetAddOptions* options) { + assert(g_thunks.WaitSetAdd); + return g_thunks.WaitSetAdd(wait_set_handle, handle, signals, cookie, options); +} + +MojoResult MojoWaitSetRemove(MojoHandle wait_set_handle, uint64_t cookie) { + assert(g_thunks.WaitSetRemove); + return g_thunks.WaitSetRemove(wait_set_handle, cookie); +} + +MojoResult MojoWaitSetWait(MojoHandle wait_set_handle, + MojoDeadline deadline, + uint32_t* num_results, + struct MojoWaitSetResult* results, + uint32_t* max_results) { + assert(g_thunks.WaitSetWait); + return g_thunks.WaitSetWait(wait_set_handle, deadline, num_results, results, + max_results); +} + THUNK_EXPORT size_t MojoSetSystemThunks(const struct MojoSystemThunks* system_thunks) { if (system_thunks->size >= sizeof(g_thunks))
diff --git a/mojo/public/platform/native/system_thunks.h b/mojo/public/platform/native/system_thunks.h index 03f2ccb..92260c7 100644 --- a/mojo/public/platform/native/system_thunks.h +++ b/mojo/public/platform/native/system_thunks.h
@@ -16,6 +16,7 @@ #include "mojo/public/c/system/result.h" #include "mojo/public/c/system/time.h" #include "mojo/public/c/system/wait.h" +#include "mojo/public/c/system/wait_set.h" // The embedder needs to bind the basic Mojo Core functions of a DSO to those of // the embedder when loading a DSO that is dependent on mojo_system. @@ -136,10 +137,22 @@ MojoHandle handle, MojoHandleRights rights_to_remove, MojoHandle* replacement_handle); + MojoResult (*CreateWaitSet)(const struct MojoCreateWaitSetOptions* options, + MojoHandle* handle); + MojoResult (*WaitSetAdd)(MojoHandle wait_set_handle, + MojoHandle handle, + MojoHandleSignals signals, + uint64_t cookie, + const struct MojoWaitSetAddOptions* options); + MojoResult (*WaitSetRemove)(MojoHandle wait_set_handle, uint64_t cookie); + MojoResult (*WaitSetWait)(MojoHandle wait_set_handle, + MojoDeadline deadline, + uint32_t* num_results, + struct MojoWaitSetResult* results, + uint32_t* max_results); }; #pragma pack(pop) - #ifdef __cplusplus // Intended to be called from the embedder. Returns a |MojoCore| initialized // to contain pointers to each of the embedder's MojoCore functions. @@ -173,6 +186,10 @@ MojoDuplicateHandleWithReducedRights, MojoDuplicateHandle, MojoReplaceHandleWithReducedRights, + MojoCreateWaitSet, + MojoWaitSetAdd, + MojoWaitSetRemove, + MojoWaitSetWait, }; return system_thunks; }