diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp')
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp index ca3f64b8a409..b457c7297bed 100644 --- a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp +++ b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp @@ -11,7 +11,9 @@ #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" #include "llvm/Support/WindowsError.h" -#if defined(LLVM_ON_UNIX) +#include <algorithm> + +#if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> @@ -60,7 +62,9 @@ char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, OnInitializedFunction OnInitialized) { ExecutorAddr MinAddr(~0ULL); + ExecutorAddr MaxAddr(0); + // FIXME: Release finalize lifetime segments. for (auto &Segment : AI.Segments) { auto Base = AI.MappingBase + Segment.Offset; auto Size = Segment.ContentSize + Segment.ZeroFillSize; @@ -68,14 +72,18 @@ void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, if (Base < MinAddr) MinAddr = Base; + if (Base + Size > MaxAddr) + MaxAddr = Base + Size; + std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0, Segment.ZeroFillSize); - if (auto EC = sys::Memory::protectMappedMemory({Base.toPtr<void *>(), Size}, - Segment.Prot)) { + if (auto EC = sys::Memory::protectMappedMemory( + {Base.toPtr<void *>(), Size}, + toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) { return OnInitialized(errorCodeToError(EC)); } - if (Segment.Prot & sys::Memory::MF_EXEC) + if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec) sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size); } @@ -85,6 +93,9 @@ void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, { std::lock_guard<std::mutex> Lock(Mutex); + + // This is the maximum range whose permission have been possibly modified + Allocations[MinAddr].Size = MaxAddr - MinAddr; Allocations[MinAddr].DeinitializationActions = std::move(*DeinitializeActions); Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr); @@ -101,13 +112,21 @@ void InProcessMemoryMapper::deinitialize( { std::lock_guard<std::mutex> Lock(Mutex); - for (auto Base : Bases) { + for (auto Base : llvm::reverse(Bases)) { if (Error Err = shared::runDeallocActions( Allocations[Base].DeinitializationActions)) { AllErr = joinErrors(std::move(AllErr), std::move(Err)); } + // Reset protections to read/write so the area can be reused + if (auto EC = sys::Memory::protectMappedMemory( + {Base.toPtr<void *>(), Allocations[Base].Size}, + sys::Memory::ProtectionFlags::MF_READ | + sys::Memory::ProtectionFlags::MF_WRITE)) { + AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC)); + } + Allocations.erase(Base); } } @@ -173,20 +192,30 @@ InProcessMemoryMapper::~InProcessMemoryMapper() { SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs, size_t PageSize) - : EPC(EPC), SAs(SAs), PageSize(PageSize) {} + : EPC(EPC), SAs(SAs), PageSize(PageSize) { +#if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32) + llvm_unreachable("SharedMemoryMapper is not supported on this platform yet"); +#endif +} Expected<std::unique_ptr<SharedMemoryMapper>> SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) { +#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) auto PageSize = sys::Process::getPageSize(); if (!PageSize) return PageSize.takeError(); return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize); +#else + return make_error<StringError>( + "SharedMemoryMapper is not supported on this platform yet", + inconvertibleErrorCode()); +#endif } void SharedMemoryMapper::reserve(size_t NumBytes, OnReservedFunction OnReserved) { -#if defined(LLVM_ON_UNIX) || defined(_WIN32) +#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) EPC.callSPSWrapperAsync< rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>( @@ -265,7 +294,7 @@ void SharedMemoryMapper::reserve(size_t NumBytes, char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { auto R = Reservations.upper_bound(Addr); - assert(R != Reservations.begin() && "Attempt to prepare unknown range"); + assert(R != Reservations.begin() && "Attempt to prepare unreserved range"); R--; ExecutorAddrDiff Offset = Addr - R->first; @@ -275,9 +304,11 @@ char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) { void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, OnInitializedFunction OnInitialized) { - auto Reservation = Reservations.find(AI.MappingBase); - assert(Reservation != Reservations.end() && - "Attempt to initialize unreserved range"); + auto Reservation = Reservations.upper_bound(AI.MappingBase); + assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range"); + Reservation--; + + auto AllocationOffset = AI.MappingBase - Reservation->first; tpctypes::SharedMemoryFinalizeRequest FR; @@ -286,13 +317,12 @@ void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, FR.Segments.reserve(AI.Segments.size()); for (auto Segment : AI.Segments) { - char *Base = - static_cast<char *>(Reservation->second.LocalAddr) + Segment.Offset; + char *Base = static_cast<char *>(Reservation->second.LocalAddr) + + AllocationOffset + Segment.Offset; std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize); tpctypes::SharedMemorySegFinalizeRequest SegReq; - SegReq.Prot = tpctypes::toWireProtectionFlags( - static_cast<sys::Memory::ProtectionFlags>(Segment.Prot)); + SegReq.AG = Segment.AG; SegReq.Addr = AI.MappingBase + Segment.Offset; SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize; @@ -311,7 +341,7 @@ void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI, OnInitialized(std::move(Result)); }, - SAs.Instance, AI.MappingBase, std::move(FR)); + SAs.Instance, Reservation->first, std::move(FR)); } void SharedMemoryMapper::deinitialize( @@ -334,7 +364,7 @@ void SharedMemoryMapper::deinitialize( void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, OnReleasedFunction OnReleased) { -#if defined(LLVM_ON_UNIX) || defined(_WIN32) +#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32) Error Err = Error::success(); { @@ -351,8 +381,8 @@ void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, #elif defined(_WIN32) if (!UnmapViewOfFile(Reservations[Base].LocalAddr)) - joinErrors(std::move(Err), - errorCodeToError(mapWindowsError(GetLastError()))); + Err = joinErrors(std::move(Err), + errorCodeToError(mapWindowsError(GetLastError()))); #endif @@ -382,23 +412,23 @@ void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases, } SharedMemoryMapper::~SharedMemoryMapper() { - std::vector<ExecutorAddr> ReservationAddrs; - if (!Reservations.empty()) { - std::lock_guard<std::mutex> Lock(Mutex); - { - ReservationAddrs.reserve(Reservations.size()); - for (const auto &R : Reservations) { - ReservationAddrs.push_back(R.first); - } - } - } + std::lock_guard<std::mutex> Lock(Mutex); + for (const auto &R : Reservations) { - std::promise<MSVCPError> P; - auto F = P.get_future(); - release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); }); - // FIXME: Release can actually fail. The error should be propagated. - // Meanwhile, a better option is to explicitly call release(). - cantFail(F.get()); +#if defined(LLVM_ON_UNIX) && !defined(__ANDROID__) + + munmap(R.second.LocalAddr, R.second.Size); + +#elif defined(_WIN32) + + UnmapViewOfFile(R.second.LocalAddr); + +#else + + (void)R; + +#endif + } } } // namespace orc |