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 11*89e6a288SDaniil Fukalov #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX 121b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 131b1f1c77SAnubhab Ghosh #include "llvm/Support/WindowsError.h" 140ecfee0bSAnubhab Ghosh 15ac3cb4ecSAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) 161b1f1c77SAnubhab Ghosh #include <fcntl.h> 171b1f1c77SAnubhab Ghosh #include <sys/mman.h> 18ee736519SFanbo Meng #if defined(__MVS__) 19ee736519SFanbo Meng #include "llvm/Support/BLAKE3.h" 20ee736519SFanbo Meng #include <sys/shm.h> 21ee736519SFanbo Meng #endif 221b1f1c77SAnubhab Ghosh #include <unistd.h> 231b1f1c77SAnubhab Ghosh #elif defined(_WIN32) 241b1f1c77SAnubhab Ghosh #include <windows.h> 251b1f1c77SAnubhab Ghosh #endif 261b1f1c77SAnubhab Ghosh 2779fbee3cSAnubhab Ghosh namespace llvm { 2879fbee3cSAnubhab Ghosh namespace orc { 2979fbee3cSAnubhab Ghosh 3079fbee3cSAnubhab Ghosh MemoryMapper::~MemoryMapper() {} 3179fbee3cSAnubhab Ghosh 324fcf8434SAnubhab Ghosh InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize) 334fcf8434SAnubhab Ghosh : PageSize(PageSize) {} 344fcf8434SAnubhab Ghosh 354fcf8434SAnubhab Ghosh Expected<std::unique_ptr<InProcessMemoryMapper>> 364fcf8434SAnubhab Ghosh InProcessMemoryMapper::Create() { 374fcf8434SAnubhab Ghosh auto PageSize = sys::Process::getPageSize(); 384fcf8434SAnubhab Ghosh if (!PageSize) 394fcf8434SAnubhab Ghosh return PageSize.takeError(); 404fcf8434SAnubhab Ghosh return std::make_unique<InProcessMemoryMapper>(*PageSize); 414fcf8434SAnubhab Ghosh } 424fcf8434SAnubhab Ghosh 4379fbee3cSAnubhab Ghosh void InProcessMemoryMapper::reserve(size_t NumBytes, 4479fbee3cSAnubhab Ghosh OnReservedFunction OnReserved) { 4579fbee3cSAnubhab Ghosh std::error_code EC; 4679fbee3cSAnubhab Ghosh auto MB = sys::Memory::allocateMappedMemory( 4779fbee3cSAnubhab Ghosh NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); 4879fbee3cSAnubhab Ghosh 4979fbee3cSAnubhab Ghosh if (EC) 5079fbee3cSAnubhab Ghosh return OnReserved(errorCodeToError(EC)); 5179fbee3cSAnubhab Ghosh 5279fbee3cSAnubhab Ghosh { 5379fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 5479fbee3cSAnubhab Ghosh Reservations[MB.base()].Size = MB.allocatedSize(); 5579fbee3cSAnubhab Ghosh } 5679fbee3cSAnubhab Ghosh 5779fbee3cSAnubhab Ghosh OnReserved( 5879fbee3cSAnubhab Ghosh ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize())); 5979fbee3cSAnubhab Ghosh } 6079fbee3cSAnubhab Ghosh 6179fbee3cSAnubhab Ghosh char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 6279fbee3cSAnubhab Ghosh return Addr.toPtr<char *>(); 6379fbee3cSAnubhab Ghosh } 6479fbee3cSAnubhab Ghosh 6579fbee3cSAnubhab Ghosh void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 6679fbee3cSAnubhab Ghosh OnInitializedFunction OnInitialized) { 6779fbee3cSAnubhab Ghosh ExecutorAddr MinAddr(~0ULL); 68a31af321SAnubhab Ghosh ExecutorAddr MaxAddr(0); 6979fbee3cSAnubhab Ghosh 70d3d9f7caSLang Hames // FIXME: Release finalize lifetime segments. 7179fbee3cSAnubhab Ghosh for (auto &Segment : AI.Segments) { 7279fbee3cSAnubhab Ghosh auto Base = AI.MappingBase + Segment.Offset; 7379fbee3cSAnubhab Ghosh auto Size = Segment.ContentSize + Segment.ZeroFillSize; 7479fbee3cSAnubhab Ghosh 7579fbee3cSAnubhab Ghosh if (Base < MinAddr) 7679fbee3cSAnubhab Ghosh MinAddr = Base; 7779fbee3cSAnubhab Ghosh 78a31af321SAnubhab Ghosh if (Base + Size > MaxAddr) 79a31af321SAnubhab Ghosh MaxAddr = Base + Size; 80a31af321SAnubhab Ghosh 8179fbee3cSAnubhab Ghosh std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0, 8279fbee3cSAnubhab Ghosh Segment.ZeroFillSize); 8379fbee3cSAnubhab Ghosh 84d3d9f7caSLang Hames if (auto EC = sys::Memory::protectMappedMemory( 85d3d9f7caSLang Hames {Base.toPtr<void *>(), Size}, 86d3d9f7caSLang Hames toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) { 8779fbee3cSAnubhab Ghosh return OnInitialized(errorCodeToError(EC)); 8879fbee3cSAnubhab Ghosh } 89d3d9f7caSLang Hames if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec) 9079fbee3cSAnubhab Ghosh sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size); 9179fbee3cSAnubhab Ghosh } 9279fbee3cSAnubhab Ghosh 9379fbee3cSAnubhab Ghosh auto DeinitializeActions = shared::runFinalizeActions(AI.Actions); 9479fbee3cSAnubhab Ghosh if (!DeinitializeActions) 9579fbee3cSAnubhab Ghosh return OnInitialized(DeinitializeActions.takeError()); 9679fbee3cSAnubhab Ghosh 9779fbee3cSAnubhab Ghosh { 9879fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 99a31af321SAnubhab Ghosh 100a31af321SAnubhab Ghosh // This is the maximum range whose permission have been possibly modified 101a31af321SAnubhab Ghosh Allocations[MinAddr].Size = MaxAddr - MinAddr; 10279fbee3cSAnubhab Ghosh Allocations[MinAddr].DeinitializationActions = 10379fbee3cSAnubhab Ghosh std::move(*DeinitializeActions); 10479fbee3cSAnubhab Ghosh Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr); 10579fbee3cSAnubhab Ghosh } 10679fbee3cSAnubhab Ghosh 10779fbee3cSAnubhab Ghosh OnInitialized(MinAddr); 10879fbee3cSAnubhab Ghosh } 10979fbee3cSAnubhab Ghosh 11079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::deinitialize( 11179fbee3cSAnubhab Ghosh ArrayRef<ExecutorAddr> Bases, 11279fbee3cSAnubhab Ghosh MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 11379fbee3cSAnubhab Ghosh Error AllErr = Error::success(); 11479fbee3cSAnubhab Ghosh 11579fbee3cSAnubhab Ghosh { 11679fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 11779fbee3cSAnubhab Ghosh 118349e5bd2SLang Hames for (auto Base : llvm::reverse(Bases)) { 11979fbee3cSAnubhab Ghosh 12079fbee3cSAnubhab Ghosh if (Error Err = shared::runDeallocActions( 12179fbee3cSAnubhab Ghosh Allocations[Base].DeinitializationActions)) { 12279fbee3cSAnubhab Ghosh AllErr = joinErrors(std::move(AllErr), std::move(Err)); 12379fbee3cSAnubhab Ghosh } 12479fbee3cSAnubhab Ghosh 125a31af321SAnubhab Ghosh // Reset protections to read/write so the area can be reused 126a31af321SAnubhab Ghosh if (auto EC = sys::Memory::protectMappedMemory( 127a31af321SAnubhab Ghosh {Base.toPtr<void *>(), Allocations[Base].Size}, 128a31af321SAnubhab Ghosh sys::Memory::ProtectionFlags::MF_READ | 129a31af321SAnubhab Ghosh sys::Memory::ProtectionFlags::MF_WRITE)) { 130a31af321SAnubhab Ghosh AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC)); 131a31af321SAnubhab Ghosh } 132a31af321SAnubhab Ghosh 13379fbee3cSAnubhab Ghosh Allocations.erase(Base); 13479fbee3cSAnubhab Ghosh } 13579fbee3cSAnubhab Ghosh } 13679fbee3cSAnubhab Ghosh 13779fbee3cSAnubhab Ghosh OnDeinitialized(std::move(AllErr)); 13879fbee3cSAnubhab Ghosh } 13979fbee3cSAnubhab Ghosh 14079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 14179fbee3cSAnubhab Ghosh OnReleasedFunction OnReleased) { 14279fbee3cSAnubhab Ghosh Error Err = Error::success(); 14379fbee3cSAnubhab Ghosh 14479fbee3cSAnubhab Ghosh for (auto Base : Bases) { 14579fbee3cSAnubhab Ghosh std::vector<ExecutorAddr> AllocAddrs; 14679fbee3cSAnubhab Ghosh size_t Size; 14779fbee3cSAnubhab Ghosh { 14879fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 14979fbee3cSAnubhab Ghosh auto &R = Reservations[Base.toPtr<void *>()]; 15079fbee3cSAnubhab Ghosh Size = R.Size; 15179fbee3cSAnubhab Ghosh AllocAddrs.swap(R.Allocations); 15279fbee3cSAnubhab Ghosh } 15379fbee3cSAnubhab Ghosh 15479fbee3cSAnubhab Ghosh // deinitialize sub allocations 15579fbee3cSAnubhab Ghosh std::promise<MSVCPError> P; 15679fbee3cSAnubhab Ghosh auto F = P.get_future(); 15779fbee3cSAnubhab Ghosh deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 15879fbee3cSAnubhab Ghosh if (Error E = F.get()) { 15979fbee3cSAnubhab Ghosh Err = joinErrors(std::move(Err), std::move(E)); 16079fbee3cSAnubhab Ghosh } 16179fbee3cSAnubhab Ghosh 16279fbee3cSAnubhab Ghosh // free the memory 16379fbee3cSAnubhab Ghosh auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size); 16479fbee3cSAnubhab Ghosh 16579fbee3cSAnubhab Ghosh auto EC = sys::Memory::releaseMappedMemory(MB); 16679fbee3cSAnubhab Ghosh if (EC) { 16779fbee3cSAnubhab Ghosh Err = joinErrors(std::move(Err), errorCodeToError(EC)); 16879fbee3cSAnubhab Ghosh } 16979fbee3cSAnubhab Ghosh 17079fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 17179fbee3cSAnubhab Ghosh Reservations.erase(Base.toPtr<void *>()); 17279fbee3cSAnubhab Ghosh } 17379fbee3cSAnubhab Ghosh 17479fbee3cSAnubhab Ghosh OnReleased(std::move(Err)); 17579fbee3cSAnubhab Ghosh } 17679fbee3cSAnubhab Ghosh 17779fbee3cSAnubhab Ghosh InProcessMemoryMapper::~InProcessMemoryMapper() { 17879fbee3cSAnubhab Ghosh std::vector<ExecutorAddr> ReservationAddrs; 17979fbee3cSAnubhab Ghosh { 18079fbee3cSAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 18179fbee3cSAnubhab Ghosh 18279fbee3cSAnubhab Ghosh ReservationAddrs.reserve(Reservations.size()); 18379fbee3cSAnubhab Ghosh for (const auto &R : Reservations) { 18479fbee3cSAnubhab Ghosh ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst())); 18579fbee3cSAnubhab Ghosh } 18679fbee3cSAnubhab Ghosh } 18779fbee3cSAnubhab Ghosh 18879fbee3cSAnubhab Ghosh std::promise<MSVCPError> P; 18979fbee3cSAnubhab Ghosh auto F = P.get_future(); 19079fbee3cSAnubhab Ghosh release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); 19179fbee3cSAnubhab Ghosh cantFail(F.get()); 19279fbee3cSAnubhab Ghosh } 19379fbee3cSAnubhab Ghosh 1941b1f1c77SAnubhab Ghosh // SharedMemoryMapper 1951b1f1c77SAnubhab Ghosh 1964fcf8434SAnubhab Ghosh SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC, 1974fcf8434SAnubhab Ghosh SymbolAddrs SAs, size_t PageSize) 198ac3cb4ecSAnubhab Ghosh : EPC(EPC), SAs(SAs), PageSize(PageSize) { 199ac3cb4ecSAnubhab Ghosh #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32) 200ac3cb4ecSAnubhab Ghosh llvm_unreachable("SharedMemoryMapper is not supported on this platform yet"); 201ac3cb4ecSAnubhab Ghosh #endif 202ac3cb4ecSAnubhab Ghosh } 2034fcf8434SAnubhab Ghosh 2044fcf8434SAnubhab Ghosh Expected<std::unique_ptr<SharedMemoryMapper>> 2054fcf8434SAnubhab Ghosh SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) { 206ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 2074fcf8434SAnubhab Ghosh auto PageSize = sys::Process::getPageSize(); 2084fcf8434SAnubhab Ghosh if (!PageSize) 2094fcf8434SAnubhab Ghosh return PageSize.takeError(); 2104fcf8434SAnubhab Ghosh 2114fcf8434SAnubhab Ghosh return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize); 212ac3cb4ecSAnubhab Ghosh #else 213ac3cb4ecSAnubhab Ghosh return make_error<StringError>( 214ac3cb4ecSAnubhab Ghosh "SharedMemoryMapper is not supported on this platform yet", 215ac3cb4ecSAnubhab Ghosh inconvertibleErrorCode()); 216ac3cb4ecSAnubhab Ghosh #endif 2174fcf8434SAnubhab Ghosh } 2184fcf8434SAnubhab Ghosh 2191b1f1c77SAnubhab Ghosh void SharedMemoryMapper::reserve(size_t NumBytes, 2201b1f1c77SAnubhab Ghosh OnReservedFunction OnReserved) { 221ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 2221b1f1c77SAnubhab Ghosh 2231b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 2241b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>( 2251b1f1c77SAnubhab Ghosh SAs.Reserve, 2261b1f1c77SAnubhab Ghosh [this, NumBytes, OnReserved = std::move(OnReserved)]( 2271b1f1c77SAnubhab Ghosh Error SerializationErr, 2281b1f1c77SAnubhab Ghosh Expected<std::pair<ExecutorAddr, std::string>> Result) mutable { 2291b1f1c77SAnubhab Ghosh if (SerializationErr) { 2301b1f1c77SAnubhab Ghosh cantFail(Result.takeError()); 2311b1f1c77SAnubhab Ghosh return OnReserved(std::move(SerializationErr)); 2321b1f1c77SAnubhab Ghosh } 2331b1f1c77SAnubhab Ghosh 2341b1f1c77SAnubhab Ghosh if (!Result) 2351b1f1c77SAnubhab Ghosh return OnReserved(Result.takeError()); 2361b1f1c77SAnubhab Ghosh 2371b1f1c77SAnubhab Ghosh ExecutorAddr RemoteAddr; 2381b1f1c77SAnubhab Ghosh std::string SharedMemoryName; 2391b1f1c77SAnubhab Ghosh std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result); 2401b1f1c77SAnubhab Ghosh 2411b1f1c77SAnubhab Ghosh void *LocalAddr = nullptr; 2421b1f1c77SAnubhab Ghosh 2431b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX) 2441b1f1c77SAnubhab Ghosh 245ee736519SFanbo Meng #if defined(__MVS__) 246ee736519SFanbo Meng ArrayRef<uint8_t> Data( 247ee736519SFanbo Meng reinterpret_cast<const uint8_t *>(SharedMemoryName.c_str()), 248ee736519SFanbo Meng SharedMemoryName.size()); 249ee736519SFanbo Meng auto HashedName = BLAKE3::hash<sizeof(key_t)>(Data); 250ee736519SFanbo Meng key_t Key = *reinterpret_cast<key_t *>(HashedName.data()); 251ee736519SFanbo Meng int SharedMemoryId = 252ee736519SFanbo Meng shmget(Key, NumBytes, IPC_CREAT | __IPC_SHAREAS | 0700); 253ee736519SFanbo Meng if (SharedMemoryId < 0) { 254ee736519SFanbo Meng return OnReserved(errorCodeToError( 255ee736519SFanbo Meng std::error_code(errno, std::generic_category()))); 256ee736519SFanbo Meng } 257ee736519SFanbo Meng LocalAddr = shmat(SharedMemoryId, nullptr, 0); 258ee736519SFanbo Meng if (LocalAddr == reinterpret_cast<void *>(-1)) { 259ee736519SFanbo Meng return OnReserved(errorCodeToError( 260ee736519SFanbo Meng std::error_code(errno, std::generic_category()))); 261ee736519SFanbo Meng } 262ee736519SFanbo Meng #else 2631b1f1c77SAnubhab Ghosh int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700); 2641b1f1c77SAnubhab Ghosh if (SharedMemoryFile < 0) { 265ba13fa2aSMichael Spencer return OnReserved(errorCodeToError(errnoAsErrorCode())); 2661b1f1c77SAnubhab Ghosh } 2671b1f1c77SAnubhab Ghosh 2681b1f1c77SAnubhab Ghosh // this prevents other processes from accessing it by name 2691b1f1c77SAnubhab Ghosh shm_unlink(SharedMemoryName.c_str()); 2701b1f1c77SAnubhab Ghosh 2711b1f1c77SAnubhab Ghosh LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED, 2721b1f1c77SAnubhab Ghosh SharedMemoryFile, 0); 2731b1f1c77SAnubhab Ghosh if (LocalAddr == MAP_FAILED) { 274ba13fa2aSMichael Spencer return OnReserved(errorCodeToError(errnoAsErrorCode())); 2751b1f1c77SAnubhab Ghosh } 2761b1f1c77SAnubhab Ghosh 2771b1f1c77SAnubhab Ghosh close(SharedMemoryFile); 278ee736519SFanbo Meng #endif 2791b1f1c77SAnubhab Ghosh 2801b1f1c77SAnubhab Ghosh #elif defined(_WIN32) 2811b1f1c77SAnubhab Ghosh 2821b1f1c77SAnubhab Ghosh std::wstring WideSharedMemoryName(SharedMemoryName.begin(), 2831b1f1c77SAnubhab Ghosh SharedMemoryName.end()); 2841b1f1c77SAnubhab Ghosh HANDLE SharedMemoryFile = OpenFileMappingW( 2851b1f1c77SAnubhab Ghosh FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str()); 2861b1f1c77SAnubhab Ghosh if (!SharedMemoryFile) 2871b1f1c77SAnubhab Ghosh return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 2881b1f1c77SAnubhab Ghosh 2891b1f1c77SAnubhab Ghosh LocalAddr = 2901b1f1c77SAnubhab Ghosh MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 2911b1f1c77SAnubhab Ghosh if (!LocalAddr) { 2921b1f1c77SAnubhab Ghosh CloseHandle(SharedMemoryFile); 2931b1f1c77SAnubhab Ghosh return OnReserved(errorCodeToError(mapWindowsError(GetLastError()))); 2941b1f1c77SAnubhab Ghosh } 2951b1f1c77SAnubhab Ghosh 2961b1f1c77SAnubhab Ghosh CloseHandle(SharedMemoryFile); 2971b1f1c77SAnubhab Ghosh 2981b1f1c77SAnubhab Ghosh #endif 2991b1f1c77SAnubhab Ghosh { 3001b1f1c77SAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 3011b1f1c77SAnubhab Ghosh Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}}); 3021b1f1c77SAnubhab Ghosh } 3031b1f1c77SAnubhab Ghosh 3041b1f1c77SAnubhab Ghosh OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes)); 3051b1f1c77SAnubhab Ghosh }, 3061b1f1c77SAnubhab Ghosh SAs.Instance, static_cast<uint64_t>(NumBytes)); 3071b1f1c77SAnubhab Ghosh 3081b1f1c77SAnubhab Ghosh #else 3091b1f1c77SAnubhab Ghosh OnReserved(make_error<StringError>( 3101b1f1c77SAnubhab Ghosh "SharedMemoryMapper is not supported on this platform yet", 3111b1f1c77SAnubhab Ghosh inconvertibleErrorCode())); 3121b1f1c77SAnubhab Ghosh #endif 3131b1f1c77SAnubhab Ghosh } 3141b1f1c77SAnubhab Ghosh 3151b1f1c77SAnubhab Ghosh char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { 3161b1f1c77SAnubhab Ghosh auto R = Reservations.upper_bound(Addr); 317ab492f62SAnubhab Ghosh assert(R != Reservations.begin() && "Attempt to prepare unreserved range"); 3181b1f1c77SAnubhab Ghosh R--; 3191b1f1c77SAnubhab Ghosh 3201b1f1c77SAnubhab Ghosh ExecutorAddrDiff Offset = Addr - R->first; 3211b1f1c77SAnubhab Ghosh 3221b1f1c77SAnubhab Ghosh return static_cast<char *>(R->second.LocalAddr) + Offset; 3231b1f1c77SAnubhab Ghosh } 3241b1f1c77SAnubhab Ghosh 3251b1f1c77SAnubhab Ghosh void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, 3261b1f1c77SAnubhab Ghosh OnInitializedFunction OnInitialized) { 327ab492f62SAnubhab Ghosh auto Reservation = Reservations.upper_bound(AI.MappingBase); 328ab492f62SAnubhab Ghosh assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range"); 329ab492f62SAnubhab Ghosh Reservation--; 330ab492f62SAnubhab Ghosh 331ab492f62SAnubhab Ghosh auto AllocationOffset = AI.MappingBase - Reservation->first; 3321b1f1c77SAnubhab Ghosh 3331b1f1c77SAnubhab Ghosh tpctypes::SharedMemoryFinalizeRequest FR; 3341b1f1c77SAnubhab Ghosh 3351b1f1c77SAnubhab Ghosh AI.Actions.swap(FR.Actions); 3361b1f1c77SAnubhab Ghosh 3371b1f1c77SAnubhab Ghosh FR.Segments.reserve(AI.Segments.size()); 3381b1f1c77SAnubhab Ghosh 3391b1f1c77SAnubhab Ghosh for (auto Segment : AI.Segments) { 340ab492f62SAnubhab Ghosh char *Base = static_cast<char *>(Reservation->second.LocalAddr) + 341ab492f62SAnubhab Ghosh AllocationOffset + Segment.Offset; 3421b1f1c77SAnubhab Ghosh std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize); 3431b1f1c77SAnubhab Ghosh 3441b1f1c77SAnubhab Ghosh tpctypes::SharedMemorySegFinalizeRequest SegReq; 345e994f84cSLang Hames SegReq.RAG = {Segment.AG.getMemProt(), 346e994f84cSLang Hames Segment.AG.getMemLifetime() == MemLifetime::Finalize}; 3471b1f1c77SAnubhab Ghosh SegReq.Addr = AI.MappingBase + Segment.Offset; 3481b1f1c77SAnubhab Ghosh SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize; 3491b1f1c77SAnubhab Ghosh 3501b1f1c77SAnubhab Ghosh FR.Segments.push_back(SegReq); 3511b1f1c77SAnubhab Ghosh } 3521b1f1c77SAnubhab Ghosh 3531b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 3541b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>( 3551b1f1c77SAnubhab Ghosh SAs.Initialize, 3561b1f1c77SAnubhab Ghosh [OnInitialized = std::move(OnInitialized)]( 3571b1f1c77SAnubhab Ghosh Error SerializationErr, Expected<ExecutorAddr> Result) mutable { 3581b1f1c77SAnubhab Ghosh if (SerializationErr) { 3591b1f1c77SAnubhab Ghosh cantFail(Result.takeError()); 3601b1f1c77SAnubhab Ghosh return OnInitialized(std::move(SerializationErr)); 3611b1f1c77SAnubhab Ghosh } 3621b1f1c77SAnubhab Ghosh 3631b1f1c77SAnubhab Ghosh OnInitialized(std::move(Result)); 3641b1f1c77SAnubhab Ghosh }, 3650ecfee0bSAnubhab Ghosh SAs.Instance, Reservation->first, std::move(FR)); 3661b1f1c77SAnubhab Ghosh } 3671b1f1c77SAnubhab Ghosh 3681b1f1c77SAnubhab Ghosh void SharedMemoryMapper::deinitialize( 3691b1f1c77SAnubhab Ghosh ArrayRef<ExecutorAddr> Allocations, 3701b1f1c77SAnubhab Ghosh MemoryMapper::OnDeinitializedFunction OnDeinitialized) { 3711b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 3721b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>( 3731b1f1c77SAnubhab Ghosh SAs.Deinitialize, 3741b1f1c77SAnubhab Ghosh [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr, 3751b1f1c77SAnubhab Ghosh Error Result) mutable { 3761b1f1c77SAnubhab Ghosh if (SerializationErr) { 3771b1f1c77SAnubhab Ghosh cantFail(std::move(Result)); 3781b1f1c77SAnubhab Ghosh return OnDeinitialized(std::move(SerializationErr)); 3791b1f1c77SAnubhab Ghosh } 3801b1f1c77SAnubhab Ghosh 3811b1f1c77SAnubhab Ghosh OnDeinitialized(std::move(Result)); 3821b1f1c77SAnubhab Ghosh }, 3831b1f1c77SAnubhab Ghosh SAs.Instance, Allocations); 3841b1f1c77SAnubhab Ghosh } 3851b1f1c77SAnubhab Ghosh 3861b1f1c77SAnubhab Ghosh void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, 3871b1f1c77SAnubhab Ghosh OnReleasedFunction OnReleased) { 388ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) 3891b1f1c77SAnubhab Ghosh Error Err = Error::success(); 3901b1f1c77SAnubhab Ghosh 3911b1f1c77SAnubhab Ghosh { 3921b1f1c77SAnubhab Ghosh std::lock_guard<std::mutex> Lock(Mutex); 3931b1f1c77SAnubhab Ghosh 3941b1f1c77SAnubhab Ghosh for (auto Base : Bases) { 3951b1f1c77SAnubhab Ghosh 3961b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX) 3971b1f1c77SAnubhab Ghosh 398ee736519SFanbo Meng #if defined(__MVS__) 399ee736519SFanbo Meng if (shmdt(Reservations[Base].LocalAddr) < 0) 400ee736519SFanbo Meng Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode())); 401ee736519SFanbo Meng #else 4021b1f1c77SAnubhab Ghosh if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0) 403ba13fa2aSMichael Spencer Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode())); 404ee736519SFanbo Meng #endif 4051b1f1c77SAnubhab Ghosh 4061b1f1c77SAnubhab Ghosh #elif defined(_WIN32) 4071b1f1c77SAnubhab Ghosh 4081b1f1c77SAnubhab Ghosh if (!UnmapViewOfFile(Reservations[Base].LocalAddr)) 40946bc1b56SMartin Storsjö Err = joinErrors(std::move(Err), 4101b1f1c77SAnubhab Ghosh errorCodeToError(mapWindowsError(GetLastError()))); 4111b1f1c77SAnubhab Ghosh 4121b1f1c77SAnubhab Ghosh #endif 4131b1f1c77SAnubhab Ghosh 4141b1f1c77SAnubhab Ghosh Reservations.erase(Base); 4151b1f1c77SAnubhab Ghosh } 4161b1f1c77SAnubhab Ghosh } 4171b1f1c77SAnubhab Ghosh 4181b1f1c77SAnubhab Ghosh EPC.callSPSWrapperAsync< 4191b1f1c77SAnubhab Ghosh rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>( 4201b1f1c77SAnubhab Ghosh SAs.Release, 4211b1f1c77SAnubhab Ghosh [OnReleased = std::move(OnReleased), 4221b1f1c77SAnubhab Ghosh Err = std::move(Err)](Error SerializationErr, Error Result) mutable { 4231b1f1c77SAnubhab Ghosh if (SerializationErr) { 4241b1f1c77SAnubhab Ghosh cantFail(std::move(Result)); 4251b1f1c77SAnubhab Ghosh return OnReleased( 4261b1f1c77SAnubhab Ghosh joinErrors(std::move(Err), std::move(SerializationErr))); 4271b1f1c77SAnubhab Ghosh } 4281b1f1c77SAnubhab Ghosh 4291b1f1c77SAnubhab Ghosh return OnReleased(joinErrors(std::move(Err), std::move(Result))); 4301b1f1c77SAnubhab Ghosh }, 4311b1f1c77SAnubhab Ghosh SAs.Instance, Bases); 4321b1f1c77SAnubhab Ghosh #else 4331b1f1c77SAnubhab Ghosh OnReleased(make_error<StringError>( 4341b1f1c77SAnubhab Ghosh "SharedMemoryMapper is not supported on this platform yet", 4351b1f1c77SAnubhab Ghosh inconvertibleErrorCode())); 4361b1f1c77SAnubhab Ghosh #endif 4371b1f1c77SAnubhab Ghosh } 4381b1f1c77SAnubhab Ghosh 4391b1f1c77SAnubhab Ghosh SharedMemoryMapper::~SharedMemoryMapper() { 4401c25ce17SAlexandre Ganea std::lock_guard<std::mutex> Lock(Mutex); 4413019f488SLang Hames for (const auto &R : Reservations) { 4421b1f1c77SAnubhab Ghosh 4431134d3a0SAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) 4441134d3a0SAnubhab Ghosh 445ee736519SFanbo Meng #if defined(__MVS__) 446ee736519SFanbo Meng shmdt(R.second.LocalAddr); 447ee736519SFanbo Meng #else 4481134d3a0SAnubhab Ghosh munmap(R.second.LocalAddr, R.second.Size); 449ee736519SFanbo Meng #endif 4501134d3a0SAnubhab Ghosh 4511134d3a0SAnubhab Ghosh #elif defined(_WIN32) 4521134d3a0SAnubhab Ghosh 4531134d3a0SAnubhab Ghosh UnmapViewOfFile(R.second.LocalAddr); 4541134d3a0SAnubhab Ghosh 4551c2ee6bdSDavid Blaikie #else 4561c2ee6bdSDavid Blaikie 4571c2ee6bdSDavid Blaikie (void)R; 4581c2ee6bdSDavid Blaikie 4591134d3a0SAnubhab Ghosh #endif 4601134d3a0SAnubhab Ghosh } 4611b1f1c77SAnubhab Ghosh } 4621b1f1c77SAnubhab Ghosh 46379fbee3cSAnubhab Ghosh } // namespace orc 46479fbee3cSAnubhab Ghosh 46579fbee3cSAnubhab Ghosh } // namespace llvm 466