181ad6265SDimitry Andric //===- MemoryMapper.cpp - 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 #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
1081ad6265SDimitry Andric
11fcaf7f86SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12fcaf7f86SDimitry Andric #include "llvm/Support/WindowsError.h"
13fcaf7f86SDimitry Andric
14bdd1243dSDimitry Andric #include <algorithm>
15bdd1243dSDimitry Andric
1661cfbce3SDimitry Andric #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
17fcaf7f86SDimitry Andric #include <fcntl.h>
18fcaf7f86SDimitry Andric #include <sys/mman.h>
19*0fca6ea1SDimitry Andric #if defined(__MVS__)
20*0fca6ea1SDimitry Andric #include "llvm/Support/BLAKE3.h"
21*0fca6ea1SDimitry Andric #include <sys/shm.h>
22*0fca6ea1SDimitry Andric #endif
23fcaf7f86SDimitry Andric #include <unistd.h>
24fcaf7f86SDimitry Andric #elif defined(_WIN32)
25fcaf7f86SDimitry Andric #include <windows.h>
26fcaf7f86SDimitry Andric #endif
27fcaf7f86SDimitry Andric
2881ad6265SDimitry Andric namespace llvm {
2981ad6265SDimitry Andric namespace orc {
3081ad6265SDimitry Andric
~MemoryMapper()3181ad6265SDimitry Andric MemoryMapper::~MemoryMapper() {}
3281ad6265SDimitry Andric
InProcessMemoryMapper(size_t PageSize)33fcaf7f86SDimitry Andric InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize)
34fcaf7f86SDimitry Andric : PageSize(PageSize) {}
35fcaf7f86SDimitry Andric
36fcaf7f86SDimitry Andric Expected<std::unique_ptr<InProcessMemoryMapper>>
Create()37fcaf7f86SDimitry Andric InProcessMemoryMapper::Create() {
38fcaf7f86SDimitry Andric auto PageSize = sys::Process::getPageSize();
39fcaf7f86SDimitry Andric if (!PageSize)
40fcaf7f86SDimitry Andric return PageSize.takeError();
41fcaf7f86SDimitry Andric return std::make_unique<InProcessMemoryMapper>(*PageSize);
42fcaf7f86SDimitry Andric }
43fcaf7f86SDimitry Andric
reserve(size_t NumBytes,OnReservedFunction OnReserved)4481ad6265SDimitry Andric void InProcessMemoryMapper::reserve(size_t NumBytes,
4581ad6265SDimitry Andric OnReservedFunction OnReserved) {
4681ad6265SDimitry Andric std::error_code EC;
4781ad6265SDimitry Andric auto MB = sys::Memory::allocateMappedMemory(
4881ad6265SDimitry Andric NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
4981ad6265SDimitry Andric
5081ad6265SDimitry Andric if (EC)
5181ad6265SDimitry Andric return OnReserved(errorCodeToError(EC));
5281ad6265SDimitry Andric
5381ad6265SDimitry Andric {
5481ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
5581ad6265SDimitry Andric Reservations[MB.base()].Size = MB.allocatedSize();
5681ad6265SDimitry Andric }
5781ad6265SDimitry Andric
5881ad6265SDimitry Andric OnReserved(
5981ad6265SDimitry Andric ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
6081ad6265SDimitry Andric }
6181ad6265SDimitry Andric
prepare(ExecutorAddr Addr,size_t ContentSize)6281ad6265SDimitry Andric char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
6381ad6265SDimitry Andric return Addr.toPtr<char *>();
6481ad6265SDimitry Andric }
6581ad6265SDimitry Andric
initialize(MemoryMapper::AllocInfo & AI,OnInitializedFunction OnInitialized)6681ad6265SDimitry Andric void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
6781ad6265SDimitry Andric OnInitializedFunction OnInitialized) {
6881ad6265SDimitry Andric ExecutorAddr MinAddr(~0ULL);
69bdd1243dSDimitry Andric ExecutorAddr MaxAddr(0);
7081ad6265SDimitry Andric
71bdd1243dSDimitry Andric // FIXME: Release finalize lifetime segments.
7281ad6265SDimitry Andric for (auto &Segment : AI.Segments) {
7381ad6265SDimitry Andric auto Base = AI.MappingBase + Segment.Offset;
7481ad6265SDimitry Andric auto Size = Segment.ContentSize + Segment.ZeroFillSize;
7581ad6265SDimitry Andric
7681ad6265SDimitry Andric if (Base < MinAddr)
7781ad6265SDimitry Andric MinAddr = Base;
7881ad6265SDimitry Andric
79bdd1243dSDimitry Andric if (Base + Size > MaxAddr)
80bdd1243dSDimitry Andric MaxAddr = Base + Size;
81bdd1243dSDimitry Andric
8281ad6265SDimitry Andric std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
8381ad6265SDimitry Andric Segment.ZeroFillSize);
8481ad6265SDimitry Andric
85bdd1243dSDimitry Andric if (auto EC = sys::Memory::protectMappedMemory(
86bdd1243dSDimitry Andric {Base.toPtr<void *>(), Size},
87bdd1243dSDimitry Andric toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) {
8881ad6265SDimitry Andric return OnInitialized(errorCodeToError(EC));
8981ad6265SDimitry Andric }
90bdd1243dSDimitry Andric if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
9181ad6265SDimitry Andric sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
9281ad6265SDimitry Andric }
9381ad6265SDimitry Andric
9481ad6265SDimitry Andric auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
9581ad6265SDimitry Andric if (!DeinitializeActions)
9681ad6265SDimitry Andric return OnInitialized(DeinitializeActions.takeError());
9781ad6265SDimitry Andric
9881ad6265SDimitry Andric {
9981ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
100bdd1243dSDimitry Andric
101bdd1243dSDimitry Andric // This is the maximum range whose permission have been possibly modified
102bdd1243dSDimitry Andric Allocations[MinAddr].Size = MaxAddr - MinAddr;
10381ad6265SDimitry Andric Allocations[MinAddr].DeinitializationActions =
10481ad6265SDimitry Andric std::move(*DeinitializeActions);
10581ad6265SDimitry Andric Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
10681ad6265SDimitry Andric }
10781ad6265SDimitry Andric
10881ad6265SDimitry Andric OnInitialized(MinAddr);
10981ad6265SDimitry Andric }
11081ad6265SDimitry Andric
deinitialize(ArrayRef<ExecutorAddr> Bases,MemoryMapper::OnDeinitializedFunction OnDeinitialized)11181ad6265SDimitry Andric void InProcessMemoryMapper::deinitialize(
11281ad6265SDimitry Andric ArrayRef<ExecutorAddr> Bases,
11381ad6265SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
11481ad6265SDimitry Andric Error AllErr = Error::success();
11581ad6265SDimitry Andric
11681ad6265SDimitry Andric {
11781ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
11881ad6265SDimitry Andric
119bdd1243dSDimitry Andric for (auto Base : llvm::reverse(Bases)) {
12081ad6265SDimitry Andric
12181ad6265SDimitry Andric if (Error Err = shared::runDeallocActions(
12281ad6265SDimitry Andric Allocations[Base].DeinitializationActions)) {
12381ad6265SDimitry Andric AllErr = joinErrors(std::move(AllErr), std::move(Err));
12481ad6265SDimitry Andric }
12581ad6265SDimitry Andric
126bdd1243dSDimitry Andric // Reset protections to read/write so the area can be reused
127bdd1243dSDimitry Andric if (auto EC = sys::Memory::protectMappedMemory(
128bdd1243dSDimitry Andric {Base.toPtr<void *>(), Allocations[Base].Size},
129bdd1243dSDimitry Andric sys::Memory::ProtectionFlags::MF_READ |
130bdd1243dSDimitry Andric sys::Memory::ProtectionFlags::MF_WRITE)) {
131bdd1243dSDimitry Andric AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC));
132bdd1243dSDimitry Andric }
133bdd1243dSDimitry Andric
13481ad6265SDimitry Andric Allocations.erase(Base);
13581ad6265SDimitry Andric }
13681ad6265SDimitry Andric }
13781ad6265SDimitry Andric
13881ad6265SDimitry Andric OnDeinitialized(std::move(AllErr));
13981ad6265SDimitry Andric }
14081ad6265SDimitry Andric
release(ArrayRef<ExecutorAddr> Bases,OnReleasedFunction OnReleased)14181ad6265SDimitry Andric void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
14281ad6265SDimitry Andric OnReleasedFunction OnReleased) {
14381ad6265SDimitry Andric Error Err = Error::success();
14481ad6265SDimitry Andric
14581ad6265SDimitry Andric for (auto Base : Bases) {
14681ad6265SDimitry Andric std::vector<ExecutorAddr> AllocAddrs;
14781ad6265SDimitry Andric size_t Size;
14881ad6265SDimitry Andric {
14981ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
15081ad6265SDimitry Andric auto &R = Reservations[Base.toPtr<void *>()];
15181ad6265SDimitry Andric Size = R.Size;
15281ad6265SDimitry Andric AllocAddrs.swap(R.Allocations);
15381ad6265SDimitry Andric }
15481ad6265SDimitry Andric
15581ad6265SDimitry Andric // deinitialize sub allocations
15681ad6265SDimitry Andric std::promise<MSVCPError> P;
15781ad6265SDimitry Andric auto F = P.get_future();
15881ad6265SDimitry Andric deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
15981ad6265SDimitry Andric if (Error E = F.get()) {
16081ad6265SDimitry Andric Err = joinErrors(std::move(Err), std::move(E));
16181ad6265SDimitry Andric }
16281ad6265SDimitry Andric
16381ad6265SDimitry Andric // free the memory
16481ad6265SDimitry Andric auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
16581ad6265SDimitry Andric
16681ad6265SDimitry Andric auto EC = sys::Memory::releaseMappedMemory(MB);
16781ad6265SDimitry Andric if (EC) {
16881ad6265SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(EC));
16981ad6265SDimitry Andric }
17081ad6265SDimitry Andric
17181ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
17281ad6265SDimitry Andric Reservations.erase(Base.toPtr<void *>());
17381ad6265SDimitry Andric }
17481ad6265SDimitry Andric
17581ad6265SDimitry Andric OnReleased(std::move(Err));
17681ad6265SDimitry Andric }
17781ad6265SDimitry Andric
~InProcessMemoryMapper()17881ad6265SDimitry Andric InProcessMemoryMapper::~InProcessMemoryMapper() {
17981ad6265SDimitry Andric std::vector<ExecutorAddr> ReservationAddrs;
18081ad6265SDimitry Andric {
18181ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
18281ad6265SDimitry Andric
18381ad6265SDimitry Andric ReservationAddrs.reserve(Reservations.size());
18481ad6265SDimitry Andric for (const auto &R : Reservations) {
18581ad6265SDimitry Andric ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
18681ad6265SDimitry Andric }
18781ad6265SDimitry Andric }
18881ad6265SDimitry Andric
18981ad6265SDimitry Andric std::promise<MSVCPError> P;
19081ad6265SDimitry Andric auto F = P.get_future();
19181ad6265SDimitry Andric release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
19281ad6265SDimitry Andric cantFail(F.get());
19381ad6265SDimitry Andric }
19481ad6265SDimitry Andric
195fcaf7f86SDimitry Andric // SharedMemoryMapper
196fcaf7f86SDimitry Andric
SharedMemoryMapper(ExecutorProcessControl & EPC,SymbolAddrs SAs,size_t PageSize)197fcaf7f86SDimitry Andric SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC,
198fcaf7f86SDimitry Andric SymbolAddrs SAs, size_t PageSize)
19961cfbce3SDimitry Andric : EPC(EPC), SAs(SAs), PageSize(PageSize) {
20061cfbce3SDimitry Andric #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32)
20161cfbce3SDimitry Andric llvm_unreachable("SharedMemoryMapper is not supported on this platform yet");
20261cfbce3SDimitry Andric #endif
20361cfbce3SDimitry Andric }
204fcaf7f86SDimitry Andric
205fcaf7f86SDimitry Andric Expected<std::unique_ptr<SharedMemoryMapper>>
Create(ExecutorProcessControl & EPC,SymbolAddrs SAs)206fcaf7f86SDimitry Andric SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
20761cfbce3SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
208fcaf7f86SDimitry Andric auto PageSize = sys::Process::getPageSize();
209fcaf7f86SDimitry Andric if (!PageSize)
210fcaf7f86SDimitry Andric return PageSize.takeError();
211fcaf7f86SDimitry Andric
212fcaf7f86SDimitry Andric return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
21361cfbce3SDimitry Andric #else
21461cfbce3SDimitry Andric return make_error<StringError>(
21561cfbce3SDimitry Andric "SharedMemoryMapper is not supported on this platform yet",
21661cfbce3SDimitry Andric inconvertibleErrorCode());
21761cfbce3SDimitry Andric #endif
218fcaf7f86SDimitry Andric }
219fcaf7f86SDimitry Andric
reserve(size_t NumBytes,OnReservedFunction OnReserved)220fcaf7f86SDimitry Andric void SharedMemoryMapper::reserve(size_t NumBytes,
221fcaf7f86SDimitry Andric OnReservedFunction OnReserved) {
22261cfbce3SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
223fcaf7f86SDimitry Andric
224fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync<
225fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>(
226fcaf7f86SDimitry Andric SAs.Reserve,
227fcaf7f86SDimitry Andric [this, NumBytes, OnReserved = std::move(OnReserved)](
228fcaf7f86SDimitry Andric Error SerializationErr,
229fcaf7f86SDimitry Andric Expected<std::pair<ExecutorAddr, std::string>> Result) mutable {
230fcaf7f86SDimitry Andric if (SerializationErr) {
231fcaf7f86SDimitry Andric cantFail(Result.takeError());
232fcaf7f86SDimitry Andric return OnReserved(std::move(SerializationErr));
233fcaf7f86SDimitry Andric }
234fcaf7f86SDimitry Andric
235fcaf7f86SDimitry Andric if (!Result)
236fcaf7f86SDimitry Andric return OnReserved(Result.takeError());
237fcaf7f86SDimitry Andric
238fcaf7f86SDimitry Andric ExecutorAddr RemoteAddr;
239fcaf7f86SDimitry Andric std::string SharedMemoryName;
240fcaf7f86SDimitry Andric std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result);
241fcaf7f86SDimitry Andric
242fcaf7f86SDimitry Andric void *LocalAddr = nullptr;
243fcaf7f86SDimitry Andric
244fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX)
245fcaf7f86SDimitry Andric
246*0fca6ea1SDimitry Andric #if defined(__MVS__)
247*0fca6ea1SDimitry Andric ArrayRef<uint8_t> Data(
248*0fca6ea1SDimitry Andric reinterpret_cast<const uint8_t *>(SharedMemoryName.c_str()),
249*0fca6ea1SDimitry Andric SharedMemoryName.size());
250*0fca6ea1SDimitry Andric auto HashedName = BLAKE3::hash<sizeof(key_t)>(Data);
251*0fca6ea1SDimitry Andric key_t Key = *reinterpret_cast<key_t *>(HashedName.data());
252*0fca6ea1SDimitry Andric int SharedMemoryId =
253*0fca6ea1SDimitry Andric shmget(Key, NumBytes, IPC_CREAT | __IPC_SHAREAS | 0700);
254*0fca6ea1SDimitry Andric if (SharedMemoryId < 0) {
255fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(
256fcaf7f86SDimitry Andric std::error_code(errno, std::generic_category())));
257fcaf7f86SDimitry Andric }
258*0fca6ea1SDimitry Andric LocalAddr = shmat(SharedMemoryId, nullptr, 0);
259*0fca6ea1SDimitry Andric if (LocalAddr == reinterpret_cast<void *>(-1)) {
260*0fca6ea1SDimitry Andric return OnReserved(errorCodeToError(
261*0fca6ea1SDimitry Andric std::error_code(errno, std::generic_category())));
262*0fca6ea1SDimitry Andric }
263*0fca6ea1SDimitry Andric #else
264*0fca6ea1SDimitry Andric int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
265*0fca6ea1SDimitry Andric if (SharedMemoryFile < 0) {
266*0fca6ea1SDimitry Andric return OnReserved(errorCodeToError(errnoAsErrorCode()));
267*0fca6ea1SDimitry Andric }
268fcaf7f86SDimitry Andric
269fcaf7f86SDimitry Andric // this prevents other processes from accessing it by name
270fcaf7f86SDimitry Andric shm_unlink(SharedMemoryName.c_str());
271fcaf7f86SDimitry Andric
272fcaf7f86SDimitry Andric LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
273fcaf7f86SDimitry Andric SharedMemoryFile, 0);
274fcaf7f86SDimitry Andric if (LocalAddr == MAP_FAILED) {
275*0fca6ea1SDimitry Andric return OnReserved(errorCodeToError(errnoAsErrorCode()));
276fcaf7f86SDimitry Andric }
277fcaf7f86SDimitry Andric
278fcaf7f86SDimitry Andric close(SharedMemoryFile);
279*0fca6ea1SDimitry Andric #endif
280fcaf7f86SDimitry Andric
281fcaf7f86SDimitry Andric #elif defined(_WIN32)
282fcaf7f86SDimitry Andric
283fcaf7f86SDimitry Andric std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
284fcaf7f86SDimitry Andric SharedMemoryName.end());
285fcaf7f86SDimitry Andric HANDLE SharedMemoryFile = OpenFileMappingW(
286fcaf7f86SDimitry Andric FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
287fcaf7f86SDimitry Andric if (!SharedMemoryFile)
288fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
289fcaf7f86SDimitry Andric
290fcaf7f86SDimitry Andric LocalAddr =
291fcaf7f86SDimitry Andric MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
292fcaf7f86SDimitry Andric if (!LocalAddr) {
293fcaf7f86SDimitry Andric CloseHandle(SharedMemoryFile);
294fcaf7f86SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
295fcaf7f86SDimitry Andric }
296fcaf7f86SDimitry Andric
297fcaf7f86SDimitry Andric CloseHandle(SharedMemoryFile);
298fcaf7f86SDimitry Andric
299fcaf7f86SDimitry Andric #endif
300fcaf7f86SDimitry Andric {
301fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
302fcaf7f86SDimitry Andric Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
303fcaf7f86SDimitry Andric }
304fcaf7f86SDimitry Andric
305fcaf7f86SDimitry Andric OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes));
306fcaf7f86SDimitry Andric },
307fcaf7f86SDimitry Andric SAs.Instance, static_cast<uint64_t>(NumBytes));
308fcaf7f86SDimitry Andric
309fcaf7f86SDimitry Andric #else
310fcaf7f86SDimitry Andric OnReserved(make_error<StringError>(
311fcaf7f86SDimitry Andric "SharedMemoryMapper is not supported on this platform yet",
312fcaf7f86SDimitry Andric inconvertibleErrorCode()));
313fcaf7f86SDimitry Andric #endif
314fcaf7f86SDimitry Andric }
315fcaf7f86SDimitry Andric
prepare(ExecutorAddr Addr,size_t ContentSize)316fcaf7f86SDimitry Andric char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
317fcaf7f86SDimitry Andric auto R = Reservations.upper_bound(Addr);
318bdd1243dSDimitry Andric assert(R != Reservations.begin() && "Attempt to prepare unreserved range");
319fcaf7f86SDimitry Andric R--;
320fcaf7f86SDimitry Andric
321fcaf7f86SDimitry Andric ExecutorAddrDiff Offset = Addr - R->first;
322fcaf7f86SDimitry Andric
323fcaf7f86SDimitry Andric return static_cast<char *>(R->second.LocalAddr) + Offset;
324fcaf7f86SDimitry Andric }
325fcaf7f86SDimitry Andric
initialize(MemoryMapper::AllocInfo & AI,OnInitializedFunction OnInitialized)326fcaf7f86SDimitry Andric void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
327fcaf7f86SDimitry Andric OnInitializedFunction OnInitialized) {
328bdd1243dSDimitry Andric auto Reservation = Reservations.upper_bound(AI.MappingBase);
329bdd1243dSDimitry Andric assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range");
330bdd1243dSDimitry Andric Reservation--;
331bdd1243dSDimitry Andric
332bdd1243dSDimitry Andric auto AllocationOffset = AI.MappingBase - Reservation->first;
333fcaf7f86SDimitry Andric
334fcaf7f86SDimitry Andric tpctypes::SharedMemoryFinalizeRequest FR;
335fcaf7f86SDimitry Andric
336fcaf7f86SDimitry Andric AI.Actions.swap(FR.Actions);
337fcaf7f86SDimitry Andric
338fcaf7f86SDimitry Andric FR.Segments.reserve(AI.Segments.size());
339fcaf7f86SDimitry Andric
340fcaf7f86SDimitry Andric for (auto Segment : AI.Segments) {
341bdd1243dSDimitry Andric char *Base = static_cast<char *>(Reservation->second.LocalAddr) +
342bdd1243dSDimitry Andric AllocationOffset + Segment.Offset;
343fcaf7f86SDimitry Andric std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
344fcaf7f86SDimitry Andric
345fcaf7f86SDimitry Andric tpctypes::SharedMemorySegFinalizeRequest SegReq;
3465f757f3fSDimitry Andric SegReq.RAG = {Segment.AG.getMemProt(),
3475f757f3fSDimitry Andric Segment.AG.getMemLifetime() == MemLifetime::Finalize};
348fcaf7f86SDimitry Andric SegReq.Addr = AI.MappingBase + Segment.Offset;
349fcaf7f86SDimitry Andric SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
350fcaf7f86SDimitry Andric
351fcaf7f86SDimitry Andric FR.Segments.push_back(SegReq);
352fcaf7f86SDimitry Andric }
353fcaf7f86SDimitry Andric
354fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync<
355fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>(
356fcaf7f86SDimitry Andric SAs.Initialize,
357fcaf7f86SDimitry Andric [OnInitialized = std::move(OnInitialized)](
358fcaf7f86SDimitry Andric Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
359fcaf7f86SDimitry Andric if (SerializationErr) {
360fcaf7f86SDimitry Andric cantFail(Result.takeError());
361fcaf7f86SDimitry Andric return OnInitialized(std::move(SerializationErr));
362fcaf7f86SDimitry Andric }
363fcaf7f86SDimitry Andric
364fcaf7f86SDimitry Andric OnInitialized(std::move(Result));
365fcaf7f86SDimitry Andric },
366bdd1243dSDimitry Andric SAs.Instance, Reservation->first, std::move(FR));
367fcaf7f86SDimitry Andric }
368fcaf7f86SDimitry Andric
deinitialize(ArrayRef<ExecutorAddr> Allocations,MemoryMapper::OnDeinitializedFunction OnDeinitialized)369fcaf7f86SDimitry Andric void SharedMemoryMapper::deinitialize(
370fcaf7f86SDimitry Andric ArrayRef<ExecutorAddr> Allocations,
371fcaf7f86SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
372fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync<
373fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>(
374fcaf7f86SDimitry Andric SAs.Deinitialize,
375fcaf7f86SDimitry Andric [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
376fcaf7f86SDimitry Andric Error Result) mutable {
377fcaf7f86SDimitry Andric if (SerializationErr) {
378fcaf7f86SDimitry Andric cantFail(std::move(Result));
379fcaf7f86SDimitry Andric return OnDeinitialized(std::move(SerializationErr));
380fcaf7f86SDimitry Andric }
381fcaf7f86SDimitry Andric
382fcaf7f86SDimitry Andric OnDeinitialized(std::move(Result));
383fcaf7f86SDimitry Andric },
384fcaf7f86SDimitry Andric SAs.Instance, Allocations);
385fcaf7f86SDimitry Andric }
386fcaf7f86SDimitry Andric
release(ArrayRef<ExecutorAddr> Bases,OnReleasedFunction OnReleased)387fcaf7f86SDimitry Andric void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
388fcaf7f86SDimitry Andric OnReleasedFunction OnReleased) {
38961cfbce3SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
390fcaf7f86SDimitry Andric Error Err = Error::success();
391fcaf7f86SDimitry Andric
392fcaf7f86SDimitry Andric {
393fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
394fcaf7f86SDimitry Andric
395fcaf7f86SDimitry Andric for (auto Base : Bases) {
396fcaf7f86SDimitry Andric
397fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX)
398fcaf7f86SDimitry Andric
399*0fca6ea1SDimitry Andric #if defined(__MVS__)
400*0fca6ea1SDimitry Andric if (shmdt(Reservations[Base].LocalAddr) < 0)
401*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode()));
402*0fca6ea1SDimitry Andric #else
403fcaf7f86SDimitry Andric if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0)
404*0fca6ea1SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode()));
405*0fca6ea1SDimitry Andric #endif
406fcaf7f86SDimitry Andric
407fcaf7f86SDimitry Andric #elif defined(_WIN32)
408fcaf7f86SDimitry Andric
409fcaf7f86SDimitry Andric if (!UnmapViewOfFile(Reservations[Base].LocalAddr))
41061cfbce3SDimitry Andric Err = joinErrors(std::move(Err),
411fcaf7f86SDimitry Andric errorCodeToError(mapWindowsError(GetLastError())));
412fcaf7f86SDimitry Andric
413fcaf7f86SDimitry Andric #endif
414fcaf7f86SDimitry Andric
415fcaf7f86SDimitry Andric Reservations.erase(Base);
416fcaf7f86SDimitry Andric }
417fcaf7f86SDimitry Andric }
418fcaf7f86SDimitry Andric
419fcaf7f86SDimitry Andric EPC.callSPSWrapperAsync<
420fcaf7f86SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>(
421fcaf7f86SDimitry Andric SAs.Release,
422fcaf7f86SDimitry Andric [OnReleased = std::move(OnReleased),
423fcaf7f86SDimitry Andric Err = std::move(Err)](Error SerializationErr, Error Result) mutable {
424fcaf7f86SDimitry Andric if (SerializationErr) {
425fcaf7f86SDimitry Andric cantFail(std::move(Result));
426fcaf7f86SDimitry Andric return OnReleased(
427fcaf7f86SDimitry Andric joinErrors(std::move(Err), std::move(SerializationErr)));
428fcaf7f86SDimitry Andric }
429fcaf7f86SDimitry Andric
430fcaf7f86SDimitry Andric return OnReleased(joinErrors(std::move(Err), std::move(Result)));
431fcaf7f86SDimitry Andric },
432fcaf7f86SDimitry Andric SAs.Instance, Bases);
433fcaf7f86SDimitry Andric #else
434fcaf7f86SDimitry Andric OnReleased(make_error<StringError>(
435fcaf7f86SDimitry Andric "SharedMemoryMapper is not supported on this platform yet",
436fcaf7f86SDimitry Andric inconvertibleErrorCode()));
437fcaf7f86SDimitry Andric #endif
438fcaf7f86SDimitry Andric }
439fcaf7f86SDimitry Andric
~SharedMemoryMapper()440fcaf7f86SDimitry Andric SharedMemoryMapper::~SharedMemoryMapper() {
441fcaf7f86SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
442fcaf7f86SDimitry Andric for (const auto &R : Reservations) {
443fcaf7f86SDimitry Andric
444bdd1243dSDimitry Andric #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
445bdd1243dSDimitry Andric
446*0fca6ea1SDimitry Andric #if defined(__MVS__)
447*0fca6ea1SDimitry Andric shmdt(R.second.LocalAddr);
448*0fca6ea1SDimitry Andric #else
449bdd1243dSDimitry Andric munmap(R.second.LocalAddr, R.second.Size);
450*0fca6ea1SDimitry Andric #endif
451bdd1243dSDimitry Andric
452bdd1243dSDimitry Andric #elif defined(_WIN32)
453bdd1243dSDimitry Andric
454bdd1243dSDimitry Andric UnmapViewOfFile(R.second.LocalAddr);
455bdd1243dSDimitry Andric
456bdd1243dSDimitry Andric #else
457bdd1243dSDimitry Andric
458bdd1243dSDimitry Andric (void)R;
459bdd1243dSDimitry Andric
460bdd1243dSDimitry Andric #endif
461bdd1243dSDimitry Andric }
462fcaf7f86SDimitry Andric }
463fcaf7f86SDimitry Andric
46481ad6265SDimitry Andric } // namespace orc
46581ad6265SDimitry Andric
46681ad6265SDimitry Andric } // namespace llvm
467