brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · bb34529 Raw
340 lines · cpp
1//===-- SPSNativeMemoryMapTest.cpp ----------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Test SPS serialization for MemoryFlags APIs.10//11//===----------------------------------------------------------------------===//12 13#include "orc-rt/SimpleNativeMemoryMap.h"14#include "orc-rt/SPSAllocAction.h"15#include "orc-rt/SPSMemoryFlags.h"16 17#include "AllocActionTestUtils.h"18#include "DirectCaller.h"19#include "gtest/gtest.h"20 21#include <future>22 23using namespace orc_rt;24 25namespace orc_rt {26 27struct SPSSimpleNativeMemoryMapSegment;28 29/// A SimpleNativeMemoryMap::InitializeRequest::Segment plus segment content (if30/// segment content type is regular).31struct TestSNMMSegment32    : public SimpleNativeMemoryMap::InitializeRequest::Segment {33 34  TestSNMMSegment(AllocGroup AG, char *Address, size_t Size,35                  std::vector<char> C = {})36      : SimpleNativeMemoryMap::InitializeRequest::Segment(37            {AG, Address, Size, {}}),38        OwnedContent(std::move(C)) {39    this->Content = {OwnedContent.data(), OwnedContent.size()};40  }41 42  std::vector<char> OwnedContent;43};44 45template <>46class SPSSerializationTraits<SPSSimpleNativeMemoryMapSegment, TestSNMMSegment> {47  using SPSType =48      SPSTuple<SPSAllocGroup, SPSExecutorAddr, uint64_t, SPSSequence<char>>;49 50public:51  static size_t size(const TestSNMMSegment &S) {52    return SPSType::AsArgList::size(S.AG, ExecutorAddr::fromPtr(S.Address),53                                    static_cast<uint64_t>(S.Size), S.Content);54  }55 56  static bool serialize(SPSOutputBuffer &OB, const TestSNMMSegment &S) {57    return SPSType::AsArgList::serialize(58        OB, S.AG, ExecutorAddr::fromPtr(S.Address),59        static_cast<uint64_t>(S.Size), S.Content);60  }61};62 63struct SPSSimpleNativeMemoryMapInitializeRequest;64 65struct TestSNMMInitializeRequest {66  std::vector<TestSNMMSegment> Segments;67  std::vector<AllocActionPair> AAPs;68};69 70template <>71class SPSSerializationTraits<SPSSimpleNativeMemoryMapInitializeRequest,72                             TestSNMMInitializeRequest> {73  using SPSType = SPSTuple<SPSSequence<SPSSimpleNativeMemoryMapSegment>,74                           SPSSequence<SPSAllocActionPair>>;75 76public:77  static size_t size(const TestSNMMInitializeRequest &IR) {78    return SPSType::AsArgList::size(IR.Segments, IR.AAPs);79  }80  static bool serialize(SPSOutputBuffer &OB,81                        const TestSNMMInitializeRequest &IR) {82    return SPSType::AsArgList::serialize(OB, IR.Segments, IR.AAPs);83  }84};85 86} // namespace orc_rt87 88template <typename T> move_only_function<void(T)> waitFor(std::future<T> &F) {89  std::promise<T> P;90  F = P.get_future();91  return [P = std::move(P)](T Val) mutable { P.set_value(std::move(Val)); };92}93 94TEST(SimpleNativeMemoryMapTest, CreateAndDestroy) {95  // Test that we can create and destroy a SimpleNativeMemoryMap instance as96  // expected.97  auto SNMM = std::make_unique<SimpleNativeMemoryMap>();98}99 100template <typename OnCompleteFn>101static void snmm_reserve(OnCompleteFn &&OnComplete,102                         SimpleNativeMemoryMap *Instance, size_t Size) {103  using SPSSig = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSSize);104  SPSWrapperFunction<SPSSig>::call(105      DirectCaller(nullptr, orc_rt_SimpleNativeMemoryMap_reserve_sps_wrapper),106      std::forward<OnCompleteFn>(OnComplete), Instance, Size);107}108 109template <typename OnCompleteFn>110static void snmm_releaseMultiple(OnCompleteFn &&OnComplete,111                                 SimpleNativeMemoryMap *Instance,112                                 span<void *> Addr) {113  using SPSSig = SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>);114  SPSWrapperFunction<SPSSig>::call(115      DirectCaller(nullptr,116                   orc_rt_SimpleNativeMemoryMap_releaseMultiple_sps_wrapper),117      std::forward<OnCompleteFn>(OnComplete), Instance, Addr);118}119 120template <typename OnCompleteFn>121static void snmm_initialize(OnCompleteFn &&OnComplete,122                            SimpleNativeMemoryMap *Instance,123                            TestSNMMInitializeRequest IR) {124  using SPSSig = SPSExpected<SPSExecutorAddr>(125      SPSExecutorAddr, SPSSimpleNativeMemoryMapInitializeRequest);126  SPSWrapperFunction<SPSSig>::call(127      DirectCaller(nullptr,128                   orc_rt_SimpleNativeMemoryMap_initialize_sps_wrapper),129      std::forward<OnCompleteFn>(OnComplete), Instance, std::move(IR));130}131 132template <typename OnCompleteFn>133static void snmm_deinitializeMultiple(OnCompleteFn &&OnComplete,134                                      SimpleNativeMemoryMap *Instance,135                                      span<void *> Base) {136  using SPSSig = SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddr>);137  SPSWrapperFunction<SPSSig>::call(138      DirectCaller(139          nullptr,140          orc_rt_SimpleNativeMemoryMap_deinitializeMultiple_sps_wrapper),141      std::forward<OnCompleteFn>(OnComplete), Instance, Base);142}143 144TEST(SimpleNativeMemoryMapTest, ReserveAndRelease) {145  // Test that we can reserve and release a slab of address space as expected,146  // without finalizing any memory within it.147  auto SNMM = std::make_unique<SimpleNativeMemoryMap>();148  std::future<Expected<Expected<void *>>> ReserveAddr;149  snmm_reserve(waitFor(ReserveAddr), SNMM.get(), 1024 * 1024 * 1024);150  auto Addr = cantFail(cantFail(ReserveAddr.get()));151 152  std::future<Expected<Error>> ReleaseResult;153  snmm_releaseMultiple(waitFor(ReleaseResult), SNMM.get(), {&Addr, 1});154  cantFail(cantFail(ReleaseResult.get()));155}156 157// Write the given value to the address pointed to by P.158static orc_rt_WrapperFunctionBuffer159write_value_sps_allocaction(const char *ArgData, size_t ArgSize) {160  return SPSAllocActionFunction<SPSExecutorAddr, uint64_t>::handle(161             ArgData, ArgSize,162             [](ExecutorAddr P, uint64_t Val) {163               *P.toPtr<uint64_t *>() = Val;164               return WrapperFunctionBuffer();165             })166      .release();167}168 169// Read the uint64_t value at Src and write it to Dst.170// Increments int via pointer.171static orc_rt_WrapperFunctionBuffer172read_value_sps_allocaction(const char *ArgData, size_t ArgSize) {173  return SPSAllocActionFunction<SPSExecutorAddr, SPSExecutorAddr>::handle(174             ArgData, ArgSize,175             [](ExecutorAddr Dst, ExecutorAddr Src) {176               *Dst.toPtr<uint64_t *>() = *Src.toPtr<uint64_t *>();177               return WrapperFunctionBuffer();178             })179      .release();180}181 182TEST(SimpleNativeMemoryMap, FullPipelineForOneRWSegment) {183  // Test that we can:184  // 1. reserve some address space.185  // 2. initialize a range within it as read/write, and that finalize actions186  //    are applied as expected.187  // 3. deinitialize the initialized range, with deallocation actions applied as188  //    expected.189  // 4. release the address range.190 191  auto SNMM = std::make_unique<SimpleNativeMemoryMap>();192  std::future<Expected<Expected<void *>>> ReserveAddr;193  snmm_reserve(waitFor(ReserveAddr), SNMM.get(), 1024 * 1024 * 1024);194  void *Addr = cantFail(cantFail(ReserveAddr.get()));195 196  std::future<Expected<Expected<void *>>> InitializeKey;197  TestSNMMInitializeRequest IR;198  char *InitializeBase = // Initialize addr at non-zero (64kb) offset from base.199      reinterpret_cast<char *>(Addr) + 64 * 1024;200  uint64_t SentinelValue1 = 0; // Read from pre-filled content201  uint64_t SentinelValue2 =202      0; // Written in initialize, read back during dealloc.203  uint64_t SentinelValue3 = 42; // Read from zero-filled region.204 205  // Build initial content vector.206  std::vector<char> Content;207  Content.resize(sizeof(uint64_t) * 2);208  memcpy(Content.data(), &SentinelValue3, sizeof(uint64_t));209  memcpy(Content.data() + sizeof(uint64_t), &SentinelValue1, sizeof(uint64_t));210 211  IR.Segments.push_back({MemProt::Read | MemProt::Write, InitializeBase,212                         64 * 1024, std::move(Content)});213 214  // Read initial content into Sentinel 1.215  IR.AAPs.push_back({216      *MakeAllocAction<SPSExecutorAddr, SPSExecutorAddr>::from(217          read_value_sps_allocaction, ExecutorAddr::fromPtr(&SentinelValue1),218          ExecutorAddr::fromPtr(InitializeBase)),219      {} // No dealloc action.220  });221 222  // Write value in finalize action, then read back into Sentinel 2.223  IR.AAPs.push_back(224      {*MakeAllocAction<SPSExecutorAddr, uint64_t>::from(225           write_value_sps_allocaction,226           ExecutorAddr::fromPtr(InitializeBase) + sizeof(uint64_t),227           uint64_t(42)),228       *MakeAllocAction<SPSExecutorAddr, SPSExecutorAddr>::from(229           read_value_sps_allocaction, ExecutorAddr::fromPtr(&SentinelValue2),230           ExecutorAddr::fromPtr(InitializeBase) + sizeof(uint64_t))});231 232  // Read first 64 bits of the zero-fill region.233  IR.AAPs.push_back({234      *MakeAllocAction<SPSExecutorAddr, SPSExecutorAddr>::from(235          read_value_sps_allocaction, ExecutorAddr::fromPtr(&SentinelValue3),236          ExecutorAddr::fromPtr(InitializeBase) + sizeof(uint64_t) * 2),237      {} // No dealloc action.238  });239 240  snmm_initialize(waitFor(InitializeKey), SNMM.get(), std::move(IR));241  void *InitializeKeyAddr = cantFail(cantFail(InitializeKey.get()));242 243  EXPECT_EQ(SentinelValue1, 42U);244  EXPECT_EQ(SentinelValue2, 0U);245  EXPECT_EQ(SentinelValue3, 0U);246 247  std::future<Expected<Error>> DeallocResult;248  snmm_deinitializeMultiple(waitFor(DeallocResult), SNMM.get(),249                            {&InitializeKeyAddr, 1});250  cantFail(cantFail(DeallocResult.get()));251 252  EXPECT_EQ(SentinelValue1, 42U);253  EXPECT_EQ(SentinelValue2, 42U);254  EXPECT_EQ(SentinelValue3, 0U);255 256  std::future<Expected<Error>> ReleaseResult;257  snmm_releaseMultiple(waitFor(ReleaseResult), SNMM.get(), {&Addr, 1});258  cantFail(cantFail(ReleaseResult.get()));259}260 261TEST(SimpleNativeMemoryMap, ReserveInitializeShutdown) {262  // Test that memory is deinitialized in the case where we reserve and263  // initialize some memory, then just shut down the memory manager.264 265  auto SNMM = std::make_unique<SimpleNativeMemoryMap>();266  std::future<Expected<Expected<void *>>> ReserveAddr;267  snmm_reserve(waitFor(ReserveAddr), SNMM.get(), 1024 * 1024 * 1024);268  void *Addr = cantFail(cantFail(ReserveAddr.get()));269 270  std::future<Expected<Expected<void *>>> InitializeKey;271  TestSNMMInitializeRequest IR;272  char *InitializeBase = // Initialize addr at non-zero (64kb) offset from base.273      reinterpret_cast<char *>(Addr) + 64 * 1024;274  uint64_t SentinelValue = 0;275 276  IR.Segments.push_back(277      {MemProt::Read | MemProt::Write, InitializeBase, 64 * 1024});278 279  IR.AAPs.push_back(280      {*MakeAllocAction<SPSExecutorAddr, uint64_t>::from(281           write_value_sps_allocaction, ExecutorAddr::fromPtr(InitializeBase),282           uint64_t(42)),283       *MakeAllocAction<SPSExecutorAddr, SPSExecutorAddr>::from(284           read_value_sps_allocaction, ExecutorAddr::fromPtr(&SentinelValue),285           ExecutorAddr::fromPtr(InitializeBase))});286  snmm_initialize(waitFor(InitializeKey), SNMM.get(), std::move(IR));287  cantFail(cantFail(InitializeKey.get()));288 289  EXPECT_EQ(SentinelValue, 0U);290 291  std::future<Error> ShutdownResult;292  SNMM->shutdown(waitFor(ShutdownResult));293  cantFail(ShutdownResult.get());294 295  EXPECT_EQ(SentinelValue, 42);296}297 298TEST(SimpleNativeMemoryMap, ReserveInitializeDetachShutdown) {299  // Test that memory is deinitialized in the case where we reserve and300  // initialize some memory, then just shut down the memory manager.301 302  auto SNMM = std::make_unique<SimpleNativeMemoryMap>();303  std::future<Expected<Expected<void *>>> ReserveAddr;304  snmm_reserve(waitFor(ReserveAddr), SNMM.get(), 1024 * 1024 * 1024);305  void *Addr = cantFail(cantFail(ReserveAddr.get()));306 307  std::future<Expected<Expected<void *>>> InitializeKey;308  TestSNMMInitializeRequest IR;309  char *InitializeBase = // Initialize addr at non-zero (64kb) offset from base.310      reinterpret_cast<char *>(Addr) + 64 * 1024;311  uint64_t SentinelValue = 0;312 313  IR.Segments.push_back(314      {MemProt::Read | MemProt::Write, InitializeBase, 64 * 1024});315 316  IR.AAPs.push_back(317      {*MakeAllocAction<SPSExecutorAddr, uint64_t>::from(318           write_value_sps_allocaction, ExecutorAddr::fromPtr(InitializeBase),319           uint64_t(42)),320       *MakeAllocAction<SPSExecutorAddr, SPSExecutorAddr>::from(321           read_value_sps_allocaction, ExecutorAddr::fromPtr(&SentinelValue),322           ExecutorAddr::fromPtr(InitializeBase))});323  snmm_initialize(waitFor(InitializeKey), SNMM.get(), std::move(IR));324  cantFail(cantFail(InitializeKey.get()));325 326  EXPECT_EQ(SentinelValue, 0U);327 328  std::future<Error> DetachResult;329  SNMM->detach(waitFor(DetachResult));330  cantFail(DetachResult.get());331 332  EXPECT_EQ(SentinelValue, 0);333 334  std::future<Error> ShutdownResult;335  SNMM->shutdown(waitFor(ShutdownResult));336  cantFail(ShutdownResult.get());337 338  EXPECT_EQ(SentinelValue, 42);339}340