11b1f1c77SAnubhab Ghosh //===- SharedMemoryMapperTest.cpp -- Tests for SharedMemoryMapper ---------===// 21b1f1c77SAnubhab Ghosh // 31b1f1c77SAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41b1f1c77SAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information. 51b1f1c77SAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61b1f1c77SAnubhab Ghosh // 71b1f1c77SAnubhab Ghosh //===----------------------------------------------------------------------===// 81b1f1c77SAnubhab Ghosh 91b1f1c77SAnubhab Ghosh #include "OrcTestCommon.h" 10*89e6a288SDaniil Fukalov #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX 111b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MemoryMapper.h" 121b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 131b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h" 141b1f1c77SAnubhab Ghosh #include "llvm/Testing/Support/Error.h" 151b1f1c77SAnubhab Ghosh 161b1f1c77SAnubhab Ghosh using namespace llvm; 171b1f1c77SAnubhab Ghosh using namespace llvm::orc; 181b1f1c77SAnubhab Ghosh using namespace llvm::orc::shared; 191b1f1c77SAnubhab Ghosh using namespace llvm::orc::rt_bootstrap; 201b1f1c77SAnubhab Ghosh 21ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 221b1f1c77SAnubhab Ghosh 231b1f1c77SAnubhab Ghosh // A basic function to be used as both initializer/deinitializer 241b1f1c77SAnubhab Ghosh orc::shared::CWrapperFunctionResult incrementWrapper(const char *ArgData, 251b1f1c77SAnubhab Ghosh size_t ArgSize) { 261b1f1c77SAnubhab Ghosh return WrapperFunction<SPSError(SPSExecutorAddr)>::handle( 271b1f1c77SAnubhab Ghosh ArgData, ArgSize, 281b1f1c77SAnubhab Ghosh [](ExecutorAddr A) -> Error { 291b1f1c77SAnubhab Ghosh *A.toPtr<int *>() += 1; 301b1f1c77SAnubhab Ghosh return Error::success(); 311b1f1c77SAnubhab Ghosh }) 321b1f1c77SAnubhab Ghosh .release(); 331b1f1c77SAnubhab Ghosh } 341b1f1c77SAnubhab Ghosh 351b1f1c77SAnubhab Ghosh TEST(SharedMemoryMapperTest, MemReserveInitializeDeinitializeRelease) { 361b1f1c77SAnubhab Ghosh // These counters are used to track how many times the initializer and 371b1f1c77SAnubhab Ghosh // deinitializer functions are called 381b1f1c77SAnubhab Ghosh int InitializeCounter = 0; 391b1f1c77SAnubhab Ghosh int DeinitializeCounter = 0; 401b1f1c77SAnubhab Ghosh 411b1f1c77SAnubhab Ghosh auto SelfEPC = cantFail(SelfExecutorProcessControl::Create()); 421b1f1c77SAnubhab Ghosh 431b1f1c77SAnubhab Ghosh ExecutorSharedMemoryMapperService MapperService; 441b1f1c77SAnubhab Ghosh 451b1f1c77SAnubhab Ghosh SharedMemoryMapper::SymbolAddrs SAs; 461b1f1c77SAnubhab Ghosh { 471b1f1c77SAnubhab Ghosh StringMap<ExecutorAddr> Map; 481b1f1c77SAnubhab Ghosh MapperService.addBootstrapSymbols(Map); 491b1f1c77SAnubhab Ghosh SAs.Instance = Map[rt::ExecutorSharedMemoryMapperServiceInstanceName]; 501b1f1c77SAnubhab Ghosh SAs.Reserve = Map[rt::ExecutorSharedMemoryMapperServiceReserveWrapperName]; 511b1f1c77SAnubhab Ghosh SAs.Initialize = 521b1f1c77SAnubhab Ghosh Map[rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName]; 531b1f1c77SAnubhab Ghosh SAs.Deinitialize = 541b1f1c77SAnubhab Ghosh Map[rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName]; 551b1f1c77SAnubhab Ghosh SAs.Release = Map[rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName]; 561b1f1c77SAnubhab Ghosh } 571b1f1c77SAnubhab Ghosh 581b1f1c77SAnubhab Ghosh std::string TestString = "Hello, World!"; 591b1f1c77SAnubhab Ghosh 601b1f1c77SAnubhab Ghosh // barrier 611b1f1c77SAnubhab Ghosh std::promise<void> P; 621b1f1c77SAnubhab Ghosh auto F = P.get_future(); 631b1f1c77SAnubhab Ghosh 641b1f1c77SAnubhab Ghosh { 651b1f1c77SAnubhab Ghosh std::unique_ptr<MemoryMapper> Mapper = 664fcf8434SAnubhab Ghosh cantFail(SharedMemoryMapper::Create(*SelfEPC, SAs)); 674fcf8434SAnubhab Ghosh 684fcf8434SAnubhab Ghosh auto PageSize = Mapper->getPageSize(); 694fcf8434SAnubhab Ghosh size_t ReqSize = PageSize; 701b1f1c77SAnubhab Ghosh 711b1f1c77SAnubhab Ghosh Mapper->reserve(ReqSize, [&](Expected<ExecutorAddrRange> Result) { 721b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(Result.takeError(), Succeeded()); 731b1f1c77SAnubhab Ghosh auto Reservation = std::move(*Result); 741b1f1c77SAnubhab Ghosh { 751b1f1c77SAnubhab Ghosh char *Addr = Mapper->prepare(Reservation.Start, TestString.size() + 1); 761b1f1c77SAnubhab Ghosh std::strcpy(Addr, TestString.c_str()); 771b1f1c77SAnubhab Ghosh } 781b1f1c77SAnubhab Ghosh MemoryMapper::AllocInfo AI; 791b1f1c77SAnubhab Ghosh { 801b1f1c77SAnubhab Ghosh MemoryMapper::AllocInfo::SegInfo SI; 811b1f1c77SAnubhab Ghosh SI.Offset = 0; 821b1f1c77SAnubhab Ghosh SI.ContentSize = TestString.size() + 1; 831b1f1c77SAnubhab Ghosh SI.ZeroFillSize = PageSize - SI.ContentSize; 84d3d9f7caSLang Hames SI.AG = MemProt::Read | MemProt::Write; 851b1f1c77SAnubhab Ghosh 861b1f1c77SAnubhab Ghosh AI.MappingBase = Reservation.Start; 871b1f1c77SAnubhab Ghosh AI.Segments.push_back(SI); 881b1f1c77SAnubhab Ghosh AI.Actions.push_back( 891b1f1c77SAnubhab Ghosh {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 901b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(incrementWrapper), 911b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(&InitializeCounter))), 921b1f1c77SAnubhab Ghosh cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>( 931b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(incrementWrapper), 941b1f1c77SAnubhab Ghosh ExecutorAddr::fromPtr(&DeinitializeCounter)))}); 951b1f1c77SAnubhab Ghosh } 961b1f1c77SAnubhab Ghosh 971b1f1c77SAnubhab Ghosh EXPECT_EQ(InitializeCounter, 0); 981b1f1c77SAnubhab Ghosh EXPECT_EQ(DeinitializeCounter, 0); 991b1f1c77SAnubhab Ghosh 1001b1f1c77SAnubhab Ghosh Mapper->initialize(AI, [&, Reservation](Expected<ExecutorAddr> Result) { 1011b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(Result.takeError(), Succeeded()); 1021b1f1c77SAnubhab Ghosh 1031b1f1c77SAnubhab Ghosh EXPECT_EQ(TestString, std::string(static_cast<char *>( 1041b1f1c77SAnubhab Ghosh Reservation.Start.toPtr<char *>()))); 1051b1f1c77SAnubhab Ghosh 1061b1f1c77SAnubhab Ghosh EXPECT_EQ(InitializeCounter, 1); 1071b1f1c77SAnubhab Ghosh EXPECT_EQ(DeinitializeCounter, 0); 1081b1f1c77SAnubhab Ghosh 1091b1f1c77SAnubhab Ghosh Mapper->deinitialize({*Result}, [&, Reservation](Error Err) { 1101b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(std::move(Err), Succeeded()); 1111b1f1c77SAnubhab Ghosh 1121b1f1c77SAnubhab Ghosh EXPECT_EQ(InitializeCounter, 1); 1131b1f1c77SAnubhab Ghosh EXPECT_EQ(DeinitializeCounter, 1); 1141b1f1c77SAnubhab Ghosh 1151b1f1c77SAnubhab Ghosh Mapper->release({Reservation.Start}, [&](Error Err) { 1161b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(std::move(Err), Succeeded()); 1171b1f1c77SAnubhab Ghosh 1181b1f1c77SAnubhab Ghosh P.set_value(); 1191b1f1c77SAnubhab Ghosh }); 1201b1f1c77SAnubhab Ghosh }); 1211b1f1c77SAnubhab Ghosh }); 1221b1f1c77SAnubhab Ghosh }); 1231b1f1c77SAnubhab Ghosh 1241b1f1c77SAnubhab Ghosh // This will block the test if any of the above callbacks are not executed 1251b1f1c77SAnubhab Ghosh F.wait(); 1261b1f1c77SAnubhab Ghosh // Mapper must be destructed before calling shutdown to avoid double free 1271b1f1c77SAnubhab Ghosh } 1281b1f1c77SAnubhab Ghosh 1291b1f1c77SAnubhab Ghosh EXPECT_THAT_ERROR(MapperService.shutdown(), Succeeded()); 1301b1f1c77SAnubhab Ghosh cantFail(SelfEPC->disconnect()); 1311b1f1c77SAnubhab Ghosh } 1321b1f1c77SAnubhab Ghosh 1331b1f1c77SAnubhab Ghosh #endif 134