1 | //===- MemoryMapper.h - Cross-process memory mapper -------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Cross-process (and in-process) memory mapping and transfer |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H |
14 | #define LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H |
15 | |
16 | #include "llvm/ExecutionEngine/Orc/Core.h" |
17 | #include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h" |
18 | #include "llvm/Support/Process.h" |
19 | |
20 | #include <mutex> |
21 | |
22 | namespace llvm { |
23 | namespace orc { |
24 | |
25 | /// Manages mapping, content transfer and protections for JIT memory |
26 | class MemoryMapper { |
27 | public: |
28 | /// Represents a single allocation containing multiple segments and |
29 | /// initialization and deinitialization actions |
30 | struct AllocInfo { |
31 | struct SegInfo { |
32 | ExecutorAddrDiff Offset; |
33 | const char *WorkingMem; |
34 | size_t ContentSize; |
35 | size_t ZeroFillSize; |
36 | AllocGroup AG; |
37 | }; |
38 | |
39 | ExecutorAddr MappingBase; |
40 | std::vector<SegInfo> Segments; |
41 | shared::AllocActions Actions; |
42 | }; |
43 | |
44 | using OnReservedFunction = unique_function<void(Expected<ExecutorAddrRange>)>; |
45 | |
46 | // Page size of the target process |
47 | virtual unsigned int getPageSize() = 0; |
48 | |
49 | /// Reserves address space in executor process |
50 | virtual void reserve(size_t NumBytes, OnReservedFunction OnReserved) = 0; |
51 | |
52 | /// Provides working memory |
53 | virtual char *prepare(ExecutorAddr Addr, size_t ContentSize) = 0; |
54 | |
55 | using OnInitializedFunction = unique_function<void(Expected<ExecutorAddr>)>; |
56 | |
57 | /// Ensures executor memory is synchronized with working copy memory, sends |
58 | /// functions to be called after initilization and before deinitialization and |
59 | /// applies memory protections |
60 | /// Returns a unique address identifying the allocation. This address should |
61 | /// be passed to deinitialize to run deallocation actions (and reset |
62 | /// permissions where possible). |
63 | virtual void initialize(AllocInfo &AI, |
64 | OnInitializedFunction OnInitialized) = 0; |
65 | |
66 | using OnDeinitializedFunction = unique_function<void(Error)>; |
67 | |
68 | /// Runs previously specified deinitialization actions |
69 | /// Executor addresses returned by initialize should be passed |
70 | virtual void deinitialize(ArrayRef<ExecutorAddr> Allocations, |
71 | OnDeinitializedFunction OnDeInitialized) = 0; |
72 | |
73 | using OnReleasedFunction = unique_function<void(Error)>; |
74 | |
75 | /// Release address space acquired through reserve() |
76 | virtual void release(ArrayRef<ExecutorAddr> Reservations, |
77 | OnReleasedFunction OnRelease) = 0; |
78 | |
79 | virtual ~MemoryMapper(); |
80 | }; |
81 | |
82 | class InProcessMemoryMapper : public MemoryMapper { |
83 | public: |
84 | InProcessMemoryMapper(size_t PageSize); |
85 | |
86 | static Expected<std::unique_ptr<InProcessMemoryMapper>> Create(); |
87 | |
88 | unsigned int getPageSize() override { return PageSize; } |
89 | |
90 | void reserve(size_t NumBytes, OnReservedFunction OnReserved) override; |
91 | |
92 | void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override; |
93 | |
94 | char *prepare(ExecutorAddr Addr, size_t ContentSize) override; |
95 | |
96 | void deinitialize(ArrayRef<ExecutorAddr> Allocations, |
97 | OnDeinitializedFunction OnDeInitialized) override; |
98 | |
99 | void release(ArrayRef<ExecutorAddr> Reservations, |
100 | OnReleasedFunction OnRelease) override; |
101 | |
102 | ~InProcessMemoryMapper() override; |
103 | |
104 | private: |
105 | struct Allocation { |
106 | size_t Size; |
107 | std::vector<shared::WrapperFunctionCall> DeinitializationActions; |
108 | }; |
109 | using AllocationMap = DenseMap<ExecutorAddr, Allocation>; |
110 | |
111 | struct Reservation { |
112 | size_t Size; |
113 | std::vector<ExecutorAddr> Allocations; |
114 | }; |
115 | using ReservationMap = DenseMap<void *, Reservation>; |
116 | |
117 | std::mutex Mutex; |
118 | ReservationMap Reservations; |
119 | AllocationMap Allocations; |
120 | |
121 | size_t PageSize; |
122 | }; |
123 | |
124 | class SharedMemoryMapper final : public MemoryMapper { |
125 | public: |
126 | struct SymbolAddrs { |
127 | ExecutorAddr Instance; |
128 | ExecutorAddr Reserve; |
129 | ExecutorAddr Initialize; |
130 | ExecutorAddr Deinitialize; |
131 | ExecutorAddr Release; |
132 | }; |
133 | |
134 | SharedMemoryMapper(ExecutorProcessControl &EPC, SymbolAddrs SAs, |
135 | size_t PageSize); |
136 | |
137 | static Expected<std::unique_ptr<SharedMemoryMapper>> |
138 | Create(ExecutorProcessControl &EPC, SymbolAddrs SAs); |
139 | |
140 | unsigned int getPageSize() override { return PageSize; } |
141 | |
142 | void reserve(size_t NumBytes, OnReservedFunction OnReserved) override; |
143 | |
144 | char *prepare(ExecutorAddr Addr, size_t ContentSize) override; |
145 | |
146 | void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override; |
147 | |
148 | void deinitialize(ArrayRef<ExecutorAddr> Allocations, |
149 | OnDeinitializedFunction OnDeInitialized) override; |
150 | |
151 | void release(ArrayRef<ExecutorAddr> Reservations, |
152 | OnReleasedFunction OnRelease) override; |
153 | |
154 | ~SharedMemoryMapper() override; |
155 | |
156 | private: |
157 | struct Reservation { |
158 | void *LocalAddr; |
159 | size_t Size; |
160 | }; |
161 | |
162 | ExecutorProcessControl &EPC; |
163 | SymbolAddrs SAs; |
164 | |
165 | std::mutex Mutex; |
166 | |
167 | std::map<ExecutorAddr, Reservation> Reservations; |
168 | |
169 | size_t PageSize; |
170 | }; |
171 | |
172 | } // namespace orc |
173 | } // end namespace llvm |
174 | |
175 | #endif // LLVM_EXECUTIONENGINE_ORC_MEMORYMAPPER_H |
176 | |