xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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