xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp (revision 89e6a288674c9fae33aeb5448c7b1fe782b2bf53)
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