179fbee3cSAnubhab Ghosh //===- MemoryMapper.cpp - Cross-process memory mapper ------------*- C++ -*-==// 279fbee3cSAnubhab Ghosh // 379fbee3cSAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 479fbee3cSAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information. 579fbee3cSAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 679fbee3cSAnubhab Ghosh // 779fbee3cSAnubhab Ghosh //===----------------------------------------------------------------------===// 879fbee3cSAnubhab Ghosh 979fbee3cSAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MemoryMapper.h" 1079fbee3cSAnubhab Ghosh 111b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 121b1f1c77SAnubhab Ghosh #include "llvm/Support/WindowsError.h" 131b1f1c77SAnubhab Ghosh 140ecfee0bSAnubhab Ghosh #include <algorithm> 150ecfee0bSAnubhab Ghosh 16ac3cb4ecSAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) 171b1f1c77SAnubhab Ghosh #include <fcntl.h> 181b1f1c77SAnubhab Ghosh #include <sys/mman.h> 191b1f1c77SAnubhab Ghosh #include <unistd.h> 201b1f1c77SAnubhab Ghosh #elif defined(_WIN32) 211b1f1c77SAnubhab Ghosh #include <windows.h> 221b1f1c77SAnubhab Ghosh #endif 231b1f1c77SAnubhab Ghosh 2479fbee3cSAnubhab Ghosh namespace llvm { 2579fbee3cSAnubhab Ghosh namespace orc { 2679fbee3cSAnubhab Ghosh 2779fbee3cSAnubhab Ghosh MemoryMapper::~MemoryMapper() {} 2879fbee3cSAnubhab Ghosh 294fcf8434SAnubhab Ghosh InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize) 304fcf8434SAnubhab Ghosh : PageSize(PageSize) {} 314fcf8434SAnubhab Ghosh 324fcf8434SAnubhab Ghosh Expected<std::unique_ptr<InProcessMemoryMapper>> 334fcf8434SAnubhab Ghosh InProcessMemoryMapper::Create() { 344fcf8434SAnubhab Ghosh auto PageSize = sys::Process::getPageSize(); 354fcf8434SAnubhab Ghosh if (!PageSize) 364fcf8434SAnubhab Ghosh return PageSize.takeError(); 374fcf8434SAnubhab Ghosh return std::make_unique<InProcessMemoryMapper>(*PageSize); 384fcf8434SAnubhab Ghosh } 394fcf8434SAnubhab Ghosh 4079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::reserve(size_t NumBytes, 4179fbee3cSAnubhab Ghosh OnReservedFunction OnReserved) { 4279fbee3cSAnubhab Ghosh std::error_code EC; 4379fbee3cSAnubhab Ghosh auto MB = sys::Memory::allocateMappedMemory( 4479fbee3cSAnubhab Ghosh NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); 4579fbee3cSAnubhab Ghosh 4679fbee3cSAnubhab Ghosh if (EC) 4779fbee3cSAnubhab Ghosh return OnReserved(errorCodeToError(EC)); 4879fbee3cSAnubhab Ghosh 4979fbee3cSAnubhab Ghosh { 5079fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 5179fbee3cSAnubhab Ghosh Reservations[MB.base()].Size = MB.allocatedSize(); 5279fbee3cSAnubhab Ghosh } 5379fbee3cSAnubhab Ghosh 5479fbee3cSAnubhab Ghosh OnReserved( 5579fbee3cSAnubhab Ghosh ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize())); 5679fbee3cSAnubhab Ghosh } 5779fbee3cSAnubhab Ghosh 5879fbee3cSAnubhab Ghosh char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 5979fbee3cSAnubhab Ghosh return Addr.toPtr<char *>(); 6079fbee3cSAnubhab Ghosh } 6179fbee3cSAnubhab Ghosh 6279fbee3cSAnubhab Ghosh void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 6379fbee3cSAnubhab Ghosh OnInitializedFunction OnInitialized) { 6479fbee3cSAnubhab Ghosh ExecutorAddr MinAddr(~0ULL); 65a31af321SAnubhab Ghosh ExecutorAddr MaxAddr(0); 6679fbee3cSAnubhab Ghosh 67d3d9f7caSLang Hames // FIXME: Release finalize lifetime segments. 6879fbee3cSAnubhab Ghosh for (auto &Segment : AI.Segments) { 6979fbee3cSAnubhab Ghosh auto Base = AI.MappingBase + Segment.Offset; 7079fbee3cSAnubhab Ghosh auto Size = Segment.ContentSize + Segment.ZeroFillSize; 7179fbee3cSAnubhab Ghosh 7279fbee3cSAnubhab Ghosh if (Base < MinAddr) 7379fbee3cSAnubhab Ghosh MinAddr = Base; 7479fbee3cSAnubhab Ghosh 75a31af321SAnubhab Ghosh if (Base + Size > MaxAddr) 76a31af321SAnubhab Ghosh MaxAddr = Base + Size; 77a31af321SAnubhab Ghosh 7879fbee3cSAnubhab Ghosh std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0, 7979fbee3cSAnubhab Ghosh Segment.ZeroFillSize); 8079fbee3cSAnubhab Ghosh 81d3d9f7caSLang Hames if (auto EC = sys::Memory::protectMappedMemory( 82d3d9f7caSLang Hames {Base.toPtr<void *>(), Size}, 83d3d9f7caSLang Hames toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) { 8479fbee3cSAnubhab Ghosh return OnInitialized(errorCodeToError(EC)); 8579fbee3cSAnubhab Ghosh } 86d3d9f7caSLang Hames if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec) 8779fbee3cSAnubhab Ghosh sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size); 8879fbee3cSAnubhab Ghosh } 8979fbee3cSAnubhab Ghosh 9079fbee3cSAnubhab Ghosh auto DeinitializeActions = shared::runFinalizeActions(AI.Actions); 9179fbee3cSAnubhab Ghosh if (!DeinitializeActions) 9279fbee3cSAnubhab Ghosh return OnInitialized(DeinitializeActions.takeError()); 9379fbee3cSAnubhab Ghosh 9479fbee3cSAnubhab Ghosh { 9579fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 96a31af321SAnubhab Ghosh 97a31af321SAnubhab Ghosh // This is the maximum range whose permission have been possibly modified 98a31af321SAnubhab Ghosh Allocations[MinAddr].Size = MaxAddr - MinAddr; 9979fbee3cSAnubhab Ghosh Allocations[MinAddr].DeinitializationActions = 10079fbee3cSAnubhab Ghosh std::move(*DeinitializeActions); 10179fbee3cSAnubhab Ghosh Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr); 10279fbee3cSAnubhab Ghosh } 10379fbee3cSAnubhab Ghosh 10479fbee3cSAnubhab Ghosh OnInitialized(MinAddr); 10579fbee3cSAnubhab Ghosh } 10679fbee3cSAnubhab Ghosh 10779fbee3cSAnubhab Ghosh void InProcessMemoryMapper::deinitialize( 10879fbee3cSAnubhab Ghosh ArrayRef<ExecutorAddr> Bases, 10979fbee3cSAnubhab Ghosh MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 11079fbee3cSAnubhab Ghosh Error AllErr = Error::success(); 11179fbee3cSAnubhab Ghosh 11279fbee3cSAnubhab Ghosh { 11379fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 11479fbee3cSAnubhab Ghosh 115349e5bd2SLang Hames for (auto Base : llvm::reverse(Bases)) { 11679fbee3cSAnubhab Ghosh 11779fbee3cSAnubhab Ghosh if (Error Err = shared::runDeallocActions( 11879fbee3cSAnubhab Ghosh Allocations[Base].DeinitializationActions)) { 11979fbee3cSAnubhab Ghosh AllErr = joinErrors(std::move(AllErr), std::move(Err)); 12079fbee3cSAnubhab Ghosh } 12179fbee3cSAnubhab Ghosh 122a31af321SAnubhab Ghosh // Reset protections to read/write so the area can be reused 123a31af321SAnubhab Ghosh if (auto EC = sys::Memory::protectMappedMemory( 124a31af321SAnubhab Ghosh {Base.toPtr<void *>(), Allocations[Base].Size}, 125a31af321SAnubhab Ghosh sys::Memory::ProtectionFlags::MF_READ | 126a31af321SAnubhab Ghosh sys::Memory::ProtectionFlags::MF_WRITE)) { 127a31af321SAnubhab Ghosh AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC)); 128a31af321SAnubhab Ghosh } 129a31af321SAnubhab Ghosh 13079fbee3cSAnubhab Ghosh Allocations.erase(Base); 13179fbee3cSAnubhab Ghosh } 13279fbee3cSAnubhab Ghosh } 13379fbee3cSAnubhab Ghosh 13479fbee3cSAnubhab Ghosh OnDeinitialized(std::move(AllErr)); 13579fbee3cSAnubhab Ghosh } 13679fbee3cSAnubhab Ghosh 13779fbee3cSAnubhab Ghosh void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 13879fbee3cSAnubhab Ghosh OnReleasedFunction OnReleased) { 13979fbee3cSAnubhab Ghosh Error Err = Error::success(); 14079fbee3cSAnubhab Ghosh 14179fbee3cSAnubhab Ghosh for (auto Base : Bases) { 14279fbee3cSAnubhab Ghosh std::vector<ExecutorAddr> AllocAddrs; 14379fbee3cSAnubhab Ghosh size_t Size; 14479fbee3cSAnubhab Ghosh { 14579fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 14679fbee3cSAnubhab Ghosh auto &R = Reservations[Base.toPtr<void *>()]; 14779fbee3cSAnubhab Ghosh Size = R.Size; 14879fbee3cSAnubhab Ghosh AllocAddrs.swap(R.Allocations); 14979fbee3cSAnubhab Ghosh } 15079fbee3cSAnubhab Ghosh 15179fbee3cSAnubhab Ghosh // deinitialize sub allocations 15279fbee3cSAnubhab Ghosh std::promise<MSVCPError> P; 15379fbee3cSAnubhab Ghosh auto F = P.get_future(); 15479fbee3cSAnubhab Ghosh deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 15579fbee3cSAnubhab Ghosh if (Error E = F.get()) { 15679fbee3cSAnubhab Ghosh Err = joinErrors(std::move(Err), std::move(E)); 15779fbee3cSAnubhab Ghosh } 15879fbee3cSAnubhab Ghosh 15979fbee3cSAnubhab Ghosh // free the memory 16079fbee3cSAnubhab Ghosh auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size); 16179fbee3cSAnubhab Ghosh 16279fbee3cSAnubhab Ghosh auto EC = sys::Memory::releaseMappedMemory(MB); 16379fbee3cSAnubhab Ghosh if (EC) { 16479fbee3cSAnubhab Ghosh Err = joinErrors(std::move(Err), errorCodeToError(EC)); 16579fbee3cSAnubhab Ghosh } 16679fbee3cSAnubhab Ghosh 16779fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 16879fbee3cSAnubhab Ghosh Reservations.erase(Base.toPtr<void *>()); 16979fbee3cSAnubhab Ghosh } 17079fbee3cSAnubhab Ghosh 17179fbee3cSAnubhab Ghosh OnReleased(std::move(Err)); 17279fbee3cSAnubhab Ghosh } 17379fbee3cSAnubhab Ghosh 17479fbee3cSAnubhab Ghosh InProcessMemoryMapper::~InProcessMemoryMapper() { 17579fbee3cSAnubhab Ghosh std::vector<ExecutorAddr> ReservationAddrs; 17679fbee3cSAnubhab Ghosh { 17779fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 17879fbee3cSAnubhab Ghosh 17979fbee3cSAnubhab Ghosh ReservationAddrs.reserve(Reservations.size()); 18079fbee3cSAnubhab Ghosh for (const auto &R : Reservations) { 18179fbee3cSAnubhab Ghosh ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst())); 18279fbee3cSAnubhab Ghosh } 18379fbee3cSAnubhab Ghosh } 18479fbee3cSAnubhab Ghosh 18579fbee3cSAnubhab Ghosh std::promise<MSVCPError> P; 18679fbee3cSAnubhab Ghosh auto F = P.get_future(); 18779fbee3cSAnubhab Ghosh release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 18879fbee3cSAnubhab Ghosh cantFail(F.get()); 18979fbee3cSAnubhab Ghosh } 19079fbee3cSAnubhab Ghosh 1911b1f1c77SAnubhab Ghosh // SharedMemoryMapper 1921b1f1c77SAnubhab Ghosh 1934fcf8434SAnubhab Ghosh SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC, 1944fcf8434SAnubhab Ghosh SymbolAddrs SAs, size_t PageSize) 195ac3cb4ecSAnubhab Ghosh : EPC(EPC), SAs(SAs), PageSize(PageSize) { 196ac3cb4ecSAnubhab Ghosh #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32) 197ac3cb4ecSAnubhab Ghosh llvm_unreachable("SharedMemoryMapper is not supported on this platform yet"); 198ac3cb4ecSAnubhab Ghosh #endif 199ac3cb4ecSAnubhab Ghosh } 2004fcf8434SAnubhab Ghosh 2014fcf8434SAnubhab Ghosh Expected<std::unique_ptr<SharedMemoryMapper>> 2024fcf8434SAnubhab Ghosh SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) { 203ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 2044fcf8434SAnubhab Ghosh auto PageSize = sys::Process::getPageSize(); 2054fcf8434SAnubhab Ghosh if (!PageSize) 2064fcf8434SAnubhab Ghosh return PageSize.takeError(); 2074fcf8434SAnubhab Ghosh 2084fcf8434SAnubhab Ghosh return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize); 209ac3cb4ecSAnubhab Ghosh #else 210ac3cb4ecSAnubhab Ghosh return make_error<StringError>( 211ac3cb4ecSAnubhab Ghosh "SharedMemoryMapper is not supported on this platform yet", 212ac3cb4ecSAnubhab Ghosh inconvertibleErrorCode()); 213ac3cb4ecSAnubhab Ghosh #endif 2144fcf8434SAnubhab Ghosh } 2154fcf8434SAnubhab Ghosh 2161b1f1c77SAnubhab Ghosh void SharedMemoryMapper::reserve(size_t NumBytes, 2171b1f1c77SAnubhab Ghosh OnReservedFunction OnReserved) { 218ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 2191b1f1c77SAnubhab Ghosh 2201b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 2211b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>( 2221b1f1c77SAnubhab Ghosh SAs.Reserve, 2231b1f1c77SAnubhab Ghosh [this, NumBytes, OnReserved = std::move(OnReserved)]( 2241b1f1c77SAnubhab Ghosh Error SerializationErr, 2251b1f1c77SAnubhab Ghosh Expected<std::pair<ExecutorAddr, std::string>> Result) mutable { 2261b1f1c77SAnubhab Ghosh if (SerializationErr) { 2271b1f1c77SAnubhab Ghosh cantFail(Result.takeError()); 2281b1f1c77SAnubhab Ghosh return OnReserved(std::move(SerializationErr)); 2291b1f1c77SAnubhab Ghosh } 2301b1f1c77SAnubhab Ghosh 2311b1f1c77SAnubhab Ghosh if (!Result) 2321b1f1c77SAnubhab Ghosh return OnReserved(Result.takeError()); 2331b1f1c77SAnubhab Ghosh 2341b1f1c77SAnubhab Ghosh ExecutorAddr RemoteAddr; 2351b1f1c77SAnubhab Ghosh std::string SharedMemoryName; 2361b1f1c77SAnubhab Ghosh std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result); 2371b1f1c77SAnubhab Ghosh 2381b1f1c77SAnubhab Ghosh void *LocalAddr = nullptr; 2391b1f1c77SAnubhab Ghosh 2401b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX) 2411b1f1c77SAnubhab Ghosh 2421b1f1c77SAnubhab Ghosh int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700); 2431b1f1c77SAnubhab Ghosh if (SharedMemoryFile < 0) { 2441b1f1c77SAnubhab Ghosh return OnReserved(errorCodeToError( 2451b1f1c77SAnubhab Ghosh std::error_code(errno, std::generic_category()))); 2461b1f1c77SAnubhab Ghosh } 2471b1f1c77SAnubhab Ghosh 2481b1f1c77SAnubhab Ghosh // this prevents other processes from accessing it by name 2491b1f1c77SAnubhab Ghosh shm_unlink(SharedMemoryName.c_str()); 2501b1f1c77SAnubhab Ghosh 2511b1f1c77SAnubhab Ghosh LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED, 2521b1f1c77SAnubhab Ghosh SharedMemoryFile, 0); 2531b1f1c77SAnubhab Ghosh if (LocalAddr == MAP_FAILED) { 2541b1f1c77SAnubhab Ghosh return OnReserved(errorCodeToError( 2551b1f1c77SAnubhab Ghosh std::error_code(errno, std::generic_category()))); 2561b1f1c77SAnubhab Ghosh } 2571b1f1c77SAnubhab Ghosh 2581b1f1c77SAnubhab Ghosh close(SharedMemoryFile); 2591b1f1c77SAnubhab Ghosh 2601b1f1c77SAnubhab Ghosh #elif defined(_WIN32) 2611b1f1c77SAnubhab Ghosh 2621b1f1c77SAnubhab Ghosh std::wstring WideSharedMemoryName(SharedMemoryName.begin(), 2631b1f1c77SAnubhab Ghosh SharedMemoryName.end()); 2641b1f1c77SAnubhab Ghosh HANDLE SharedMemoryFile = OpenFileMappingW( 2651b1f1c77SAnubhab Ghosh FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str()); 2661b1f1c77SAnubhab Ghosh if (!SharedMemoryFile) 2671b1f1c77SAnubhab Ghosh return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 2681b1f1c77SAnubhab Ghosh 2691b1f1c77SAnubhab Ghosh LocalAddr = 2701b1f1c77SAnubhab Ghosh MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 2711b1f1c77SAnubhab Ghosh if (!LocalAddr) { 2721b1f1c77SAnubhab Ghosh CloseHandle(SharedMemoryFile); 2731b1f1c77SAnubhab Ghosh return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 2741b1f1c77SAnubhab Ghosh } 2751b1f1c77SAnubhab Ghosh 2761b1f1c77SAnubhab Ghosh CloseHandle(SharedMemoryFile); 2771b1f1c77SAnubhab Ghosh 2781b1f1c77SAnubhab Ghosh #endif 2791b1f1c77SAnubhab Ghosh { 2801b1f1c77SAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 2811b1f1c77SAnubhab Ghosh Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}}); 2821b1f1c77SAnubhab Ghosh } 2831b1f1c77SAnubhab Ghosh 2841b1f1c77SAnubhab Ghosh OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes)); 2851b1f1c77SAnubhab Ghosh }, 2861b1f1c77SAnubhab Ghosh SAs.Instance, static_cast<uint64_t>(NumBytes)); 2871b1f1c77SAnubhab Ghosh 2881b1f1c77SAnubhab Ghosh #else 2891b1f1c77SAnubhab Ghosh OnReserved(make_error<StringError>( 2901b1f1c77SAnubhab Ghosh "SharedMemoryMapper is not supported on this platform yet", 2911b1f1c77SAnubhab Ghosh inconvertibleErrorCode())); 2921b1f1c77SAnubhab Ghosh #endif 2931b1f1c77SAnubhab Ghosh } 2941b1f1c77SAnubhab Ghosh 2951b1f1c77SAnubhab Ghosh char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 2961b1f1c77SAnubhab Ghosh auto R = Reservations.upper_bound(Addr); 297ab492f62SAnubhab Ghosh assert(R != Reservations.begin() && "Attempt to prepare unreserved range"); 2981b1f1c77SAnubhab Ghosh R--; 2991b1f1c77SAnubhab Ghosh 3001b1f1c77SAnubhab Ghosh ExecutorAddrDiff Offset = Addr - R->first; 3011b1f1c77SAnubhab Ghosh 3021b1f1c77SAnubhab Ghosh return static_cast<char *>(R->second.LocalAddr) + Offset; 3031b1f1c77SAnubhab Ghosh } 3041b1f1c77SAnubhab Ghosh 3051b1f1c77SAnubhab Ghosh void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 3061b1f1c77SAnubhab Ghosh OnInitializedFunction OnInitialized) { 307ab492f62SAnubhab Ghosh auto Reservation = Reservations.upper_bound(AI.MappingBase); 308ab492f62SAnubhab Ghosh assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range"); 309ab492f62SAnubhab Ghosh Reservation--; 310ab492f62SAnubhab Ghosh 311ab492f62SAnubhab Ghosh auto AllocationOffset = AI.MappingBase - Reservation->first; 3121b1f1c77SAnubhab Ghosh 3131b1f1c77SAnubhab Ghosh tpctypes::SharedMemoryFinalizeRequest FR; 3141b1f1c77SAnubhab Ghosh 3151b1f1c77SAnubhab Ghosh AI.Actions.swap(FR.Actions); 3161b1f1c77SAnubhab Ghosh 3171b1f1c77SAnubhab Ghosh FR.Segments.reserve(AI.Segments.size()); 3181b1f1c77SAnubhab Ghosh 3191b1f1c77SAnubhab Ghosh for (auto Segment : AI.Segments) { 320ab492f62SAnubhab Ghosh char *Base = static_cast<char *>(Reservation->second.LocalAddr) + 321ab492f62SAnubhab Ghosh AllocationOffset + Segment.Offset; 3221b1f1c77SAnubhab Ghosh std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize); 3231b1f1c77SAnubhab Ghosh 3241b1f1c77SAnubhab Ghosh tpctypes::SharedMemorySegFinalizeRequest SegReq; 325d3d9f7caSLang Hames SegReq.AG = Segment.AG; 3261b1f1c77SAnubhab Ghosh SegReq.Addr = AI.MappingBase + Segment.Offset; 3271b1f1c77SAnubhab Ghosh SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize; 3281b1f1c77SAnubhab Ghosh 3291b1f1c77SAnubhab Ghosh FR.Segments.push_back(SegReq); 3301b1f1c77SAnubhab Ghosh } 3311b1f1c77SAnubhab Ghosh 3321b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 3331b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>( 3341b1f1c77SAnubhab Ghosh SAs.Initialize, 3351b1f1c77SAnubhab Ghosh [OnInitialized = std::move(OnInitialized)]( 3361b1f1c77SAnubhab Ghosh Error SerializationErr, Expected<ExecutorAddr> Result) mutable { 3371b1f1c77SAnubhab Ghosh if (SerializationErr) { 3381b1f1c77SAnubhab Ghosh cantFail(Result.takeError()); 3391b1f1c77SAnubhab Ghosh return OnInitialized(std::move(SerializationErr)); 3401b1f1c77SAnubhab Ghosh } 3411b1f1c77SAnubhab Ghosh 3421b1f1c77SAnubhab Ghosh OnInitialized(std::move(Result)); 3431b1f1c77SAnubhab Ghosh }, 3440ecfee0bSAnubhab Ghosh SAs.Instance, Reservation->first, std::move(FR)); 3451b1f1c77SAnubhab Ghosh } 3461b1f1c77SAnubhab Ghosh 3471b1f1c77SAnubhab Ghosh void SharedMemoryMapper::deinitialize( 3481b1f1c77SAnubhab Ghosh ArrayRef<ExecutorAddr> Allocations, 3491b1f1c77SAnubhab Ghosh MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 3501b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 3511b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>( 3521b1f1c77SAnubhab Ghosh SAs.Deinitialize, 3531b1f1c77SAnubhab Ghosh [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr, 3541b1f1c77SAnubhab Ghosh Error Result) mutable { 3551b1f1c77SAnubhab Ghosh if (SerializationErr) { 3561b1f1c77SAnubhab Ghosh cantFail(std::move(Result)); 3571b1f1c77SAnubhab Ghosh return OnDeinitialized(std::move(SerializationErr)); 3581b1f1c77SAnubhab Ghosh } 3591b1f1c77SAnubhab Ghosh 3601b1f1c77SAnubhab Ghosh OnDeinitialized(std::move(Result)); 3611b1f1c77SAnubhab Ghosh }, 3621b1f1c77SAnubhab Ghosh SAs.Instance, Allocations); 3631b1f1c77SAnubhab Ghosh } 3641b1f1c77SAnubhab Ghosh 3651b1f1c77SAnubhab Ghosh void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 3661b1f1c77SAnubhab Ghosh OnReleasedFunction OnReleased) { 367ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 3681b1f1c77SAnubhab Ghosh Error Err = Error::success(); 3691b1f1c77SAnubhab Ghosh 3701b1f1c77SAnubhab Ghosh { 3711b1f1c77SAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 3721b1f1c77SAnubhab Ghosh 3731b1f1c77SAnubhab Ghosh for (auto Base : Bases) { 3741b1f1c77SAnubhab Ghosh 3751b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX) 3761b1f1c77SAnubhab Ghosh 3771b1f1c77SAnubhab Ghosh if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0) 3781b1f1c77SAnubhab Ghosh Err = joinErrors(std::move(Err), errorCodeToError(std::error_code( 3791b1f1c77SAnubhab Ghosh errno, std::generic_category()))); 3801b1f1c77SAnubhab Ghosh 3811b1f1c77SAnubhab Ghosh #elif defined(_WIN32) 3821b1f1c77SAnubhab Ghosh 3831b1f1c77SAnubhab Ghosh if (!UnmapViewOfFile(Reservations[Base].LocalAddr)) 38446bc1b56SMartin Storsjö Err = joinErrors(std::move(Err), 3851b1f1c77SAnubhab Ghosh errorCodeToError(mapWindowsError(GetLastError()))); 3861b1f1c77SAnubhab Ghosh 3871b1f1c77SAnubhab Ghosh #endif 3881b1f1c77SAnubhab Ghosh 3891b1f1c77SAnubhab Ghosh Reservations.erase(Base); 3901b1f1c77SAnubhab Ghosh } 3911b1f1c77SAnubhab Ghosh } 3921b1f1c77SAnubhab Ghosh 3931b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 3941b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>( 3951b1f1c77SAnubhab Ghosh SAs.Release, 3961b1f1c77SAnubhab Ghosh [OnReleased = std::move(OnReleased), 3971b1f1c77SAnubhab Ghosh Err = std::move(Err)](Error SerializationErr, Error Result) mutable { 3981b1f1c77SAnubhab Ghosh if (SerializationErr) { 3991b1f1c77SAnubhab Ghosh cantFail(std::move(Result)); 4001b1f1c77SAnubhab Ghosh return OnReleased( 4011b1f1c77SAnubhab Ghosh joinErrors(std::move(Err), std::move(SerializationErr))); 4021b1f1c77SAnubhab Ghosh } 4031b1f1c77SAnubhab Ghosh 4041b1f1c77SAnubhab Ghosh return OnReleased(joinErrors(std::move(Err), std::move(Result))); 4051b1f1c77SAnubhab Ghosh }, 4061b1f1c77SAnubhab Ghosh SAs.Instance, Bases); 4071b1f1c77SAnubhab Ghosh #else 4081b1f1c77SAnubhab Ghosh OnReleased(make_error<StringError>( 4091b1f1c77SAnubhab Ghosh "SharedMemoryMapper is not supported on this platform yet", 4101b1f1c77SAnubhab Ghosh inconvertibleErrorCode())); 4111b1f1c77SAnubhab Ghosh #endif 4121b1f1c77SAnubhab Ghosh } 4131b1f1c77SAnubhab Ghosh 4141b1f1c77SAnubhab Ghosh SharedMemoryMapper::~SharedMemoryMapper() { 4151c25ce17SAlexandre Ganea std::lock_guard<std::mutex> Lock(Mutex); 4163019f488SLang Hames for (const auto &R : Reservations) { 4171b1f1c77SAnubhab Ghosh 4181134d3a0SAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) 4191134d3a0SAnubhab Ghosh 4201134d3a0SAnubhab Ghosh munmap(R.second.LocalAddr, R.second.Size); 4211134d3a0SAnubhab Ghosh 4221134d3a0SAnubhab Ghosh #elif defined(_WIN32) 4231134d3a0SAnubhab Ghosh 4241134d3a0SAnubhab Ghosh UnmapViewOfFile(R.second.LocalAddr); 4251134d3a0SAnubhab Ghosh 426*1c2ee6bdSDavid Blaikie #else 427*1c2ee6bdSDavid Blaikie 428*1c2ee6bdSDavid Blaikie (void)R; 429*1c2ee6bdSDavid Blaikie 4301134d3a0SAnubhab Ghosh #endif 4311134d3a0SAnubhab Ghosh } 4321b1f1c77SAnubhab Ghosh } 4331b1f1c77SAnubhab Ghosh 43479fbee3cSAnubhab Ghosh } // namespace orc 43579fbee3cSAnubhab Ghosh 43679fbee3cSAnubhab Ghosh } // namespace llvm 437