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.