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