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 11*fcaf7f86SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 12*fcaf7f86SDimitry Andric #include "llvm/Support/WindowsError.h" 13*fcaf7f86SDimitry Andric 14*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) 15*fcaf7f86SDimitry Andric #include <fcntl.h> 16*fcaf7f86SDimitry Andric #include <sys/mman.h> 17*fcaf7f86SDimitry Andric #include <unistd.h> 18*fcaf7f86SDimitry Andric #elif defined(_WIN32) 19*fcaf7f86SDimitry Andric #include <windows.h> 20*fcaf7f86SDimitry Andric #endif 21*fcaf7f86SDimitry Andric 2281ad6265SDimitry Andric namespace llvm { 2381ad6265SDimitry Andric namespace orc { 2481ad6265SDimitry Andric 2581ad6265SDimitry Andric MemoryMapper::~MemoryMapper() {} 2681ad6265SDimitry Andric 27*fcaf7f86SDimitry Andric InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize) 28*fcaf7f86SDimitry Andric : PageSize(PageSize) {} 29*fcaf7f86SDimitry Andric 30*fcaf7f86SDimitry Andric Expected<std::unique_ptr<InProcessMemoryMapper>> 31*fcaf7f86SDimitry Andric InProcessMemoryMapper::Create() { 32*fcaf7f86SDimitry Andric auto PageSize = sys::Process::getPageSize(); 33*fcaf7f86SDimitry Andric if (!PageSize) 34*fcaf7f86SDimitry Andric return PageSize.takeError(); 35*fcaf7f86SDimitry Andric return std::make_unique<InProcessMemoryMapper>(*PageSize); 36*fcaf7f86SDimitry Andric } 37*fcaf7f86SDimitry Andric 3881ad6265SDimitry Andric void InProcessMemoryMapper::reserve(size_t NumBytes, 3981ad6265SDimitry Andric OnReservedFunction OnReserved) { 4081ad6265SDimitry Andric std::error_code EC; 4181ad6265SDimitry Andric auto MB = sys::Memory::allocateMappedMemory( 4281ad6265SDimitry Andric NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); 4381ad6265SDimitry Andric 4481ad6265SDimitry Andric if (EC) 4581ad6265SDimitry Andric return OnReserved(errorCodeToError(EC)); 4681ad6265SDimitry Andric 4781ad6265SDimitry Andric { 4881ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 4981ad6265SDimitry Andric Reservations[MB.base()].Size = MB.allocatedSize(); 5081ad6265SDimitry Andric } 5181ad6265SDimitry Andric 5281ad6265SDimitry Andric OnReserved( 5381ad6265SDimitry Andric ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize())); 5481ad6265SDimitry Andric } 5581ad6265SDimitry Andric 5681ad6265SDimitry Andric char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 5781ad6265SDimitry Andric return Addr.toPtr<char *>(); 5881ad6265SDimitry Andric } 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 6181ad6265SDimitry Andric OnInitializedFunction OnInitialized) { 6281ad6265SDimitry Andric ExecutorAddr MinAddr(~0ULL); 6381ad6265SDimitry Andric 6481ad6265SDimitry Andric for (auto &Segment : AI.Segments) { 6581ad6265SDimitry Andric auto Base = AI.MappingBase + Segment.Offset; 6681ad6265SDimitry Andric auto Size = Segment.ContentSize + Segment.ZeroFillSize; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric if (Base < MinAddr) 6981ad6265SDimitry Andric MinAddr = Base; 7081ad6265SDimitry Andric 7181ad6265SDimitry Andric std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0, 7281ad6265SDimitry Andric Segment.ZeroFillSize); 7381ad6265SDimitry Andric 7481ad6265SDimitry Andric if (auto EC = sys::Memory::protectMappedMemory({Base.toPtr<void *>(), Size}, 7581ad6265SDimitry Andric Segment.Prot)) { 7681ad6265SDimitry Andric return OnInitialized(errorCodeToError(EC)); 7781ad6265SDimitry Andric } 7881ad6265SDimitry Andric if (Segment.Prot & sys::Memory::MF_EXEC) 7981ad6265SDimitry Andric sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size); 8081ad6265SDimitry Andric } 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric auto DeinitializeActions = shared::runFinalizeActions(AI.Actions); 8381ad6265SDimitry Andric if (!DeinitializeActions) 8481ad6265SDimitry Andric return OnInitialized(DeinitializeActions.takeError()); 8581ad6265SDimitry Andric 8681ad6265SDimitry Andric { 8781ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 8881ad6265SDimitry Andric Allocations[MinAddr].DeinitializationActions = 8981ad6265SDimitry Andric std::move(*DeinitializeActions); 9081ad6265SDimitry Andric Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr); 9181ad6265SDimitry Andric } 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric OnInitialized(MinAddr); 9481ad6265SDimitry Andric } 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric void InProcessMemoryMapper::deinitialize( 9781ad6265SDimitry Andric ArrayRef<ExecutorAddr> Bases, 9881ad6265SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 9981ad6265SDimitry Andric Error AllErr = Error::success(); 10081ad6265SDimitry Andric 10181ad6265SDimitry Andric { 10281ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 10381ad6265SDimitry Andric 10481ad6265SDimitry Andric for (auto Base : Bases) { 10581ad6265SDimitry Andric 10681ad6265SDimitry Andric if (Error Err = shared::runDeallocActions( 10781ad6265SDimitry Andric Allocations[Base].DeinitializationActions)) { 10881ad6265SDimitry Andric AllErr = joinErrors(std::move(AllErr), std::move(Err)); 10981ad6265SDimitry Andric } 11081ad6265SDimitry Andric 11181ad6265SDimitry Andric Allocations.erase(Base); 11281ad6265SDimitry Andric } 11381ad6265SDimitry Andric } 11481ad6265SDimitry Andric 11581ad6265SDimitry Andric OnDeinitialized(std::move(AllErr)); 11681ad6265SDimitry Andric } 11781ad6265SDimitry Andric 11881ad6265SDimitry Andric void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 11981ad6265SDimitry Andric OnReleasedFunction OnReleased) { 12081ad6265SDimitry Andric Error Err = Error::success(); 12181ad6265SDimitry Andric 12281ad6265SDimitry Andric for (auto Base : Bases) { 12381ad6265SDimitry Andric std::vector<ExecutorAddr> AllocAddrs; 12481ad6265SDimitry Andric size_t Size; 12581ad6265SDimitry Andric { 12681ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 12781ad6265SDimitry Andric auto &R = Reservations[Base.toPtr<void *>()]; 12881ad6265SDimitry Andric Size = R.Size; 12981ad6265SDimitry Andric AllocAddrs.swap(R.Allocations); 13081ad6265SDimitry Andric } 13181ad6265SDimitry Andric 13281ad6265SDimitry Andric // deinitialize sub allocations 13381ad6265SDimitry Andric std::promise<MSVCPError> P; 13481ad6265SDimitry Andric auto F = P.get_future(); 13581ad6265SDimitry Andric deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 13681ad6265SDimitry Andric if (Error E = F.get()) { 13781ad6265SDimitry Andric Err = joinErrors(std::move(Err), std::move(E)); 13881ad6265SDimitry Andric } 13981ad6265SDimitry Andric 14081ad6265SDimitry Andric // free the memory 14181ad6265SDimitry Andric auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size); 14281ad6265SDimitry Andric 14381ad6265SDimitry Andric auto EC = sys::Memory::releaseMappedMemory(MB); 14481ad6265SDimitry Andric if (EC) { 14581ad6265SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(EC)); 14681ad6265SDimitry Andric } 14781ad6265SDimitry Andric 14881ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 14981ad6265SDimitry Andric Reservations.erase(Base.toPtr<void *>()); 15081ad6265SDimitry Andric } 15181ad6265SDimitry Andric 15281ad6265SDimitry Andric OnReleased(std::move(Err)); 15381ad6265SDimitry Andric } 15481ad6265SDimitry Andric 15581ad6265SDimitry Andric InProcessMemoryMapper::~InProcessMemoryMapper() { 15681ad6265SDimitry Andric std::vector<ExecutorAddr> ReservationAddrs; 15781ad6265SDimitry Andric { 15881ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 15981ad6265SDimitry Andric 16081ad6265SDimitry Andric ReservationAddrs.reserve(Reservations.size()); 16181ad6265SDimitry Andric for (const auto &R : Reservations) { 16281ad6265SDimitry Andric ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst())); 16381ad6265SDimitry Andric } 16481ad6265SDimitry Andric } 16581ad6265SDimitry Andric 16681ad6265SDimitry Andric std::promise<MSVCPError> P; 16781ad6265SDimitry Andric auto F = P.get_future(); 16881ad6265SDimitry Andric release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 16981ad6265SDimitry Andric cantFail(F.get()); 17081ad6265SDimitry Andric } 17181ad6265SDimitry Andric 172*fcaf7f86SDimitry Andric // SharedMemoryMapper 173*fcaf7f86SDimitry Andric 174*fcaf7f86SDimitry Andric SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC, 175*fcaf7f86SDimitry Andric SymbolAddrs SAs, size_t PageSize) 176*fcaf7f86SDimitry Andric : EPC(EPC), SAs(SAs), PageSize(PageSize) {} 177*fcaf7f86SDimitry Andric 178*fcaf7f86SDimitry Andric Expected<std::unique_ptr<SharedMemoryMapper>> 179*fcaf7f86SDimitry Andric SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) { 180*fcaf7f86SDimitry Andric auto PageSize = sys::Process::getPageSize(); 181*fcaf7f86SDimitry Andric if (!PageSize) 182*fcaf7f86SDimitry Andric return PageSize.takeError(); 183*fcaf7f86SDimitry Andric 184*fcaf7f86SDimitry Andric return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize); 185*fcaf7f86SDimitry Andric } 186*fcaf7f86SDimitry Andric 187*fcaf7f86SDimitry Andric void SharedMemoryMapper::reserve(size_t NumBytes, 188*fcaf7f86SDimitry Andric OnReservedFunction OnReserved) { 189*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) || defined(_WIN32) 190*fcaf7f86SDimitry Andric 191*fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 192*fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>( 193*fcaf7f86SDimitry Andric SAs.Reserve, 194*fcaf7f86SDimitry Andric [this, NumBytes, OnReserved = std::move(OnReserved)]( 195*fcaf7f86SDimitry Andric Error SerializationErr, 196*fcaf7f86SDimitry Andric Expected<std::pair<ExecutorAddr, std::string>> Result) mutable { 197*fcaf7f86SDimitry Andric if (SerializationErr) { 198*fcaf7f86SDimitry Andric cantFail(Result.takeError()); 199*fcaf7f86SDimitry Andric return OnReserved(std::move(SerializationErr)); 200*fcaf7f86SDimitry Andric } 201*fcaf7f86SDimitry Andric 202*fcaf7f86SDimitry Andric if (!Result) 203*fcaf7f86SDimitry Andric return OnReserved(Result.takeError()); 204*fcaf7f86SDimitry Andric 205*fcaf7f86SDimitry Andric ExecutorAddr RemoteAddr; 206*fcaf7f86SDimitry Andric std::string SharedMemoryName; 207*fcaf7f86SDimitry Andric std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result); 208*fcaf7f86SDimitry Andric 209*fcaf7f86SDimitry Andric void *LocalAddr = nullptr; 210*fcaf7f86SDimitry Andric 211*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) 212*fcaf7f86SDimitry Andric 213*fcaf7f86SDimitry Andric int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700); 214*fcaf7f86SDimitry Andric if (SharedMemoryFile < 0) { 215*fcaf7f86SDimitry Andric return OnReserved(errorCodeToError( 216*fcaf7f86SDimitry Andric std::error_code(errno, std::generic_category()))); 217*fcaf7f86SDimitry Andric } 218*fcaf7f86SDimitry Andric 219*fcaf7f86SDimitry Andric // this prevents other processes from accessing it by name 220*fcaf7f86SDimitry Andric shm_unlink(SharedMemoryName.c_str()); 221*fcaf7f86SDimitry Andric 222*fcaf7f86SDimitry Andric LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED, 223*fcaf7f86SDimitry Andric SharedMemoryFile, 0); 224*fcaf7f86SDimitry Andric if (LocalAddr == MAP_FAILED) { 225*fcaf7f86SDimitry Andric return OnReserved(errorCodeToError( 226*fcaf7f86SDimitry Andric std::error_code(errno, std::generic_category()))); 227*fcaf7f86SDimitry Andric } 228*fcaf7f86SDimitry Andric 229*fcaf7f86SDimitry Andric close(SharedMemoryFile); 230*fcaf7f86SDimitry Andric 231*fcaf7f86SDimitry Andric #elif defined(_WIN32) 232*fcaf7f86SDimitry Andric 233*fcaf7f86SDimitry Andric std::wstring WideSharedMemoryName(SharedMemoryName.begin(), 234*fcaf7f86SDimitry Andric SharedMemoryName.end()); 235*fcaf7f86SDimitry Andric HANDLE SharedMemoryFile = OpenFileMappingW( 236*fcaf7f86SDimitry Andric FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str()); 237*fcaf7f86SDimitry Andric if (!SharedMemoryFile) 238*fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 239*fcaf7f86SDimitry Andric 240*fcaf7f86SDimitry Andric LocalAddr = 241*fcaf7f86SDimitry Andric MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 242*fcaf7f86SDimitry Andric if (!LocalAddr) { 243*fcaf7f86SDimitry Andric CloseHandle(SharedMemoryFile); 244*fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 245*fcaf7f86SDimitry Andric } 246*fcaf7f86SDimitry Andric 247*fcaf7f86SDimitry Andric CloseHandle(SharedMemoryFile); 248*fcaf7f86SDimitry Andric 249*fcaf7f86SDimitry Andric #endif 250*fcaf7f86SDimitry Andric { 251*fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 252*fcaf7f86SDimitry Andric Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}}); 253*fcaf7f86SDimitry Andric } 254*fcaf7f86SDimitry Andric 255*fcaf7f86SDimitry Andric OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes)); 256*fcaf7f86SDimitry Andric }, 257*fcaf7f86SDimitry Andric SAs.Instance, static_cast<uint64_t>(NumBytes)); 258*fcaf7f86SDimitry Andric 259*fcaf7f86SDimitry Andric #else 260*fcaf7f86SDimitry Andric OnReserved(make_error<StringError>( 261*fcaf7f86SDimitry Andric "SharedMemoryMapper is not supported on this platform yet", 262*fcaf7f86SDimitry Andric inconvertibleErrorCode())); 263*fcaf7f86SDimitry Andric #endif 264*fcaf7f86SDimitry Andric } 265*fcaf7f86SDimitry Andric 266*fcaf7f86SDimitry Andric char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 267*fcaf7f86SDimitry Andric auto R = Reservations.upper_bound(Addr); 268*fcaf7f86SDimitry Andric assert(R != Reservations.begin() && "Attempt to prepare unknown range"); 269*fcaf7f86SDimitry Andric R--; 270*fcaf7f86SDimitry Andric 271*fcaf7f86SDimitry Andric ExecutorAddrDiff Offset = Addr - R->first; 272*fcaf7f86SDimitry Andric 273*fcaf7f86SDimitry Andric return static_cast<char *>(R->second.LocalAddr) + Offset; 274*fcaf7f86SDimitry Andric } 275*fcaf7f86SDimitry Andric 276*fcaf7f86SDimitry Andric void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 277*fcaf7f86SDimitry Andric OnInitializedFunction OnInitialized) { 278*fcaf7f86SDimitry Andric auto Reservation = Reservations.find(AI.MappingBase); 279*fcaf7f86SDimitry Andric assert(Reservation != Reservations.end() && 280*fcaf7f86SDimitry Andric "Attempt to initialize unreserved range"); 281*fcaf7f86SDimitry Andric 282*fcaf7f86SDimitry Andric tpctypes::SharedMemoryFinalizeRequest FR; 283*fcaf7f86SDimitry Andric 284*fcaf7f86SDimitry Andric AI.Actions.swap(FR.Actions); 285*fcaf7f86SDimitry Andric 286*fcaf7f86SDimitry Andric FR.Segments.reserve(AI.Segments.size()); 287*fcaf7f86SDimitry Andric 288*fcaf7f86SDimitry Andric for (auto Segment : AI.Segments) { 289*fcaf7f86SDimitry Andric char *Base = 290*fcaf7f86SDimitry Andric static_cast<char *>(Reservation->second.LocalAddr) + Segment.Offset; 291*fcaf7f86SDimitry Andric std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize); 292*fcaf7f86SDimitry Andric 293*fcaf7f86SDimitry Andric tpctypes::SharedMemorySegFinalizeRequest SegReq; 294*fcaf7f86SDimitry Andric SegReq.Prot = tpctypes::toWireProtectionFlags( 295*fcaf7f86SDimitry Andric static_cast<sys::Memory::ProtectionFlags>(Segment.Prot)); 296*fcaf7f86SDimitry Andric SegReq.Addr = AI.MappingBase + Segment.Offset; 297*fcaf7f86SDimitry Andric SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize; 298*fcaf7f86SDimitry Andric 299*fcaf7f86SDimitry Andric FR.Segments.push_back(SegReq); 300*fcaf7f86SDimitry Andric } 301*fcaf7f86SDimitry Andric 302*fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 303*fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>( 304*fcaf7f86SDimitry Andric SAs.Initialize, 305*fcaf7f86SDimitry Andric [OnInitialized = std::move(OnInitialized)]( 306*fcaf7f86SDimitry Andric Error SerializationErr, Expected<ExecutorAddr> Result) mutable { 307*fcaf7f86SDimitry Andric if (SerializationErr) { 308*fcaf7f86SDimitry Andric cantFail(Result.takeError()); 309*fcaf7f86SDimitry Andric return OnInitialized(std::move(SerializationErr)); 310*fcaf7f86SDimitry Andric } 311*fcaf7f86SDimitry Andric 312*fcaf7f86SDimitry Andric OnInitialized(std::move(Result)); 313*fcaf7f86SDimitry Andric }, 314*fcaf7f86SDimitry Andric SAs.Instance, AI.MappingBase, std::move(FR)); 315*fcaf7f86SDimitry Andric } 316*fcaf7f86SDimitry Andric 317*fcaf7f86SDimitry Andric void SharedMemoryMapper::deinitialize( 318*fcaf7f86SDimitry Andric ArrayRef<ExecutorAddr> Allocations, 319*fcaf7f86SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 320*fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 321*fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>( 322*fcaf7f86SDimitry Andric SAs.Deinitialize, 323*fcaf7f86SDimitry Andric [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr, 324*fcaf7f86SDimitry Andric Error Result) mutable { 325*fcaf7f86SDimitry Andric if (SerializationErr) { 326*fcaf7f86SDimitry Andric cantFail(std::move(Result)); 327*fcaf7f86SDimitry Andric return OnDeinitialized(std::move(SerializationErr)); 328*fcaf7f86SDimitry Andric } 329*fcaf7f86SDimitry Andric 330*fcaf7f86SDimitry Andric OnDeinitialized(std::move(Result)); 331*fcaf7f86SDimitry Andric }, 332*fcaf7f86SDimitry Andric SAs.Instance, Allocations); 333*fcaf7f86SDimitry Andric } 334*fcaf7f86SDimitry Andric 335*fcaf7f86SDimitry Andric void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 336*fcaf7f86SDimitry Andric OnReleasedFunction OnReleased) { 337*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) || defined(_WIN32) 338*fcaf7f86SDimitry Andric Error Err = Error::success(); 339*fcaf7f86SDimitry Andric 340*fcaf7f86SDimitry Andric { 341*fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 342*fcaf7f86SDimitry Andric 343*fcaf7f86SDimitry Andric for (auto Base : Bases) { 344*fcaf7f86SDimitry Andric 345*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) 346*fcaf7f86SDimitry Andric 347*fcaf7f86SDimitry Andric if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0) 348*fcaf7f86SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(std::error_code( 349*fcaf7f86SDimitry Andric errno, std::generic_category()))); 350*fcaf7f86SDimitry Andric 351*fcaf7f86SDimitry Andric #elif defined(_WIN32) 352*fcaf7f86SDimitry Andric 353*fcaf7f86SDimitry Andric if (!UnmapViewOfFile(Reservations[Base].LocalAddr)) 354*fcaf7f86SDimitry Andric joinErrors(std::move(Err), 355*fcaf7f86SDimitry Andric errorCodeToError(mapWindowsError(GetLastError()))); 356*fcaf7f86SDimitry Andric 357*fcaf7f86SDimitry Andric #endif 358*fcaf7f86SDimitry Andric 359*fcaf7f86SDimitry Andric Reservations.erase(Base); 360*fcaf7f86SDimitry Andric } 361*fcaf7f86SDimitry Andric } 362*fcaf7f86SDimitry Andric 363*fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync< 364*fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>( 365*fcaf7f86SDimitry Andric SAs.Release, 366*fcaf7f86SDimitry Andric [OnReleased = std::move(OnReleased), 367*fcaf7f86SDimitry Andric Err = std::move(Err)](Error SerializationErr, Error Result) mutable { 368*fcaf7f86SDimitry Andric if (SerializationErr) { 369*fcaf7f86SDimitry Andric cantFail(std::move(Result)); 370*fcaf7f86SDimitry Andric return OnReleased( 371*fcaf7f86SDimitry Andric joinErrors(std::move(Err), std::move(SerializationErr))); 372*fcaf7f86SDimitry Andric } 373*fcaf7f86SDimitry Andric 374*fcaf7f86SDimitry Andric return OnReleased(joinErrors(std::move(Err), std::move(Result))); 375*fcaf7f86SDimitry Andric }, 376*fcaf7f86SDimitry Andric SAs.Instance, Bases); 377*fcaf7f86SDimitry Andric #else 378*fcaf7f86SDimitry Andric OnReleased(make_error<StringError>( 379*fcaf7f86SDimitry Andric "SharedMemoryMapper is not supported on this platform yet", 380*fcaf7f86SDimitry Andric inconvertibleErrorCode())); 381*fcaf7f86SDimitry Andric #endif 382*fcaf7f86SDimitry Andric } 383*fcaf7f86SDimitry Andric 384*fcaf7f86SDimitry Andric SharedMemoryMapper::~SharedMemoryMapper() { 385*fcaf7f86SDimitry Andric std::vector<ExecutorAddr> ReservationAddrs; 386*fcaf7f86SDimitry Andric if (!Reservations.empty()) { 387*fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex); 388*fcaf7f86SDimitry Andric { 389*fcaf7f86SDimitry Andric ReservationAddrs.reserve(Reservations.size()); 390*fcaf7f86SDimitry Andric for (const auto &R : Reservations) { 391*fcaf7f86SDimitry Andric ReservationAddrs.push_back(R.first); 392*fcaf7f86SDimitry Andric } 393*fcaf7f86SDimitry Andric } 394*fcaf7f86SDimitry Andric } 395*fcaf7f86SDimitry Andric 396*fcaf7f86SDimitry Andric std::promise<MSVCPError> P; 397*fcaf7f86SDimitry Andric auto F = P.get_future(); 398*fcaf7f86SDimitry Andric release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 399*fcaf7f86SDimitry Andric // FIXME: Release can actually fail. The error should be propagated. 400*fcaf7f86SDimitry Andric // Meanwhile, a better option is to explicitly call release(). 401*fcaf7f86SDimitry Andric cantFail(F.get()); 402*fcaf7f86SDimitry Andric } 403*fcaf7f86SDimitry Andric 40481ad6265SDimitry Andric } // namespace orc 40581ad6265SDimitry Andric 40681ad6265SDimitry Andric } // namespace llvm 407