181ad6265SDimitry Andric //===- MemoryMapper.h - 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 // Cross-process (and in-process) memory mapping and transfer 1081ad6265SDimitry Andric // 1181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H 1481ad6265SDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H 1581ad6265SDimitry Andric 1681ad6265SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h" 17*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h" 18fcaf7f86SDimitry Andric #include "llvm/Support/Process.h" 1981ad6265SDimitry Andric 2081ad6265SDimitry Andric #include <mutex> 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric namespace llvm { 2381ad6265SDimitry Andric namespace orc { 2481ad6265SDimitry Andric 2581ad6265SDimitry Andric /// Manages mapping, content transfer and protections for JIT memory 2681ad6265SDimitry Andric class MemoryMapper { 2781ad6265SDimitry Andric public: 2881ad6265SDimitry Andric /// Represents a single allocation containing multiple segments and 2981ad6265SDimitry Andric /// initialization and deinitialization actions 3081ad6265SDimitry Andric struct AllocInfo { 3181ad6265SDimitry Andric struct SegInfo { 3281ad6265SDimitry Andric ExecutorAddrDiff Offset; 3381ad6265SDimitry Andric const char *WorkingMem; 3481ad6265SDimitry Andric size_t ContentSize; 3581ad6265SDimitry Andric size_t ZeroFillSize; 36*bdd1243dSDimitry Andric AllocGroup AG; 3781ad6265SDimitry Andric }; 3881ad6265SDimitry Andric 3981ad6265SDimitry Andric ExecutorAddr MappingBase; 4081ad6265SDimitry Andric std::vector<SegInfo> Segments; 4181ad6265SDimitry Andric shared::AllocActions Actions; 4281ad6265SDimitry Andric }; 4381ad6265SDimitry Andric 4481ad6265SDimitry Andric using OnReservedFunction = unique_function<void(Expected<ExecutorAddrRange>)>; 4581ad6265SDimitry Andric 46fcaf7f86SDimitry Andric // Page size of the target process 47fcaf7f86SDimitry Andric virtual unsigned int getPageSize() = 0; 48fcaf7f86SDimitry Andric 4981ad6265SDimitry Andric /// Reserves address space in executor process 5081ad6265SDimitry Andric virtual void reserve(size_t NumBytes, OnReservedFunction OnReserved) = 0; 5181ad6265SDimitry Andric 5281ad6265SDimitry Andric /// Provides working memory 5381ad6265SDimitry Andric virtual char *prepare(ExecutorAddr Addr, size_t ContentSize) = 0; 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric using OnInitializedFunction = unique_function<void(Expected<ExecutorAddr>)>; 5681ad6265SDimitry Andric 5781ad6265SDimitry Andric /// Ensures executor memory is synchronized with working copy memory, sends 5881ad6265SDimitry Andric /// functions to be called after initilization and before deinitialization and 5981ad6265SDimitry Andric /// applies memory protections 6081ad6265SDimitry Andric /// Returns a unique address identifying the allocation. This address should 6181ad6265SDimitry Andric /// be passed to deinitialize to run deallocation actions (and reset 6281ad6265SDimitry Andric /// permissions where possible). 6381ad6265SDimitry Andric virtual void initialize(AllocInfo &AI, 6481ad6265SDimitry Andric OnInitializedFunction OnInitialized) = 0; 6581ad6265SDimitry Andric 6681ad6265SDimitry Andric using OnDeinitializedFunction = unique_function<void(Error)>; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric /// Runs previously specified deinitialization actions 6981ad6265SDimitry Andric /// Executor addresses returned by initialize should be passed 7081ad6265SDimitry Andric virtual void deinitialize(ArrayRef<ExecutorAddr> Allocations, 7181ad6265SDimitry Andric OnDeinitializedFunction OnDeInitialized) = 0; 7281ad6265SDimitry Andric 7381ad6265SDimitry Andric using OnReleasedFunction = unique_function<void(Error)>; 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric /// Release address space acquired through reserve() 7681ad6265SDimitry Andric virtual void release(ArrayRef<ExecutorAddr> Reservations, 7781ad6265SDimitry Andric OnReleasedFunction OnRelease) = 0; 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric virtual ~MemoryMapper(); 8081ad6265SDimitry Andric }; 8181ad6265SDimitry Andric 82*bdd1243dSDimitry Andric class InProcessMemoryMapper : public MemoryMapper { 8381ad6265SDimitry Andric public: 84fcaf7f86SDimitry Andric InProcessMemoryMapper(size_t PageSize); 85fcaf7f86SDimitry Andric 86fcaf7f86SDimitry Andric static Expected<std::unique_ptr<InProcessMemoryMapper>> Create(); 87fcaf7f86SDimitry Andric getPageSize()88fcaf7f86SDimitry Andric unsigned int getPageSize() override { return PageSize; } 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric void reserve(size_t NumBytes, OnReservedFunction OnReserved) override; 9181ad6265SDimitry Andric 9281ad6265SDimitry Andric void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override; 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric char *prepare(ExecutorAddr Addr, size_t ContentSize) override; 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric void deinitialize(ArrayRef<ExecutorAddr> Allocations, 9781ad6265SDimitry Andric OnDeinitializedFunction OnDeInitialized) override; 9881ad6265SDimitry Andric 9981ad6265SDimitry Andric void release(ArrayRef<ExecutorAddr> Reservations, 10081ad6265SDimitry Andric OnReleasedFunction OnRelease) override; 10181ad6265SDimitry Andric 10281ad6265SDimitry Andric ~InProcessMemoryMapper() override; 10381ad6265SDimitry Andric 10481ad6265SDimitry Andric private: 10581ad6265SDimitry Andric struct Allocation { 106*bdd1243dSDimitry Andric size_t Size; 10781ad6265SDimitry Andric std::vector<shared::WrapperFunctionCall> DeinitializationActions; 10881ad6265SDimitry Andric }; 10981ad6265SDimitry Andric using AllocationMap = DenseMap<ExecutorAddr, Allocation>; 11081ad6265SDimitry Andric 11181ad6265SDimitry Andric struct Reservation { 11281ad6265SDimitry Andric size_t Size; 11381ad6265SDimitry Andric std::vector<ExecutorAddr> Allocations; 11481ad6265SDimitry Andric }; 11581ad6265SDimitry Andric using ReservationMap = DenseMap<void *, Reservation>; 11681ad6265SDimitry Andric 11781ad6265SDimitry Andric std::mutex Mutex; 11881ad6265SDimitry Andric ReservationMap Reservations; 11981ad6265SDimitry Andric AllocationMap Allocations; 120fcaf7f86SDimitry Andric 121fcaf7f86SDimitry Andric size_t PageSize; 122fcaf7f86SDimitry Andric }; 123fcaf7f86SDimitry Andric 124fcaf7f86SDimitry Andric class SharedMemoryMapper final : public MemoryMapper { 125fcaf7f86SDimitry Andric public: 126fcaf7f86SDimitry Andric struct SymbolAddrs { 127fcaf7f86SDimitry Andric ExecutorAddr Instance; 128fcaf7f86SDimitry Andric ExecutorAddr Reserve; 129fcaf7f86SDimitry Andric ExecutorAddr Initialize; 130fcaf7f86SDimitry Andric ExecutorAddr Deinitialize; 131fcaf7f86SDimitry Andric ExecutorAddr Release; 132fcaf7f86SDimitry Andric }; 133fcaf7f86SDimitry Andric 134fcaf7f86SDimitry Andric SharedMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs, 135fcaf7f86SDimitry Andric size_t PageSize); 136fcaf7f86SDimitry Andric 137fcaf7f86SDimitry Andric static Expected<std::unique_ptr<SharedMemoryMapper>> 138fcaf7f86SDimitry Andric Create(ExecutorProcessControl &EPC, SymbolAddrs SAs); 139fcaf7f86SDimitry Andric getPageSize()140fcaf7f86SDimitry Andric unsigned int getPageSize() override { return PageSize; } 141fcaf7f86SDimitry Andric 142fcaf7f86SDimitry Andric void reserve(size_t NumBytes, OnReservedFunction OnReserved) override; 143fcaf7f86SDimitry Andric 144fcaf7f86SDimitry Andric char *prepare(ExecutorAddr Addr, size_t ContentSize) override; 145fcaf7f86SDimitry Andric 146fcaf7f86SDimitry Andric void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override; 147fcaf7f86SDimitry Andric 148fcaf7f86SDimitry Andric void deinitialize(ArrayRef<ExecutorAddr> Allocations, 149fcaf7f86SDimitry Andric OnDeinitializedFunction OnDeInitialized) override; 150fcaf7f86SDimitry Andric 151fcaf7f86SDimitry Andric void release(ArrayRef<ExecutorAddr> Reservations, 152fcaf7f86SDimitry Andric OnReleasedFunction OnRelease) override; 153fcaf7f86SDimitry Andric 154fcaf7f86SDimitry Andric ~SharedMemoryMapper() override; 155fcaf7f86SDimitry Andric 156fcaf7f86SDimitry Andric private: 157fcaf7f86SDimitry Andric struct Reservation { 158fcaf7f86SDimitry Andric void *LocalAddr; 159fcaf7f86SDimitry Andric size_t Size; 160fcaf7f86SDimitry Andric }; 161fcaf7f86SDimitry Andric 162fcaf7f86SDimitry Andric ExecutorProcessControl &EPC; 163fcaf7f86SDimitry Andric SymbolAddrs SAs; 164fcaf7f86SDimitry Andric 165fcaf7f86SDimitry Andric std::mutex Mutex; 166fcaf7f86SDimitry Andric 167fcaf7f86SDimitry Andric std::map<ExecutorAddr, Reservation> Reservations; 168fcaf7f86SDimitry Andric 169fcaf7f86SDimitry Andric size_t PageSize; 17081ad6265SDimitry Andric }; 17181ad6265SDimitry Andric 17281ad6265SDimitry Andric } // namespace orc 17381ad6265SDimitry Andric } // end namespace llvm 17481ad6265SDimitry Andric 17581ad6265SDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H 176