181ad6265SDimitry Andric //===- MemoryMapper.cpp - Cross-process memory mapper ------------*- C++ -*-==// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "llvm/ExecutionEngine/Orc/MemoryMapper.h" 1081ad6265SDimitry Andric 11fcaf7f86SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 12fcaf7f86SDimitry Andric #include "llvm/Support/WindowsError.h" 13fcaf7f86SDimitry Andric 14bdd1243dSDimitry Andric #include <algorithm> 15bdd1243dSDimitry Andric 1661cfbce3SDimitry Andric #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) 17fcaf7f86SDimitry Andric #include <fcntl.h> 18fcaf7f86SDimitry Andric #include <sys/mman.h> 19*0fca6ea1SDimitry Andric #if defined(__MVS__) 20*0fca6ea1SDimitry Andric #include "llvm/Support/BLAKE3.h" 21*0fca6ea1SDimitry Andric #include <sys/shm.h> 22*0fca6ea1SDimitry Andric #endif 23fcaf7f86SDimitry Andric #include <unistd.h> 24fcaf7f86SDimitry Andric #elif defined(_WIN32) 25fcaf7f86SDimitry Andric #include <windows.h> 26fcaf7f86SDimitry Andric #endif 27fcaf7f86SDimitry Andric 2881ad6265SDimitry Andric namespace llvm { 2981ad6265SDimitry Andric namespace orc { 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric MemoryMapper::~MemoryMapper() {} 3281ad6265SDimitry Andric 33fcaf7f86SDimitry Andric InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize) 34fcaf7f86SDimitry Andric : PageSize(PageSize) {} 35fcaf7f86SDimitry Andric 36fcaf7f86SDimitry Andric Expected<std::unique_ptr<InProcessMemoryMapper>> 37fcaf7f86SDimitry Andric InProcessMemoryMapper::Create() { 38fcaf7f86SDimitry Andric auto PageSize = sys::Process::getPageSize(); 39fcaf7f86SDimitry Andric if (!PageSize) 40fcaf7f86SDimitry Andric return PageSize.takeError(); 41fcaf7f86SDimitry Andric return std::make_unique<InProcessMemoryMapper>(*PageSize); 42fcaf7f86SDimitry Andric } 43fcaf7f86SDimitry Andric 4481ad6265SDimitry Andric void InProcessMemoryMapper::reserve(size_t NumBytes, 4581ad6265SDimitry Andric OnReservedFunction OnReserved) { 4681ad6265SDimitry Andric std::error_code EC; 4781ad6265SDimitry Andric auto MB = sys::Memory::allocateMappedMemory( 4881ad6265SDimitry Andric NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric if (EC) 5181ad6265SDimitry Andric return OnReserved(errorCodeToError(EC)); 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric { 5481ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 5581ad6265SDimitry Andric Reservations[MB.base()].Size = MB.allocatedSize(); 5681ad6265SDimitry Andric } 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric OnReserved( 5981ad6265SDimitry Andric ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize())); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 6381ad6265SDimitry Andric return Addr.toPtr<char *>(); 6481ad6265SDimitry Andric } 6581ad6265SDimitry Andric 6681ad6265SDimitry Andric void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 6781ad6265SDimitry Andric OnInitializedFunction OnInitialized) { 6881ad6265SDimitry Andric ExecutorAddr MinAddr(~0ULL); 69bdd1243dSDimitry Andric ExecutorAddr MaxAddr(0); 7081ad6265SDimitry Andric 71bdd1243dSDimitry Andric // FIXME: Release finalize lifetime segments. 7281ad6265SDimitry Andric for (auto &Segment : AI.Segments) { 7381ad6265SDimitry Andric auto Base = AI.MappingBase + Segment.Offset; 7481ad6265SDimitry Andric auto Size = Segment.ContentSize + Segment.ZeroFillSize; 7581ad6265SDimitry Andric 7681ad6265SDimitry Andric if (Base < MinAddr) 7781ad6265SDimitry Andric MinAddr = Base; 7881ad6265SDimitry Andric 79bdd1243dSDimitry Andric if (Base + Size > MaxAddr) 80bdd1243dSDimitry Andric MaxAddr = Base + Size; 81bdd1243dSDimitry Andric 8281ad6265SDimitry Andric std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0, 8381ad6265SDimitry Andric Segment.ZeroFillSize); 8481ad6265SDimitry Andric 85bdd1243dSDimitry Andric if (auto EC = sys::Memory::protectMappedMemory( 86bdd1243dSDimitry Andric {Base.toPtr<void *>(), Size}, 87bdd1243dSDimitry Andric toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) { 8881ad6265SDimitry Andric return OnInitialized(errorCodeToError(EC)); 8981ad6265SDimitry Andric } 90bdd1243dSDimitry Andric if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec) 9181ad6265SDimitry Andric sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size); 9281ad6265SDimitry Andric } 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric auto DeinitializeActions = shared::runFinalizeActions(AI.Actions); 9581ad6265SDimitry Andric if (!DeinitializeActions) 9681ad6265SDimitry Andric return OnInitialized(DeinitializeActions.takeError()); 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric { 9981ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 100bdd1243dSDimitry Andric 101bdd1243dSDimitry Andric // This is the maximum range whose permission have been possibly modified 102bdd1243dSDimitry Andric Allocations[MinAddr].Size = MaxAddr - MinAddr; 10381ad6265SDimitry Andric Allocations[MinAddr].DeinitializationActions = 10481ad6265SDimitry Andric std::move(*DeinitializeActions); 10581ad6265SDimitry Andric Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr); 10681ad6265SDimitry Andric } 10781ad6265SDimitry Andric 10881ad6265SDimitry Andric OnInitialized(MinAddr); 10981ad6265SDimitry Andric } 11081ad6265SDimitry Andric 11181ad6265SDimitry Andric void InProcessMemoryMapper::deinitialize( 11281ad6265SDimitry Andric ArrayRef<ExecutorAddr> Bases, 11381ad6265SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 11481ad6265SDimitry Andric Error AllErr = Error::success(); 11581ad6265SDimitry Andric 11681ad6265SDimitry Andric { 11781ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 11881ad6265SDimitry Andric 119bdd1243dSDimitry Andric for (auto Base : llvm::reverse(Bases)) { 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric if (Error Err = shared::runDeallocActions( 12281ad6265SDimitry Andric Allocations[Base].DeinitializationActions)) { 12381ad6265SDimitry Andric AllErr = joinErrors(std::move(AllErr), std::move(Err)); 12481ad6265SDimitry Andric } 12581ad6265SDimitry Andric 126bdd1243dSDimitry Andric // Reset protections to read/write so the area can be reused 127bdd1243dSDimitry Andric if (auto EC = sys::Memory::protectMappedMemory( 128bdd1243dSDimitry Andric {Base.toPtr<void *>(), Allocations[Base].Size}, 129bdd1243dSDimitry Andric sys::Memory::ProtectionFlags::MF_READ | 130bdd1243dSDimitry Andric sys::Memory::ProtectionFlags::MF_WRITE)) { 131bdd1243dSDimitry Andric AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC)); 132bdd1243dSDimitry Andric } 133bdd1243dSDimitry Andric 13481ad6265SDimitry Andric Allocations.erase(Base); 13581ad6265SDimitry Andric } 13681ad6265SDimitry Andric } 13781ad6265SDimitry Andric 13881ad6265SDimitry Andric OnDeinitialized(std::move(AllErr)); 13981ad6265SDimitry Andric } 14081ad6265SDimitry Andric 14181ad6265SDimitry Andric void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 14281ad6265SDimitry Andric OnReleasedFunction OnReleased) { 14381ad6265SDimitry Andric Error Err = Error::success(); 14481ad6265SDimitry Andric 14581ad6265SDimitry Andric for (auto Base : Bases) { 14681ad6265SDimitry Andric std::vector<ExecutorAddr> AllocAddrs; 14781ad6265SDimitry Andric size_t Size; 14881ad6265SDimitry Andric { 14981ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 15081ad6265SDimitry Andric auto &R = Reservations[Base.toPtr<void *>()]; 15181ad6265SDimitry Andric Size = R.Size; 15281ad6265SDimitry Andric AllocAddrs.swap(R.Allocations); 15381ad6265SDimitry Andric } 15481ad6265SDimitry Andric 15581ad6265SDimitry Andric // deinitialize sub allocations 15681ad6265SDimitry Andric std::promise<MSVCPError> P; 15781ad6265SDimitry Andric auto F = P.get_future(); 15881ad6265SDimitry Andric deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 15981ad6265SDimitry Andric if (Error E = F.get()) { 16081ad6265SDimitry Andric Err = joinErrors(std::move(Err), std::move(E)); 16181ad6265SDimitry Andric } 16281ad6265SDimitry Andric 16381ad6265SDimitry Andric // free the memory 16481ad6265SDimitry Andric auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size); 16581ad6265SDimitry Andric 16681ad6265SDimitry Andric auto EC = sys::Memory::releaseMappedMemory(MB); 16781ad6265SDimitry Andric if (EC) { 16881ad6265SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(EC)); 16981ad6265SDimitry Andric } 17081ad6265SDimitry Andric 17181ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 17281ad6265SDimitry Andric Reservations.erase(Base.toPtr<void *>()); 17381ad6265SDimitry Andric } 17481ad6265SDimitry Andric 17581ad6265SDimitry Andric OnReleased(std::move(Err)); 17681ad6265SDimitry Andric } 17781ad6265SDimitry Andric 17881ad6265SDimitry Andric InProcessMemoryMapper::~InProcessMemoryMapper() { 17981ad6265SDimitry Andric std::vector<ExecutorAddr> ReservationAddrs; 18081ad6265SDimitry Andric { 18181ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 18281ad6265SDimitry Andric 18381ad6265SDimitry Andric ReservationAddrs.reserve(Reservations.size()); 18481ad6265SDimitry Andric for (const auto &R : Reservations) { 18581ad6265SDimitry Andric ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst())); 18681ad6265SDimitry Andric } 18781ad6265SDimitry Andric } 18881ad6265SDimitry Andric 18981ad6265SDimitry Andric std::promise<MSVCPError> P; 19081ad6265SDimitry Andric auto F = P.get_future(); 19181ad6265SDimitry Andric release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 19281ad6265SDimitry Andric cantFail(F.get()); 19381ad6265SDimitry Andric } 19481ad6265SDimitry Andric 195fcaf7f86SDimitry Andric // SharedMemoryMapper 196fcaf7f86SDimitry Andric 197fcaf7f86SDimitry Andric SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC, 198fcaf7f86SDimitry Andric SymbolAddrs SAs, size_t PageSize) 19961cfbce3SDimitry Andric : EPC(EPC), SAs(SAs), PageSize(PageSize) { 20061cfbce3SDimitry Andric #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32) 20161cfbce3SDimitry Andric llvm_unreachable("SharedMemoryMapper is not supported on this platform yet"); 20261cfbce3SDimitry Andric #endif 20361cfbce3SDimitry Andric } 204fcaf7f86SDimitry Andric 205fcaf7f86SDimitry Andric Expected<std::unique_ptr<SharedMemoryMapper>> 206fcaf7f86SDimitry Andric SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) { 20761cfbce3SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 208fcaf7f86SDimitry Andric auto PageSize = sys::Process::getPageSize(); 209fcaf7f86SDimitry Andric if (!PageSize) 210fcaf7f86SDimitry Andric return PageSize.takeError(); 211fcaf7f86SDimitry Andric 212fcaf7f86SDimitry Andric return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize); 21361cfbce3SDimitry Andric #else 21461cfbce3SDimitry Andric return make_error<StringError>( 21561cfbce3SDimitry Andric "SharedMemoryMapper is not supported on this platform yet", 21661cfbce3SDimitry Andric inconvertibleErrorCode()); 21761cfbce3SDimitry Andric #endif 218fcaf7f86SDimitry Andric } 219fcaf7f86SDimitry Andric 220fcaf7f86SDimitry Andric void SharedMemoryMapper::reserve(size_t NumBytes, 221fcaf7f86SDimitry Andric OnReservedFunction OnReserved) { 22261cfbce3SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 223fcaf7f86SDimitry Andric 224fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 225fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>( 226fcaf7f86SDimitry Andric SAs.Reserve, 227fcaf7f86SDimitry Andric [this, NumBytes, OnReserved = std::move(OnReserved)]( 228fcaf7f86SDimitry Andric Error SerializationErr, 229fcaf7f86SDimitry Andric Expected<std::pair<ExecutorAddr, std::string>> Result) mutable { 230fcaf7f86SDimitry Andric if (SerializationErr) { 231fcaf7f86SDimitry Andric cantFail(Result.takeError()); 232fcaf7f86SDimitry Andric return OnReserved(std::move(SerializationErr)); 233fcaf7f86SDimitry Andric } 234fcaf7f86SDimitry Andric 235fcaf7f86SDimitry Andric if (!Result) 236fcaf7f86SDimitry Andric return OnReserved(Result.takeError()); 237fcaf7f86SDimitry Andric 238fcaf7f86SDimitry Andric ExecutorAddr RemoteAddr; 239fcaf7f86SDimitry Andric std::string SharedMemoryName; 240fcaf7f86SDimitry Andric std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result); 241fcaf7f86SDimitry Andric 242fcaf7f86SDimitry Andric void *LocalAddr = nullptr; 243fcaf7f86SDimitry Andric 244fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) 245fcaf7f86SDimitry Andric 246*0fca6ea1SDimitry Andric #if defined(__MVS__) 247*0fca6ea1SDimitry Andric ArrayRef<uint8_t> Data( 248*0fca6ea1SDimitry Andric reinterpret_cast<const uint8_t *>(SharedMemoryName.c_str()), 249*0fca6ea1SDimitry Andric SharedMemoryName.size()); 250*0fca6ea1SDimitry Andric auto HashedName = BLAKE3::hash<sizeof(key_t)>(Data); 251*0fca6ea1SDimitry Andric key_t Key = *reinterpret_cast<key_t *>(HashedName.data()); 252*0fca6ea1SDimitry Andric int SharedMemoryId = 253*0fca6ea1SDimitry Andric shmget(Key, NumBytes, IPC_CREAT | __IPC_SHAREAS | 0700); 254*0fca6ea1SDimitry Andric if (SharedMemoryId < 0) { 255fcaf7f86SDimitry Andric return OnReserved(errorCodeToError( 256fcaf7f86SDimitry Andric std::error_code(errno, std::generic_category()))); 257fcaf7f86SDimitry Andric } 258*0fca6ea1SDimitry Andric LocalAddr = shmat(SharedMemoryId, nullptr, 0); 259*0fca6ea1SDimitry Andric if (LocalAddr == reinterpret_cast<void *>(-1)) { 260*0fca6ea1SDimitry Andric return OnReserved(errorCodeToError( 261*0fca6ea1SDimitry Andric std::error_code(errno, std::generic_category()))); 262*0fca6ea1SDimitry Andric } 263*0fca6ea1SDimitry Andric #else 264*0fca6ea1SDimitry Andric int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700); 265*0fca6ea1SDimitry Andric if (SharedMemoryFile < 0) { 266*0fca6ea1SDimitry Andric return OnReserved(errorCodeToError(errnoAsErrorCode())); 267*0fca6ea1SDimitry Andric } 268fcaf7f86SDimitry Andric 269fcaf7f86SDimitry Andric // this prevents other processes from accessing it by name 270fcaf7f86SDimitry Andric shm_unlink(SharedMemoryName.c_str()); 271fcaf7f86SDimitry Andric 272fcaf7f86SDimitry Andric LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED, 273fcaf7f86SDimitry Andric SharedMemoryFile, 0); 274fcaf7f86SDimitry Andric if (LocalAddr == MAP_FAILED) { 275*0fca6ea1SDimitry Andric return OnReserved(errorCodeToError(errnoAsErrorCode())); 276fcaf7f86SDimitry Andric } 277fcaf7f86SDimitry Andric 278fcaf7f86SDimitry Andric close(SharedMemoryFile); 279*0fca6ea1SDimitry Andric #endif 280fcaf7f86SDimitry Andric 281fcaf7f86SDimitry Andric #elif defined(_WIN32) 282fcaf7f86SDimitry Andric 283fcaf7f86SDimitry Andric std::wstring WideSharedMemoryName(SharedMemoryName.begin(), 284fcaf7f86SDimitry Andric SharedMemoryName.end()); 285fcaf7f86SDimitry Andric HANDLE SharedMemoryFile = OpenFileMappingW( 286fcaf7f86SDimitry Andric FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str()); 287fcaf7f86SDimitry Andric if (!SharedMemoryFile) 288fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 289fcaf7f86SDimitry Andric 290fcaf7f86SDimitry Andric LocalAddr = 291fcaf7f86SDimitry Andric MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 292fcaf7f86SDimitry Andric if (!LocalAddr) { 293fcaf7f86SDimitry Andric CloseHandle(SharedMemoryFile); 294fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 295fcaf7f86SDimitry Andric } 296fcaf7f86SDimitry Andric 297fcaf7f86SDimitry Andric CloseHandle(SharedMemoryFile); 298fcaf7f86SDimitry Andric 299fcaf7f86SDimitry Andric #endif 300fcaf7f86SDimitry Andric { 301fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 302fcaf7f86SDimitry Andric Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}}); 303fcaf7f86SDimitry Andric } 304fcaf7f86SDimitry Andric 305fcaf7f86SDimitry Andric OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes)); 306fcaf7f86SDimitry Andric }, 307fcaf7f86SDimitry Andric SAs.Instance, static_cast<uint64_t>(NumBytes)); 308fcaf7f86SDimitry Andric 309fcaf7f86SDimitry Andric #else 310fcaf7f86SDimitry Andric OnReserved(make_error<StringError>( 311fcaf7f86SDimitry Andric "SharedMemoryMapper is not supported on this platform yet", 312fcaf7f86SDimitry Andric inconvertibleErrorCode())); 313fcaf7f86SDimitry Andric #endif 314fcaf7f86SDimitry Andric } 315fcaf7f86SDimitry Andric 316fcaf7f86SDimitry Andric char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 317fcaf7f86SDimitry Andric auto R = Reservations.upper_bound(Addr); 318bdd1243dSDimitry Andric assert(R != Reservations.begin() && "Attempt to prepare unreserved range"); 319fcaf7f86SDimitry Andric R--; 320fcaf7f86SDimitry Andric 321fcaf7f86SDimitry Andric ExecutorAddrDiff Offset = Addr - R->first; 322fcaf7f86SDimitry Andric 323fcaf7f86SDimitry Andric return static_cast<char *>(R->second.LocalAddr) + Offset; 324fcaf7f86SDimitry Andric } 325fcaf7f86SDimitry Andric 326fcaf7f86SDimitry Andric void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 327fcaf7f86SDimitry Andric OnInitializedFunction OnInitialized) { 328bdd1243dSDimitry Andric auto Reservation = Reservations.upper_bound(AI.MappingBase); 329bdd1243dSDimitry Andric assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range"); 330bdd1243dSDimitry Andric Reservation--; 331bdd1243dSDimitry Andric 332bdd1243dSDimitry Andric auto AllocationOffset = AI.MappingBase - Reservation->first; 333fcaf7f86SDimitry Andric 334fcaf7f86SDimitry Andric tpctypes::SharedMemoryFinalizeRequest FR; 335fcaf7f86SDimitry Andric 336fcaf7f86SDimitry Andric AI.Actions.swap(FR.Actions); 337fcaf7f86SDimitry Andric 338fcaf7f86SDimitry Andric FR.Segments.reserve(AI.Segments.size()); 339fcaf7f86SDimitry Andric 340fcaf7f86SDimitry Andric for (auto Segment : AI.Segments) { 341bdd1243dSDimitry Andric char *Base = static_cast<char *>(Reservation->second.LocalAddr) + 342bdd1243dSDimitry Andric AllocationOffset + Segment.Offset; 343fcaf7f86SDimitry Andric std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize); 344fcaf7f86SDimitry Andric 345fcaf7f86SDimitry Andric tpctypes::SharedMemorySegFinalizeRequest SegReq; 3465f757f3fSDimitry Andric SegReq.RAG = {Segment.AG.getMemProt(), 3475f757f3fSDimitry Andric Segment.AG.getMemLifetime() == MemLifetime::Finalize}; 348fcaf7f86SDimitry Andric SegReq.Addr = AI.MappingBase + Segment.Offset; 349fcaf7f86SDimitry Andric SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize; 350fcaf7f86SDimitry Andric 351fcaf7f86SDimitry Andric FR.Segments.push_back(SegReq); 352fcaf7f86SDimitry Andric } 353fcaf7f86SDimitry Andric 354fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 355fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>( 356fcaf7f86SDimitry Andric SAs.Initialize, 357fcaf7f86SDimitry Andric [OnInitialized = std::move(OnInitialized)]( 358fcaf7f86SDimitry Andric Error SerializationErr, Expected<ExecutorAddr> Result) mutable { 359fcaf7f86SDimitry Andric if (SerializationErr) { 360fcaf7f86SDimitry Andric cantFail(Result.takeError()); 361fcaf7f86SDimitry Andric return OnInitialized(std::move(SerializationErr)); 362fcaf7f86SDimitry Andric } 363fcaf7f86SDimitry Andric 364fcaf7f86SDimitry Andric OnInitialized(std::move(Result)); 365fcaf7f86SDimitry Andric }, 366bdd1243dSDimitry Andric SAs.Instance, Reservation->first, std::move(FR)); 367fcaf7f86SDimitry Andric } 368fcaf7f86SDimitry Andric 369fcaf7f86SDimitry Andric void SharedMemoryMapper::deinitialize( 370fcaf7f86SDimitry Andric ArrayRef<ExecutorAddr> Allocations, 371fcaf7f86SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 372fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 373fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>( 374fcaf7f86SDimitry Andric SAs.Deinitialize, 375fcaf7f86SDimitry Andric [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr, 376fcaf7f86SDimitry Andric Error Result) mutable { 377fcaf7f86SDimitry Andric if (SerializationErr) { 378fcaf7f86SDimitry Andric cantFail(std::move(Result)); 379fcaf7f86SDimitry Andric return OnDeinitialized(std::move(SerializationErr)); 380fcaf7f86SDimitry Andric } 381fcaf7f86SDimitry Andric 382fcaf7f86SDimitry Andric OnDeinitialized(std::move(Result)); 383fcaf7f86SDimitry Andric }, 384fcaf7f86SDimitry Andric SAs.Instance, Allocations); 385fcaf7f86SDimitry Andric } 386fcaf7f86SDimitry Andric 387fcaf7f86SDimitry Andric void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 388fcaf7f86SDimitry Andric OnReleasedFunction OnReleased) { 38961cfbce3SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 390fcaf7f86SDimitry Andric Error Err = Error::success(); 391fcaf7f86SDimitry Andric 392fcaf7f86SDimitry Andric { 393fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 394fcaf7f86SDimitry Andric 395fcaf7f86SDimitry Andric for (auto Base : Bases) { 396fcaf7f86SDimitry Andric 397fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) 398fcaf7f86SDimitry Andric 399*0fca6ea1SDimitry Andric #if defined(__MVS__) 400*0fca6ea1SDimitry Andric if (shmdt(Reservations[Base].LocalAddr) < 0) 401*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode())); 402*0fca6ea1SDimitry Andric #else 403fcaf7f86SDimitry Andric if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0) 404*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode())); 405*0fca6ea1SDimitry Andric #endif 406fcaf7f86SDimitry Andric 407fcaf7f86SDimitry Andric #elif defined(_WIN32) 408fcaf7f86SDimitry Andric 409fcaf7f86SDimitry Andric if (!UnmapViewOfFile(Reservations[Base].LocalAddr)) 41061cfbce3SDimitry Andric Err = joinErrors(std::move(Err), 411fcaf7f86SDimitry Andric errorCodeToError(mapWindowsError(GetLastError()))); 412fcaf7f86SDimitry Andric 413fcaf7f86SDimitry Andric #endif 414fcaf7f86SDimitry Andric 415fcaf7f86SDimitry Andric Reservations.erase(Base); 416fcaf7f86SDimitry Andric } 417fcaf7f86SDimitry Andric } 418fcaf7f86SDimitry Andric 419fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 420fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>( 421fcaf7f86SDimitry Andric SAs.Release, 422fcaf7f86SDimitry Andric [OnReleased = std::move(OnReleased), 423fcaf7f86SDimitry Andric Err = std::move(Err)](Error SerializationErr, Error Result) mutable { 424fcaf7f86SDimitry Andric if (SerializationErr) { 425fcaf7f86SDimitry Andric cantFail(std::move(Result)); 426fcaf7f86SDimitry Andric return OnReleased( 427fcaf7f86SDimitry Andric joinErrors(std::move(Err), std::move(SerializationErr))); 428fcaf7f86SDimitry Andric } 429fcaf7f86SDimitry Andric 430fcaf7f86SDimitry Andric return OnReleased(joinErrors(std::move(Err), std::move(Result))); 431fcaf7f86SDimitry Andric }, 432fcaf7f86SDimitry Andric SAs.Instance, Bases); 433fcaf7f86SDimitry Andric #else 434fcaf7f86SDimitry Andric OnReleased(make_error<StringError>( 435fcaf7f86SDimitry Andric "SharedMemoryMapper is not supported on this platform yet", 436fcaf7f86SDimitry Andric inconvertibleErrorCode())); 437fcaf7f86SDimitry Andric #endif 438fcaf7f86SDimitry Andric } 439fcaf7f86SDimitry Andric 440fcaf7f86SDimitry Andric SharedMemoryMapper::~SharedMemoryMapper() { 441fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 442fcaf7f86SDimitry Andric for (const auto &R : Reservations) { 443fcaf7f86SDimitry Andric 444bdd1243dSDimitry Andric #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) 445bdd1243dSDimitry Andric 446*0fca6ea1SDimitry Andric #if defined(__MVS__) 447*0fca6ea1SDimitry Andric shmdt(R.second.LocalAddr); 448*0fca6ea1SDimitry Andric #else 449bdd1243dSDimitry Andric munmap(R.second.LocalAddr, R.second.Size); 450*0fca6ea1SDimitry Andric #endif 451bdd1243dSDimitry Andric 452bdd1243dSDimitry Andric #elif defined(_WIN32) 453bdd1243dSDimitry Andric 454bdd1243dSDimitry Andric UnmapViewOfFile(R.second.LocalAddr); 455bdd1243dSDimitry Andric 456bdd1243dSDimitry Andric #else 457bdd1243dSDimitry Andric 458bdd1243dSDimitry Andric (void)R; 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric #endif 461bdd1243dSDimitry Andric } 462fcaf7f86SDimitry Andric } 463fcaf7f86SDimitry Andric 46481ad6265SDimitry Andric } // namespace orc 46581ad6265SDimitry Andric 46681ad6265SDimitry Andric } // namespace llvm 467