11b1f1c77SAnubhab Ghosh //===- SharedMemoryMapperTest.cpp -- Tests for SharedMemoryMapper ---------===//
21b1f1c77SAnubhab Ghosh //
31b1f1c77SAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41b1f1c77SAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information.
51b1f1c77SAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61b1f1c77SAnubhab Ghosh //
71b1f1c77SAnubhab Ghosh //===----------------------------------------------------------------------===//
81b1f1c77SAnubhab Ghosh
91b1f1c77SAnubhab Ghosh #include "OrcTestCommon.h"
101b1f1c77SAnubhab Ghosh
111b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
121b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
131b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h"
141b1f1c77SAnubhab Ghosh #include "llvm/Testing/Support/Error.h"
151b1f1c77SAnubhab Ghosh
161b1f1c77SAnubhab Ghosh using namespace llvm;
171b1f1c77SAnubhab Ghosh using namespace llvm::orc;
181b1f1c77SAnubhab Ghosh using namespace llvm::orc::shared;
191b1f1c77SAnubhab Ghosh using namespace llvm::orc::rt_bootstrap;
201b1f1c77SAnubhab Ghosh
21*b3293305SAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
221b1f1c77SAnubhab Ghosh
231b1f1c77SAnubhab Ghosh // A basic function to be used as both initializer/deinitializer
incrementWrapper(const char * ArgData,size_t ArgSize)241b1f1c77SAnubhab Ghosh orc::shared::CWrapperFunctionResult incrementWrapper(const char *ArgData,
251b1f1c77SAnubhab Ghosh size_t ArgSize) {
261b1f1c77SAnubhab Ghosh return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
271b1f1c77SAnubhab Ghosh ArgData, ArgSize,
281b1f1c77SAnubhab Ghosh [](ExecutorAddr A) -> Error {
291b1f1c77SAnubhab Ghosh *A.toPtr<int *>() += 1;
301b1f1c77SAnubhab Ghosh return Error::success();
311b1f1c77SAnubhab Ghosh })
321b1f1c77SAnubhab Ghosh .release();
331b1f1c77SAnubhab Ghosh }
341b1f1c77SAnubhab Ghosh
TEST(SharedMemoryMapperTest,MemReserveInitializeDeinitializeRelease)351b1f1c77SAnubhab Ghosh TEST(SharedMemoryMapperTest, MemReserveInitializeDeinitializeRelease) {
361b1f1c77SAnubhab Ghosh // These counters are used to track how many times the initializer and
371b1f1c77SAnubhab Ghosh // deinitializer functions are called
381b1f1c77SAnubhab Ghosh int InitializeCounter = 0;
391b1f1c77SAnubhab Ghosh int DeinitializeCounter = 0;
401b1f1c77SAnubhab Ghosh
411b1f1c77SAnubhab Ghosh auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
421b1f1c77SAnubhab Ghosh
431b1f1c77SAnubhab Ghosh ExecutorSharedMemoryMapperService MapperService;
441b1f1c77SAnubhab Ghosh
451b1f1c77SAnubhab Ghosh SharedMemoryMapper::SymbolAddrs SAs;
461b1f1c77SAnubhab Ghosh {
471b1f1c77SAnubhab Ghosh StringMap<ExecutorAddr> Map;
481b1f1c77SAnubhab Ghosh MapperService.addBootstrapSymbols(Map);
491b1f1c77SAnubhab Ghosh SAs.Instance = Map[rt::ExecutorSharedMemoryMapperServiceInstanceName];
501b1f1c77SAnubhab Ghosh SAs.Reserve = Map[rt::ExecutorSharedMemoryMapperServiceReserveWrapperName];
511b1f1c77SAnubhab Ghosh SAs.Initialize =
521b1f1c77SAnubhab Ghosh Map[rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName];
531b1f1c77SAnubhab Ghosh SAs.Deinitialize =
541b1f1c77SAnubhab Ghosh Map[rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName];
551b1f1c77SAnubhab Ghosh SAs.Release = Map[rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName];
561b1f1c77SAnubhab Ghosh }
571b1f1c77SAnubhab Ghosh
581b1f1c77SAnubhab Ghosh std::string TestString = "Hello, World!";
591b1f1c77SAnubhab Ghosh
601b1f1c77SAnubhab Ghosh // barrier
611b1f1c77SAnubhab Ghosh std::promise<void> P;
621b1f1c77SAnubhab Ghosh auto F = P.get_future();
631b1f1c77SAnubhab Ghosh
641b1f1c77SAnubhab Ghosh {
651b1f1c77SAnubhab Ghosh std::unique_ptr<MemoryMapper> Mapper =
664fcf8434SAnubhab Ghosh cantFail(SharedMemoryMapper::Create(*SelfEPC, SAs));
674fcf8434SAnubhab Ghosh
684fcf8434SAnubhab Ghosh auto PageSize = Mapper->getPageSize();
694fcf8434SAnubhab Ghosh size_t ReqSize = PageSize;
701b1f1c77SAnubhab Ghosh
711b1f1c77SAnubhab Ghosh Mapper->reserve(ReqSize, [&](Expected<ExecutorAddrRange> Result) {
721b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(Result.takeError(), Succeeded());
731b1f1c77SAnubhab Ghosh auto Reservation = std::move(*Result);
741b1f1c77SAnubhab Ghosh {
751b1f1c77SAnubhab Ghosh char *Addr = Mapper->prepare(Reservation.Start, TestString.size() + 1);
761b1f1c77SAnubhab Ghosh std::strcpy(Addr, TestString.c_str());
771b1f1c77SAnubhab Ghosh }
781b1f1c77SAnubhab Ghosh MemoryMapper::AllocInfo AI;
791b1f1c77SAnubhab Ghosh {
801b1f1c77SAnubhab Ghosh MemoryMapper::AllocInfo::SegInfo SI;
811b1f1c77SAnubhab Ghosh SI.Offset = 0;
821b1f1c77SAnubhab Ghosh SI.ContentSize = TestString.size() + 1;
831b1f1c77SAnubhab Ghosh SI.ZeroFillSize = PageSize - SI.ContentSize;
841b1f1c77SAnubhab Ghosh SI.Prot = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
851b1f1c77SAnubhab Ghosh
861b1f1c77SAnubhab Ghosh AI.MappingBase = Reservation.Start;
871b1f1c77SAnubhab Ghosh AI.Segments.push_back(SI);
881b1f1c77SAnubhab Ghosh AI.Actions.push_back(
891b1f1c77SAnubhab Ghosh {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
901b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(incrementWrapper),
911b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(&InitializeCounter))),
921b1f1c77SAnubhab Ghosh cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
931b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(incrementWrapper),
941b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(&DeinitializeCounter)))});
951b1f1c77SAnubhab Ghosh }
961b1f1c77SAnubhab Ghosh
971b1f1c77SAnubhab Ghosh EXPECT_EQ(InitializeCounter, 0);
981b1f1c77SAnubhab Ghosh EXPECT_EQ(DeinitializeCounter, 0);
991b1f1c77SAnubhab Ghosh
1001b1f1c77SAnubhab Ghosh Mapper->initialize(AI, [&, Reservation](Expected<ExecutorAddr> Result) {
1011b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(Result.takeError(), Succeeded());
1021b1f1c77SAnubhab Ghosh
1031b1f1c77SAnubhab Ghosh EXPECT_EQ(TestString, std::string(static_cast<char *>(
1041b1f1c77SAnubhab Ghosh Reservation.Start.toPtr<char *>())));
1051b1f1c77SAnubhab Ghosh
1061b1f1c77SAnubhab Ghosh EXPECT_EQ(InitializeCounter, 1);
1071b1f1c77SAnubhab Ghosh EXPECT_EQ(DeinitializeCounter, 0);
1081b1f1c77SAnubhab Ghosh
1091b1f1c77SAnubhab Ghosh Mapper->deinitialize({*Result}, [&, Reservation](Error Err) {
1101b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(std::move(Err), Succeeded());
1111b1f1c77SAnubhab Ghosh
1121b1f1c77SAnubhab Ghosh EXPECT_EQ(InitializeCounter, 1);
1131b1f1c77SAnubhab Ghosh EXPECT_EQ(DeinitializeCounter, 1);
1141b1f1c77SAnubhab Ghosh
1151b1f1c77SAnubhab Ghosh Mapper->release({Reservation.Start}, [&](Error Err) {
1161b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(std::move(Err), Succeeded());
1171b1f1c77SAnubhab Ghosh
1181b1f1c77SAnubhab Ghosh P.set_value();
1191b1f1c77SAnubhab Ghosh });
1201b1f1c77SAnubhab Ghosh });
1211b1f1c77SAnubhab Ghosh });
1221b1f1c77SAnubhab Ghosh });
1231b1f1c77SAnubhab Ghosh
1241b1f1c77SAnubhab Ghosh // This will block the test if any of the above callbacks are not executed
1251b1f1c77SAnubhab Ghosh F.wait();
1261b1f1c77SAnubhab Ghosh // Mapper must be destructed before calling shutdown to avoid double free
1271b1f1c77SAnubhab Ghosh }
1281b1f1c77SAnubhab Ghosh
1291b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(MapperService.shutdown(), Succeeded());
1301b1f1c77SAnubhab Ghosh cantFail(SelfEPC->disconnect());
1311b1f1c77SAnubhab Ghosh }
1321b1f1c77SAnubhab Ghosh
1331b1f1c77SAnubhab Ghosh #endif
134