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
16using namespace llvm;
17using namespace llvm::orc;
18using namespace llvm::orc::shared;
19using 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
24orc::shared::CWrapperFunctionResult incrementWrapper(const char *ArgData,
25 size_t ArgSize) {
26 return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
27 ArgData, ArgSize,
28 Handler: [](ExecutorAddr A) -> Error {
29 *A.toPtr<int *>() += 1;
30 return Error::success();
31 })
32 .release();
33}
34
35TEST(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(ValOrErr: SelfExecutorProcessControl::Create());
42
43 ExecutorSharedMemoryMapperService MapperService;
44
45 SharedMemoryMapper::SymbolAddrs SAs;
46 {
47 StringMap<ExecutorAddr> Map;
48 MapperService.addBootstrapSymbols(M&: 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(ValOrErr: SharedMemoryMapper::Create(EPC&: *SelfEPC, SAs));
67
68 auto PageSize = Mapper->getPageSize();
69 size_t ReqSize = PageSize;
70
71 Mapper->reserve(NumBytes: ReqSize, OnReserved: [&](Expected<ExecutorAddrRange> Result) {
72 EXPECT_THAT_ERROR(Result.takeError(), Succeeded());
73 auto Reservation = std::move(*Result);
74 {
75 char *Addr = Mapper->prepare(Addr: Reservation.Start, ContentSize: TestString.size() + 1);
76 std::strcpy(dest: Addr, src: 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(x: SI);
88 AI.Actions.push_back(
89 x: {.Finalize: cantFail(ValOrErr: WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
90 FnAddr: ExecutorAddr::fromPtr(Ptr: incrementWrapper),
91 Args: ExecutorAddr::fromPtr(Ptr: &InitializeCounter))),
92 .Dealloc: cantFail(ValOrErr: WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
93 FnAddr: ExecutorAddr::fromPtr(Ptr: incrementWrapper),
94 Args: ExecutorAddr::fromPtr(Ptr: &DeinitializeCounter)))});
95 }
96
97 EXPECT_EQ(InitializeCounter, 0);
98 EXPECT_EQ(DeinitializeCounter, 0);
99
100 Mapper->initialize(AI, OnInitialized: [&, 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(Allocations: {*Result}, OnDeInitialized: [&, 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(Reservations: {Reservation.Start}, OnRelease: [&](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(Err: SelfEPC->disconnect());
131}
132
133#endif
134

source code of llvm/unittests/ExecutionEngine/Orc/SharedMemoryMapperTest.cpp