LLVM: lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10#include "llvm/Config/llvm-config.h"
14#include
15
16#if defined(LLVM_ON_UNIX)
17#include <errno.h>
18#include <fcntl.h>
19#include <sys/mman.h>
20#if defined(__MVS__)
22#include <sys/shm.h>
23#endif
24#include <unistd.h>
25#endif
26
27namespace llvm {
28namespace orc {
30
31#if defined(_WIN32)
32static DWORD getWindowsProtectionFlags(MemProt MP) {
34 return PAGE_READONLY;
37
38 return PAGE_READWRITE;
39 }
41 return PAGE_EXECUTE_READ;
43 return PAGE_EXECUTE_READWRITE;
45 return PAGE_EXECUTE;
46
47 return PAGE_NOACCESS;
48}
49#endif
50
51Expected<std::pair<ExecutorAddr, std::string>>
53#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
54
55#if defined(LLVM_ON_UNIX)
56
57 std::string SharedMemoryName;
58 {
59 std::stringstream SharedMemoryNameStream;
61 << (++SharedMemoryCount);
62 SharedMemoryName = SharedMemoryNameStream.str();
63 }
64
65#if defined(__MVS__)
67 reinterpret_cast<const uint8_t *>(SharedMemoryName.c_str()),
68 SharedMemoryName.size());
70 key_t Key = *reinterpret_cast<key_t *>(HashedName.data());
71 int SharedMemoryId =
72 shmget(Key, Size, IPC_CREAT | IPC_EXCL | __IPC_SHAREAS | 0700);
73 if (SharedMemoryId < 0)
75
76 void *Addr = shmat(SharedMemoryId, nullptr, 0);
77 if (Addr == reinterpret_cast<void *>(-1))
79#else
80 int SharedMemoryFile =
81 shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT | O_EXCL, 0700);
82 if (SharedMemoryFile < 0)
84
85
86 if (ftruncate(SharedMemoryFile, Size) < 0)
88
89 void *Addr = mmap(nullptr, Size, PROT_NONE, MAP_SHARED, SharedMemoryFile, 0);
90 if (Addr == MAP_FAILED)
92
93 close(SharedMemoryFile);
94#endif
95
96#elif defined(_WIN32)
97
98 std::string SharedMemoryName;
99 {
100 std::stringstream SharedMemoryNameStream;
102 << (++SharedMemoryCount);
103 SharedMemoryName = SharedMemoryNameStream.str();
104 }
105
106 std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
107 SharedMemoryName.end());
108 HANDLE SharedMemoryFile = CreateFileMappingW(
109 INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, Size >> 32,
110 Size & 0xffffffff, WideSharedMemoryName.c_str());
111 if (!SharedMemoryFile)
113
114 void *Addr = MapViewOfFile(SharedMemoryFile,
115 FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, 0);
116 if (!Addr) {
117 CloseHandle(SharedMemoryFile);
119 }
120
121#endif
122
123 {
124 std::lock_guardstd::mutex Lock(Mutex);
125 Reservations[Addr].Size = Size;
126#if defined(_WIN32)
127 Reservations[Addr].SharedMemoryFile = SharedMemoryFile;
128#endif
129 }
130
132 std::move(SharedMemoryName));
133#else
135 "SharedMemoryMapper is not supported on this platform yet",
137#endif
138}
139
142#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
143
145
146
147 for (auto &Segment : FR.Segments) {
148 if (Segment.Addr < MinAddr)
149 MinAddr = Segment.Addr;
150
151#if defined(LLVM_ON_UNIX)
152
153#if defined(__MVS__)
154
155#else
156 int NativeProt = 0;
158 NativeProt |= PROT_READ;
160 NativeProt |= PROT_WRITE;
162 NativeProt |= PROT_EXEC;
163
164 if (mprotect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt))
166#endif
167
168#elif defined(_WIN32)
169
170 DWORD NativeProt = getWindowsProtectionFlags(Segment.RAG.Prot);
171
172 if (!VirtualProtect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt,
173 &NativeProt))
175
176#endif
177
180 Segment.Size);
181 }
182
183
185 if (!DeinitializeActions) {
186 return DeinitializeActions.takeError();
187 }
188
189 {
190 std::lock_guardstd::mutex Lock(Mutex);
191 Allocations[MinAddr].DeinitializationActions =
192 std::move(*DeinitializeActions);
193 Reservations[Reservation.toPtr<void *>()].Allocations.push_back(MinAddr);
194 }
195
196 return MinAddr;
197
198#else
200 "SharedMemoryMapper is not supported on this platform yet",
202#endif
203}
204
206 const std::vector &Bases) {
208
209 {
210 std::lock_guardstd::mutex Lock(Mutex);
211
214 Allocations[Base].DeinitializationActions)) {
215 AllErr = joinErrors(std::move(AllErr), std::move(Err));
216 }
217
218
219 for (auto &Reservation : Reservations) {
220 auto AllocationIt = llvm::find(Reservation.second.Allocations, Base);
221 if (AllocationIt != Reservation.second.Allocations.end()) {
222 Reservation.second.Allocations.erase(AllocationIt);
223 break;
224 }
225 }
226
227 Allocations.erase(Base);
228 }
229 }
230
231 return AllErr;
232}
233
235 const std::vector &Bases) {
236#if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
238
239 for (auto Base : Bases) {
240 std::vector AllocAddrs;
242
243#if defined(_WIN32)
244 HANDLE SharedMemoryFile;
245#endif
246
247 {
248 std::lock_guardstd::mutex Lock(Mutex);
249 auto &R = Reservations[Base.toPtr<void *>()];
250 Size = R.Size;
251
252#if defined(_WIN32)
253 SharedMemoryFile = R.SharedMemoryFile;
254#endif
255
256 AllocAddrs.swap(R.Allocations);
257 }
258
259
261 Err = joinErrors(std::move(Err), std::move(E));
262
263#if defined(LLVM_ON_UNIX)
264
265#if defined(__MVS__)
267
268 if (shmdt(Base.toPtr<void *>()) < 0)
270#else
271 if (munmap(Base.toPtr<void *>(), Size) != 0)
273#endif
274
275#elif defined(_WIN32)
277
278 if (!UnmapViewOfFile(Base.toPtr<void *>()))
281
282 CloseHandle(SharedMemoryFile);
283
284#endif
285
286 std::lock_guardstd::mutex Lock(Mutex);
287 Reservations.erase(Base.toPtr<void *>());
288 }
289
290 return Err;
291#else
293 "SharedMemoryMapper is not supported on this platform yet",
295#endif
296}
297
299 if (Reservations.empty())
301
302 std::vector ReservationAddrs;
303 ReservationAddrs.reserve(Reservations.size());
304 for (const auto &R : Reservations)
306
307 return release(std::move(ReservationAddrs));
308}
309
323
325ExecutorSharedMemoryMapperService::reserveWrapper(const char *ArgData,
326 size_t ArgSize) {
329 handle(ArgData, ArgSize,
332 .release();
333}
334
336ExecutorSharedMemoryMapperService::initializeWrapper(const char *ArgData,
337 size_t ArgSize) {
340 handle(ArgData, ArgSize,
343 .release();
344}
345
347ExecutorSharedMemoryMapperService::deinitializeWrapper(const char *ArgData,
348 size_t ArgSize) {
349 return shared::WrapperFunction<
351 handle(ArgData, ArgSize,
354 .release();
355}
356
358ExecutorSharedMemoryMapperService::releaseWrapper(const char *ArgData,
359 size_t ArgSize) {
360 return shared::WrapperFunction<
362 handle(ArgData, ArgSize,
365 .release();
366}
367
368}
369}
370}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides a library for accessing information about this process and other processes on the operating ...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static BLAKE3Result< NumBytes > hash(ArrayRef< uint8_t > Data)
Returns a BLAKE3 hash for the given data.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Represents an address in the executor process.
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
static LLVM_ABI void InvalidateInstructionCache(const void *Addr, size_t Len)
InvalidateInstructionCache - Before the JIT can run a block of code that has been emitted it must inv...
static LLVM_ABI Pid getProcessId()
Get the process's identifier.
LLVM_ABI const char * ExecutorSharedMemoryMapperServiceInstanceName
shared::SPSExpected< shared::SPSTuple< shared::SPSExecutorAddr, shared::SPSString > >( shared::SPSExecutorAddr, uint64_t) SPSExecutorSharedMemoryMapperServiceReserveSignature
LLVM_ABI const char * ExecutorSharedMemoryMapperServiceReserveWrapperName
LLVM_ABI const char * ExecutorSharedMemoryMapperServiceDeinitializeWrapperName
LLVM_ABI const char * ExecutorSharedMemoryMapperServiceReleaseWrapperName
shared::SPSExpected< shared::SPSExecutorAddr >( shared::SPSExecutorAddr, shared::SPSExecutorAddr, shared::SPSSharedMemoryFinalizeRequest) SPSExecutorSharedMemoryMapperServiceInitializeSignature
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSExecutorSharedMemoryMapperServiceDeinitializeSignature
LLVM_ABI const char * ExecutorSharedMemoryMapperServiceInitializeWrapperName
shared::SPSError( shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSExecutorSharedMemoryMapperServiceReleaseSignature
MemProt
Describes Read/Write/Exec permissions for memory.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto reverse(ContainerTy &&C)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ABI std::error_code mapWindowsError(unsigned EV)
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.