1 //===- SharedMemoryMapperTest.cpp -- Tests for SharedMemoryMapper ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "OrcTestCommon.h" 10 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX 11 #include "llvm/ExecutionEngine/Orc/MemoryMapper.h" 12 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 13 #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h" 14 #include "llvm/Testing/Support/Error.h" 15 16 using namespace llvm; 17 using namespace llvm::orc; 18 using namespace llvm::orc::shared; 19 using namespace llvm::orc::rt_bootstrap; 20 21 #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 22 23 // A basic function to be used as both initializer/deinitializer 24 orc::shared::CWrapperFunctionResult incrementWrapper(const char *ArgData, 25 size_t ArgSize) { 26 return WrapperFunction<SPSError(SPSExecutorAddr)>::handle( 27 ArgData, ArgSize, 28 [](ExecutorAddr A) -> Error { 29 *A.toPtr<int *>() += 1; 30 return Error::success(); 31 }) 32 .release(); 33 } 34 35 TEST(SharedMemoryMapperTest, MemReserveInitializeDeinitializeRelease) { 36 // These counters are used to track how many times the initializer and 37 // deinitializer functions are called 38 int InitializeCounter = 0; 39 int DeinitializeCounter = 0; 40 41 auto SelfEPC = cantFail(SelfExecutorProcessControl::Create()); 42 43 ExecutorSharedMemoryMapperService MapperService; 44 45 SharedMemoryMapper::SymbolAddrs SAs; 46 { 47 StringMap<ExecutorAddr> Map; 48 MapperService.addBootstrapSymbols(Map); 49 SAs.Instance = Map[rt::ExecutorSharedMemoryMapperServiceInstanceName]; 50 SAs.Reserve = Map[rt::ExecutorSharedMemoryMapperServiceReserveWrapperName]; 51 SAs.Initialize = 52 Map[rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName]; 53 SAs.Deinitialize = 54 Map[rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName]; 55 SAs.Release = Map[rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName]; 56 } 57 58 std::string TestString = "Hello, World!"; 59 60 // barrier 61 std::promise<void> P; 62 auto F = P.get_future(); 63 64 { 65 std::unique_ptr<MemoryMapper> Mapper = 66 cantFail(SharedMemoryMapper::Create(*SelfEPC, SAs)); 67 68 auto PageSize = Mapper->getPageSize(); 69 size_t ReqSize = PageSize; 70 71 Mapper->reserve(ReqSize, [&](Expected<ExecutorAddrRange> Result) { 72 EXPECT_THAT_ERROR(Result.takeError(), Succeeded()); 73 auto Reservation = std::move(*Result); 74 { 75 char *Addr = Mapper->prepare(Reservation.Start, TestString.size() + 1); 76 std::strcpy(Addr, TestString.c_str()); 77 } 78 MemoryMapper::AllocInfo AI; 79 { 80 MemoryMapper::AllocInfo::SegInfo SI; 81 SI.Offset = 0; 82 SI.ContentSize = TestString.size() + 1; 83 SI.ZeroFillSize = PageSize - SI.ContentSize; 84 SI.AG = MemProt::Read | MemProt::Write; 85 86 AI.MappingBase = Reservation.Start; 87 AI.Segments.push_back(SI); 88 AI.Actions.push_back( 89 {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 90 ExecutorAddr::fromPtr(incrementWrapper), 91 ExecutorAddr::fromPtr(&InitializeCounter))), 92 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 93 ExecutorAddr::fromPtr(incrementWrapper), 94 ExecutorAddr::fromPtr(&DeinitializeCounter)))}); 95 } 96 97 EXPECT_EQ(InitializeCounter, 0); 98 EXPECT_EQ(DeinitializeCounter, 0); 99 100 Mapper->initialize(AI, [&, Reservation](Expected<ExecutorAddr> Result) { 101 EXPECT_THAT_ERROR(Result.takeError(), Succeeded()); 102 103 EXPECT_EQ(TestString, std::string(static_cast<char *>( 104 Reservation.Start.toPtr<char *>()))); 105 106 EXPECT_EQ(InitializeCounter, 1); 107 EXPECT_EQ(DeinitializeCounter, 0); 108 109 Mapper->deinitialize({*Result}, [&, Reservation](Error Err) { 110 EXPECT_THAT_ERROR(std::move(Err), Succeeded()); 111 112 EXPECT_EQ(InitializeCounter, 1); 113 EXPECT_EQ(DeinitializeCounter, 1); 114 115 Mapper->release({Reservation.Start}, [&](Error Err) { 116 EXPECT_THAT_ERROR(std::move(Err), Succeeded()); 117 118 P.set_value(); 119 }); 120 }); 121 }); 122 }); 123 124 // This will block the test if any of the above callbacks are not executed 125 F.wait(); 126 // Mapper must be destructed before calling shutdown to avoid double free 127 } 128 129 EXPECT_THAT_ERROR(MapperService.shutdown(), Succeeded()); 130 cantFail(SelfEPC->disconnect()); 131 } 132 133 #endif 134