From d47588986e102d022f5cc92fdb2b16b5554830ca Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Wed, 16 Nov 2016 17:31:09 +0000 Subject: [PATCH] [Orc] Re-enable the RPC unit test disabled in r286917. This unit test infinite-looped on s390x due to a thread_yield being optimized out. I've updated the QueueChannel class (where thread_yield was called) to use a condition variable instead. This should cause the unit test to behave correctly. llvm-svn: 287121 --- .../ExecutionEngine/Orc/RPCUtilsTest.cpp | 291 +++++++++--------- 1 file changed, 143 insertions(+), 148 deletions(-) diff --git a/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp index d658780b036a..6da8b63c0d43 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp @@ -19,10 +19,11 @@ using namespace llvm::orc::rpc; class Queue : public std::queue { public: - std::mutex &getLock() { return Lock; } - + std::mutex &getMutex() { return M; } + std::condition_variable &getCondVar() { return CV; } private: - std::mutex Lock; + std::mutex M; + std::condition_variable CV; }; class QueueChannel : public RawByteChannel { @@ -31,26 +32,22 @@ public: : InQueue(InQueue), OutQueue(OutQueue) {} Error readBytes(char *Dst, unsigned Size) override { - while (Size != 0) { - // If there's nothing to read then yield. + std::unique_lock Lock(InQueue.getMutex()); + while (Size) { while (InQueue.empty()) - std::this_thread::yield(); - - // Lock the channel and read what we can. - std::lock_guard Lock(InQueue.getLock()); - while (!InQueue.empty() && Size) { - *Dst++ = InQueue.front(); - --Size; - InQueue.pop(); - } + InQueue.getCondVar().wait(Lock); + *Dst++ = InQueue.front(); + --Size; + InQueue.pop(); } return Error::success(); } Error appendBytes(const char *Src, unsigned Size) override { - std::lock_guard Lock(OutQueue.getLock()); + std::unique_lock Lock(OutQueue.getMutex()); while (Size--) OutQueue.push(*Src++); + OutQueue.getCondVar().notify_one(); return Error::success(); } @@ -93,162 +90,160 @@ private: QueueChannel C; }; -// FIXME: Temporarily disabled while the infnite loop discovered in r286639 is -// fixed (see llvm commits list discussion for that commit). -// TEST(DummyRPC, TestAsyncVoidBool) { -// Queue Q1, Q2; -// DummyRPCEndpoint Client(Q1, Q2); -// DummyRPCEndpoint Server(Q2, Q1); +TEST(DummyRPC, TestAsyncVoidBool) { + Queue Q1, Q2; + DummyRPCEndpoint Client(Q1, Q2); + DummyRPCEndpoint Server(Q2, Q1); -// std::thread ServerThread([&]() { -// Server.addHandler( -// [](bool B) { -// EXPECT_EQ(B, true) -// << "Server void(bool) received unexpected result"; -// }); + std::thread ServerThread([&]() { + Server.addHandler( + [](bool B) { + EXPECT_EQ(B, true) + << "Server void(bool) received unexpected result"; + }); -// { -// // Poke the server to handle the negotiate call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; -// } + { + // Poke the server to handle the negotiate call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; + } -// { -// // Poke the server to handle the VoidBool call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; -// } -// }); + { + // Poke the server to handle the VoidBool call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; + } + }); -// { -// // Make an async call. -// auto Err = Client.callAsync( -// [](Error Err) { -// EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed"; -// return Error::success(); -// }, true); -// EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)"; -// } + { + // Make an async call. + auto Err = Client.callAsync( + [](Error Err) { + EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed"; + return Error::success(); + }, true); + EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)"; + } -// { -// // Poke the client to process the result of the void(bool) call. -// auto Err = Client.handleOne(); -// EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; -// } + { + // Poke the client to process the result of the void(bool) call. + auto Err = Client.handleOne(); + EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; + } -// ServerThread.join(); -// } + ServerThread.join(); +} -// TEST(DummyRPC, TestAsyncIntInt) { -// Queue Q1, Q2; -// DummyRPCEndpoint Client(Q1, Q2); -// DummyRPCEndpoint Server(Q2, Q1); +TEST(DummyRPC, TestAsyncIntInt) { + Queue Q1, Q2; + DummyRPCEndpoint Client(Q1, Q2); + DummyRPCEndpoint Server(Q2, Q1); -// std::thread ServerThread([&]() { -// Server.addHandler( -// [](int X) -> int { -// EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result"; -// return 2 * X; -// }); + std::thread ServerThread([&]() { + Server.addHandler( + [](int X) -> int { + EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result"; + return 2 * X; + }); -// { -// // Poke the server to handle the negotiate call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; -// } + { + // Poke the server to handle the negotiate call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; + } -// { -// // Poke the server to handle the int(int) call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)"; -// } -// }); + { + // Poke the server to handle the int(int) call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)"; + } + }); -// { -// auto Err = Client.callAsync( -// [](Expected Result) { -// EXPECT_TRUE(!!Result) << "Async int(int) response handler failed"; -// EXPECT_EQ(*Result, 42) -// << "Async int(int) response handler received incorrect result"; -// return Error::success(); -// }, 21); -// EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)"; -// } + { + auto Err = Client.callAsync( + [](Expected Result) { + EXPECT_TRUE(!!Result) << "Async int(int) response handler failed"; + EXPECT_EQ(*Result, 42) + << "Async int(int) response handler received incorrect result"; + return Error::success(); + }, 21); + EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)"; + } -// { -// // Poke the client to process the result. -// auto Err = Client.handleOne(); -// EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; -// } + { + // Poke the client to process the result. + auto Err = Client.handleOne(); + EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)"; + } -// ServerThread.join(); -// } + ServerThread.join(); +} -// TEST(DummyRPC, TestSerialization) { -// Queue Q1, Q2; -// DummyRPCEndpoint Client(Q1, Q2); -// DummyRPCEndpoint Server(Q2, Q1); +TEST(DummyRPC, TestSerialization) { + Queue Q1, Q2; + DummyRPCEndpoint Client(Q1, Q2); + DummyRPCEndpoint Server(Q2, Q1); -// std::thread ServerThread([&]() { -// Server.addHandler( -// [&](int8_t S8, uint8_t U8, int16_t S16, uint16_t U16, -// int32_t S32, uint32_t U32, int64_t S64, uint64_t U64, -// bool B, std::string S, std::vector V) { + std::thread ServerThread([&]() { + Server.addHandler( + [&](int8_t S8, uint8_t U8, int16_t S16, uint16_t U16, + int32_t S32, uint32_t U32, int64_t S64, uint64_t U64, + bool B, std::string S, std::vector V) { -// EXPECT_EQ(S8, -101) << "int8_t serialization broken"; -// EXPECT_EQ(U8, 250) << "uint8_t serialization broken"; -// EXPECT_EQ(S16, -10000) << "int16_t serialization broken"; -// EXPECT_EQ(U16, 10000) << "uint16_t serialization broken"; -// EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken"; -// EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken"; -// EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken"; -// EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken"; -// EXPECT_EQ(B, true) << "bool serialization broken"; -// EXPECT_EQ(S, "foo") << "std::string serialization broken"; -// EXPECT_EQ(V, std::vector({42, 7})) -// << "std::vector serialization broken"; -// return Error::success(); -// }); + EXPECT_EQ(S8, -101) << "int8_t serialization broken"; + EXPECT_EQ(U8, 250) << "uint8_t serialization broken"; + EXPECT_EQ(S16, -10000) << "int16_t serialization broken"; + EXPECT_EQ(U16, 10000) << "uint16_t serialization broken"; + EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken"; + EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken"; + EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken"; + EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken"; + EXPECT_EQ(B, true) << "bool serialization broken"; + EXPECT_EQ(S, "foo") << "std::string serialization broken"; + EXPECT_EQ(V, std::vector({42, 7})) + << "std::vector serialization broken"; + return Error::success(); + }); -// { -// // Poke the server to handle the negotiate call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; -// } + { + // Poke the server to handle the negotiate call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate"; + } -// { -// // Poke the server to handle the AllTheTypes call. -// auto Err = Server.handleOne(); -// EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; -// } -// }); + { + // Poke the server to handle the AllTheTypes call. + auto Err = Server.handleOne(); + EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)"; + } + }); -// { -// // Make an async call. -// std::vector v({42, 7}); -// auto Err = Client.callAsync( -// [](Error Err) { -// EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed"; -// return Error::success(); -// }, -// static_cast(-101), static_cast(250), -// static_cast(-10000), static_cast(10000), -// static_cast(-1000000000), static_cast(1000000000), -// static_cast(-10000000000), static_cast(10000000000), -// true, std::string("foo"), v); -// EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes"; -// } + { + // Make an async call. + std::vector v({42, 7}); + auto Err = Client.callAsync( + [](Error Err) { + EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed"; + return Error::success(); + }, + static_cast(-101), static_cast(250), + static_cast(-10000), static_cast(10000), + static_cast(-1000000000), static_cast(1000000000), + static_cast(-10000000000), static_cast(10000000000), + true, std::string("foo"), v); + EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes"; + } -// { -// // Poke the client to process the result of the AllTheTypes call. -// auto Err = Client.handleOne(); -// EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes"; -// } + { + // Poke the client to process the result of the AllTheTypes call. + auto Err = Client.handleOne(); + EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes"; + } -// ServerThread.join(); -// } + ServerThread.join(); +} // Test the synchronous call API. // TEST_F(DummyRPC, TestSynchronousCall) {