xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp (revision 5acd471698849d9e322a29e6ca08791e8d447b7b)
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 
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 // A basic function to be used as both initializer/deinitializer
22 orc::shared::CWrapperFunctionResult incrementWrapper(const char *ArgData,
23                                                      size_t ArgSize) {
24   return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
25              ArgData, ArgSize,
26              [](ExecutorAddr A) -> Error {
27                *A.toPtr<int *>() += 1;
28                return Error::success();
29              })
30       .release();
31 }
32 
33 TEST(SharedMemoryMapperTest, MemReserveInitializeDeinitializeRelease) {
34   // These counters are used to track how many times the initializer and
35   // deinitializer functions are called
36   int InitializeCounter = 0;
37   int DeinitializeCounter = 0;
38 
39   auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());
40 
41   ExecutorSharedMemoryMapperService MapperService;
42 
43   SharedMemoryMapper::SymbolAddrs SAs;
44   {
45     StringMap<ExecutorAddr> Map;
46     MapperService.addBootstrapSymbols(Map);
47     SAs.Instance = Map[rt::ExecutorSharedMemoryMapperServiceInstanceName];
48     SAs.Reserve = Map[rt::ExecutorSharedMemoryMapperServiceReserveWrapperName];
49     SAs.Initialize =
50         Map[rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName];
51     SAs.Deinitialize =
52         Map[rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName];
53     SAs.Release = Map[rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName];
54   }
55 
56   std::string TestString = "Hello, World!";
57 
58   // barrier
59   std::promise<void> P;
60   auto F = P.get_future();
61 
62   {
63     auto PageSize = cantFail(sys::Process::getPageSize());
64     size_t ReqSize = PageSize;
65 
66     std::unique_ptr<MemoryMapper> Mapper =
67         std::make_unique<SharedMemoryMapper>(*SelfEPC, SAs);
68 
69     Mapper->reserve(ReqSize, [&](Expected<ExecutorAddrRange> Result) {
70       EXPECT_THAT_ERROR(Result.takeError(), Succeeded());
71       auto Reservation = std::move(*Result);
72       {
73         char *Addr = Mapper->prepare(Reservation.Start, TestString.size() + 1);
74         std::strcpy(Addr, TestString.c_str());
75       }
76       MemoryMapper::AllocInfo AI;
77       {
78         MemoryMapper::AllocInfo::SegInfo SI;
79         SI.Offset = 0;
80         SI.ContentSize = TestString.size() + 1;
81         SI.ZeroFillSize = PageSize - SI.ContentSize;
82         SI.Prot = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
83 
84         AI.MappingBase = Reservation.Start;
85         AI.Segments.push_back(SI);
86         AI.Actions.push_back(
87             {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
88                  ExecutorAddr::fromPtr(incrementWrapper),
89                  ExecutorAddr::fromPtr(&InitializeCounter))),
90              cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
91                  ExecutorAddr::fromPtr(incrementWrapper),
92                  ExecutorAddr::fromPtr(&DeinitializeCounter)))});
93       }
94 
95       EXPECT_EQ(InitializeCounter, 0);
96       EXPECT_EQ(DeinitializeCounter, 0);
97 
98       Mapper->initialize(AI, [&, Reservation](Expected<ExecutorAddr> Result) {
99         EXPECT_THAT_ERROR(Result.takeError(), Succeeded());
100 
101         EXPECT_EQ(TestString, std::string(static_cast<char *>(
102                                   Reservation.Start.toPtr<char *>())));
103 
104         EXPECT_EQ(InitializeCounter, 1);
105         EXPECT_EQ(DeinitializeCounter, 0);
106 
107         Mapper->deinitialize({*Result}, [&, Reservation](Error Err) {
108           EXPECT_THAT_ERROR(std::move(Err), Succeeded());
109 
110           EXPECT_EQ(InitializeCounter, 1);
111           EXPECT_EQ(DeinitializeCounter, 1);
112 
113           Mapper->release({Reservation.Start}, [&](Error Err) {
114             EXPECT_THAT_ERROR(std::move(Err), Succeeded());
115 
116             P.set_value();
117           });
118         });
119       });
120     });
121 
122     // This will block the test if any of the above callbacks are not executed
123     F.wait();
124     // Mapper must be destructed before calling shutdown to avoid double free
125   }
126 
127   EXPECT_THAT_ERROR(MapperService.shutdown(), Succeeded());
128   cantFail(SelfEPC->disconnect());
129 }
130