xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp (revision 1f4d91ecb8529678a3d3919d7523743bd21942ca)
179fbee3cSAnubhab Ghosh //===- MemoryMapper.cpp - Cross-process memory mapper ------------*- C++ -*-==//
279fbee3cSAnubhab Ghosh //
379fbee3cSAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
479fbee3cSAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information.
579fbee3cSAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
679fbee3cSAnubhab Ghosh //
779fbee3cSAnubhab Ghosh //===----------------------------------------------------------------------===//
879fbee3cSAnubhab Ghosh 
979fbee3cSAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
1079fbee3cSAnubhab Ghosh 
11*89e6a288SDaniil Fukalov #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
121b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
131b1f1c77SAnubhab Ghosh #include "llvm/Support/WindowsError.h"
140ecfee0bSAnubhab Ghosh 
15ac3cb4ecSAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
161b1f1c77SAnubhab Ghosh #include <fcntl.h>
171b1f1c77SAnubhab Ghosh #include <sys/mman.h>
18ee736519SFanbo Meng #if defined(__MVS__)
19ee736519SFanbo Meng #include "llvm/Support/BLAKE3.h"
20ee736519SFanbo Meng #include <sys/shm.h>
21ee736519SFanbo Meng #endif
221b1f1c77SAnubhab Ghosh #include <unistd.h>
231b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
241b1f1c77SAnubhab Ghosh #include <windows.h>
251b1f1c77SAnubhab Ghosh #endif
261b1f1c77SAnubhab Ghosh 
2779fbee3cSAnubhab Ghosh namespace llvm {
2879fbee3cSAnubhab Ghosh namespace orc {
2979fbee3cSAnubhab Ghosh 
3079fbee3cSAnubhab Ghosh MemoryMapper::~MemoryMapper() {}
3179fbee3cSAnubhab Ghosh 
324fcf8434SAnubhab Ghosh InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize)
334fcf8434SAnubhab Ghosh     : PageSize(PageSize) {}
344fcf8434SAnubhab Ghosh 
354fcf8434SAnubhab Ghosh Expected<std::unique_ptr<InProcessMemoryMapper>>
364fcf8434SAnubhab Ghosh InProcessMemoryMapper::Create() {
374fcf8434SAnubhab Ghosh   auto PageSize = sys::Process::getPageSize();
384fcf8434SAnubhab Ghosh   if (!PageSize)
394fcf8434SAnubhab Ghosh     return PageSize.takeError();
404fcf8434SAnubhab Ghosh   return std::make_unique<InProcessMemoryMapper>(*PageSize);
414fcf8434SAnubhab Ghosh }
424fcf8434SAnubhab Ghosh 
4379fbee3cSAnubhab Ghosh void InProcessMemoryMapper::reserve(size_t NumBytes,
4479fbee3cSAnubhab Ghosh                                     OnReservedFunction OnReserved) {
4579fbee3cSAnubhab Ghosh   std::error_code EC;
4679fbee3cSAnubhab Ghosh   auto MB = sys::Memory::allocateMappedMemory(
4779fbee3cSAnubhab Ghosh       NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
4879fbee3cSAnubhab Ghosh 
4979fbee3cSAnubhab Ghosh   if (EC)
5079fbee3cSAnubhab Ghosh     return OnReserved(errorCodeToError(EC));
5179fbee3cSAnubhab Ghosh 
5279fbee3cSAnubhab Ghosh   {
5379fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
5479fbee3cSAnubhab Ghosh     Reservations[MB.base()].Size = MB.allocatedSize();
5579fbee3cSAnubhab Ghosh   }
5679fbee3cSAnubhab Ghosh 
5779fbee3cSAnubhab Ghosh   OnReserved(
5879fbee3cSAnubhab Ghosh       ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
5979fbee3cSAnubhab Ghosh }
6079fbee3cSAnubhab Ghosh 
6179fbee3cSAnubhab Ghosh char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
6279fbee3cSAnubhab Ghosh   return Addr.toPtr<char *>();
6379fbee3cSAnubhab Ghosh }
6479fbee3cSAnubhab Ghosh 
6579fbee3cSAnubhab Ghosh void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
6679fbee3cSAnubhab Ghosh                                        OnInitializedFunction OnInitialized) {
6779fbee3cSAnubhab Ghosh   ExecutorAddr MinAddr(~0ULL);
68a31af321SAnubhab Ghosh   ExecutorAddr MaxAddr(0);
6979fbee3cSAnubhab Ghosh 
70d3d9f7caSLang Hames   // FIXME: Release finalize lifetime segments.
7179fbee3cSAnubhab Ghosh   for (auto &Segment : AI.Segments) {
7279fbee3cSAnubhab Ghosh     auto Base = AI.MappingBase + Segment.Offset;
7379fbee3cSAnubhab Ghosh     auto Size = Segment.ContentSize + Segment.ZeroFillSize;
7479fbee3cSAnubhab Ghosh 
7579fbee3cSAnubhab Ghosh     if (Base < MinAddr)
7679fbee3cSAnubhab Ghosh       MinAddr = Base;
7779fbee3cSAnubhab Ghosh 
78a31af321SAnubhab Ghosh     if (Base + Size > MaxAddr)
79a31af321SAnubhab Ghosh       MaxAddr = Base + Size;
80a31af321SAnubhab Ghosh 
8179fbee3cSAnubhab Ghosh     std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
8279fbee3cSAnubhab Ghosh                 Segment.ZeroFillSize);
8379fbee3cSAnubhab Ghosh 
84d3d9f7caSLang Hames     if (auto EC = sys::Memory::protectMappedMemory(
85d3d9f7caSLang Hames             {Base.toPtr<void *>(), Size},
86d3d9f7caSLang Hames             toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) {
8779fbee3cSAnubhab Ghosh       return OnInitialized(errorCodeToError(EC));
8879fbee3cSAnubhab Ghosh     }
89d3d9f7caSLang Hames     if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
9079fbee3cSAnubhab Ghosh       sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
9179fbee3cSAnubhab Ghosh   }
9279fbee3cSAnubhab Ghosh 
9379fbee3cSAnubhab Ghosh   auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
9479fbee3cSAnubhab Ghosh   if (!DeinitializeActions)
9579fbee3cSAnubhab Ghosh     return OnInitialized(DeinitializeActions.takeError());
9679fbee3cSAnubhab Ghosh 
9779fbee3cSAnubhab Ghosh   {
9879fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
99a31af321SAnubhab Ghosh 
100a31af321SAnubhab Ghosh     // This is the maximum range whose permission have been possibly modified
101a31af321SAnubhab Ghosh     Allocations[MinAddr].Size = MaxAddr - MinAddr;
10279fbee3cSAnubhab Ghosh     Allocations[MinAddr].DeinitializationActions =
10379fbee3cSAnubhab Ghosh         std::move(*DeinitializeActions);
10479fbee3cSAnubhab Ghosh     Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
10579fbee3cSAnubhab Ghosh   }
10679fbee3cSAnubhab Ghosh 
10779fbee3cSAnubhab Ghosh   OnInitialized(MinAddr);
10879fbee3cSAnubhab Ghosh }
10979fbee3cSAnubhab Ghosh 
11079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::deinitialize(
11179fbee3cSAnubhab Ghosh     ArrayRef<ExecutorAddr> Bases,
11279fbee3cSAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
11379fbee3cSAnubhab Ghosh   Error AllErr = Error::success();
11479fbee3cSAnubhab Ghosh 
11579fbee3cSAnubhab Ghosh   {
11679fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
11779fbee3cSAnubhab Ghosh 
118349e5bd2SLang Hames     for (auto Base : llvm::reverse(Bases)) {
11979fbee3cSAnubhab Ghosh 
12079fbee3cSAnubhab Ghosh       if (Error Err = shared::runDeallocActions(
12179fbee3cSAnubhab Ghosh               Allocations[Base].DeinitializationActions)) {
12279fbee3cSAnubhab Ghosh         AllErr = joinErrors(std::move(AllErr), std::move(Err));
12379fbee3cSAnubhab Ghosh       }
12479fbee3cSAnubhab Ghosh 
125a31af321SAnubhab Ghosh       // Reset protections to read/write so the area can be reused
126a31af321SAnubhab Ghosh       if (auto EC = sys::Memory::protectMappedMemory(
127a31af321SAnubhab Ghosh               {Base.toPtr<void *>(), Allocations[Base].Size},
128a31af321SAnubhab Ghosh               sys::Memory::ProtectionFlags::MF_READ |
129a31af321SAnubhab Ghosh                   sys::Memory::ProtectionFlags::MF_WRITE)) {
130a31af321SAnubhab Ghosh         AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC));
131a31af321SAnubhab Ghosh       }
132a31af321SAnubhab Ghosh 
13379fbee3cSAnubhab Ghosh       Allocations.erase(Base);
13479fbee3cSAnubhab Ghosh     }
13579fbee3cSAnubhab Ghosh   }
13679fbee3cSAnubhab Ghosh 
13779fbee3cSAnubhab Ghosh   OnDeinitialized(std::move(AllErr));
13879fbee3cSAnubhab Ghosh }
13979fbee3cSAnubhab Ghosh 
14079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
14179fbee3cSAnubhab Ghosh                                     OnReleasedFunction OnReleased) {
14279fbee3cSAnubhab Ghosh   Error Err = Error::success();
14379fbee3cSAnubhab Ghosh 
14479fbee3cSAnubhab Ghosh   for (auto Base : Bases) {
14579fbee3cSAnubhab Ghosh     std::vector<ExecutorAddr> AllocAddrs;
14679fbee3cSAnubhab Ghosh     size_t Size;
14779fbee3cSAnubhab Ghosh     {
14879fbee3cSAnubhab Ghosh       std::lock_guard<std::mutex> Lock(Mutex);
14979fbee3cSAnubhab Ghosh       auto &R = Reservations[Base.toPtr<void *>()];
15079fbee3cSAnubhab Ghosh       Size = R.Size;
15179fbee3cSAnubhab Ghosh       AllocAddrs.swap(R.Allocations);
15279fbee3cSAnubhab Ghosh     }
15379fbee3cSAnubhab Ghosh 
15479fbee3cSAnubhab Ghosh     // deinitialize sub allocations
15579fbee3cSAnubhab Ghosh     std::promise<MSVCPError> P;
15679fbee3cSAnubhab Ghosh     auto F = P.get_future();
15779fbee3cSAnubhab Ghosh     deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
15879fbee3cSAnubhab Ghosh     if (Error E = F.get()) {
15979fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), std::move(E));
16079fbee3cSAnubhab Ghosh     }
16179fbee3cSAnubhab Ghosh 
16279fbee3cSAnubhab Ghosh     // free the memory
16379fbee3cSAnubhab Ghosh     auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
16479fbee3cSAnubhab Ghosh 
16579fbee3cSAnubhab Ghosh     auto EC = sys::Memory::releaseMappedMemory(MB);
16679fbee3cSAnubhab Ghosh     if (EC) {
16779fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), errorCodeToError(EC));
16879fbee3cSAnubhab Ghosh     }
16979fbee3cSAnubhab Ghosh 
17079fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
17179fbee3cSAnubhab Ghosh     Reservations.erase(Base.toPtr<void *>());
17279fbee3cSAnubhab Ghosh   }
17379fbee3cSAnubhab Ghosh 
17479fbee3cSAnubhab Ghosh   OnReleased(std::move(Err));
17579fbee3cSAnubhab Ghosh }
17679fbee3cSAnubhab Ghosh 
17779fbee3cSAnubhab Ghosh InProcessMemoryMapper::~InProcessMemoryMapper() {
17879fbee3cSAnubhab Ghosh   std::vector<ExecutorAddr> ReservationAddrs;
17979fbee3cSAnubhab Ghosh   {
18079fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
18179fbee3cSAnubhab Ghosh 
18279fbee3cSAnubhab Ghosh     ReservationAddrs.reserve(Reservations.size());
18379fbee3cSAnubhab Ghosh     for (const auto &R : Reservations) {
18479fbee3cSAnubhab Ghosh       ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
18579fbee3cSAnubhab Ghosh     }
18679fbee3cSAnubhab Ghosh   }
18779fbee3cSAnubhab Ghosh 
18879fbee3cSAnubhab Ghosh   std::promise<MSVCPError> P;
18979fbee3cSAnubhab Ghosh   auto F = P.get_future();
19079fbee3cSAnubhab Ghosh   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
19179fbee3cSAnubhab Ghosh   cantFail(F.get());
19279fbee3cSAnubhab Ghosh }
19379fbee3cSAnubhab Ghosh 
1941b1f1c77SAnubhab Ghosh // SharedMemoryMapper
1951b1f1c77SAnubhab Ghosh 
1964fcf8434SAnubhab Ghosh SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC,
1974fcf8434SAnubhab Ghosh                                        SymbolAddrs SAs, size_t PageSize)
198ac3cb4ecSAnubhab Ghosh     : EPC(EPC), SAs(SAs), PageSize(PageSize) {
199ac3cb4ecSAnubhab Ghosh #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32)
200ac3cb4ecSAnubhab Ghosh   llvm_unreachable("SharedMemoryMapper is not supported on this platform yet");
201ac3cb4ecSAnubhab Ghosh #endif
202ac3cb4ecSAnubhab Ghosh }
2034fcf8434SAnubhab Ghosh 
2044fcf8434SAnubhab Ghosh Expected<std::unique_ptr<SharedMemoryMapper>>
2054fcf8434SAnubhab Ghosh SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
206ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2074fcf8434SAnubhab Ghosh   auto PageSize = sys::Process::getPageSize();
2084fcf8434SAnubhab Ghosh   if (!PageSize)
2094fcf8434SAnubhab Ghosh     return PageSize.takeError();
2104fcf8434SAnubhab Ghosh 
2114fcf8434SAnubhab Ghosh   return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
212ac3cb4ecSAnubhab Ghosh #else
213ac3cb4ecSAnubhab Ghosh   return make_error<StringError>(
214ac3cb4ecSAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
215ac3cb4ecSAnubhab Ghosh       inconvertibleErrorCode());
216ac3cb4ecSAnubhab Ghosh #endif
2174fcf8434SAnubhab Ghosh }
2184fcf8434SAnubhab Ghosh 
2191b1f1c77SAnubhab Ghosh void SharedMemoryMapper::reserve(size_t NumBytes,
2201b1f1c77SAnubhab Ghosh                                  OnReservedFunction OnReserved) {
221ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2221b1f1c77SAnubhab Ghosh 
2231b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
2241b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>(
2251b1f1c77SAnubhab Ghosh       SAs.Reserve,
2261b1f1c77SAnubhab Ghosh       [this, NumBytes, OnReserved = std::move(OnReserved)](
2271b1f1c77SAnubhab Ghosh           Error SerializationErr,
2281b1f1c77SAnubhab Ghosh           Expected<std::pair<ExecutorAddr, std::string>> Result) mutable {
2291b1f1c77SAnubhab Ghosh         if (SerializationErr) {
2301b1f1c77SAnubhab Ghosh           cantFail(Result.takeError());
2311b1f1c77SAnubhab Ghosh           return OnReserved(std::move(SerializationErr));
2321b1f1c77SAnubhab Ghosh         }
2331b1f1c77SAnubhab Ghosh 
2341b1f1c77SAnubhab Ghosh         if (!Result)
2351b1f1c77SAnubhab Ghosh           return OnReserved(Result.takeError());
2361b1f1c77SAnubhab Ghosh 
2371b1f1c77SAnubhab Ghosh         ExecutorAddr RemoteAddr;
2381b1f1c77SAnubhab Ghosh         std::string SharedMemoryName;
2391b1f1c77SAnubhab Ghosh         std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result);
2401b1f1c77SAnubhab Ghosh 
2411b1f1c77SAnubhab Ghosh         void *LocalAddr = nullptr;
2421b1f1c77SAnubhab Ghosh 
2431b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX)
2441b1f1c77SAnubhab Ghosh 
245ee736519SFanbo Meng #if defined(__MVS__)
246ee736519SFanbo Meng         ArrayRef<uint8_t> Data(
247ee736519SFanbo Meng             reinterpret_cast<const uint8_t *>(SharedMemoryName.c_str()),
248ee736519SFanbo Meng             SharedMemoryName.size());
249ee736519SFanbo Meng         auto HashedName = BLAKE3::hash<sizeof(key_t)>(Data);
250ee736519SFanbo Meng         key_t Key = *reinterpret_cast<key_t *>(HashedName.data());
251ee736519SFanbo Meng         int SharedMemoryId =
252ee736519SFanbo Meng             shmget(Key, NumBytes, IPC_CREAT | __IPC_SHAREAS | 0700);
253ee736519SFanbo Meng         if (SharedMemoryId < 0) {
254ee736519SFanbo Meng           return OnReserved(errorCodeToError(
255ee736519SFanbo Meng               std::error_code(errno, std::generic_category())));
256ee736519SFanbo Meng         }
257ee736519SFanbo Meng         LocalAddr = shmat(SharedMemoryId, nullptr, 0);
258ee736519SFanbo Meng         if (LocalAddr == reinterpret_cast<void *>(-1)) {
259ee736519SFanbo Meng           return OnReserved(errorCodeToError(
260ee736519SFanbo Meng               std::error_code(errno, std::generic_category())));
261ee736519SFanbo Meng         }
262ee736519SFanbo Meng #else
2631b1f1c77SAnubhab Ghosh         int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
2641b1f1c77SAnubhab Ghosh         if (SharedMemoryFile < 0) {
265ba13fa2aSMichael Spencer           return OnReserved(errorCodeToError(errnoAsErrorCode()));
2661b1f1c77SAnubhab Ghosh         }
2671b1f1c77SAnubhab Ghosh 
2681b1f1c77SAnubhab Ghosh         // this prevents other processes from accessing it by name
2691b1f1c77SAnubhab Ghosh         shm_unlink(SharedMemoryName.c_str());
2701b1f1c77SAnubhab Ghosh 
2711b1f1c77SAnubhab Ghosh         LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
2721b1f1c77SAnubhab Ghosh                          SharedMemoryFile, 0);
2731b1f1c77SAnubhab Ghosh         if (LocalAddr == MAP_FAILED) {
274ba13fa2aSMichael Spencer           return OnReserved(errorCodeToError(errnoAsErrorCode()));
2751b1f1c77SAnubhab Ghosh         }
2761b1f1c77SAnubhab Ghosh 
2771b1f1c77SAnubhab Ghosh         close(SharedMemoryFile);
278ee736519SFanbo Meng #endif
2791b1f1c77SAnubhab Ghosh 
2801b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
2811b1f1c77SAnubhab Ghosh 
2821b1f1c77SAnubhab Ghosh         std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
2831b1f1c77SAnubhab Ghosh                                           SharedMemoryName.end());
2841b1f1c77SAnubhab Ghosh         HANDLE SharedMemoryFile = OpenFileMappingW(
2851b1f1c77SAnubhab Ghosh             FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
2861b1f1c77SAnubhab Ghosh         if (!SharedMemoryFile)
2871b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2881b1f1c77SAnubhab Ghosh 
2891b1f1c77SAnubhab Ghosh         LocalAddr =
2901b1f1c77SAnubhab Ghosh             MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
2911b1f1c77SAnubhab Ghosh         if (!LocalAddr) {
2921b1f1c77SAnubhab Ghosh           CloseHandle(SharedMemoryFile);
2931b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2941b1f1c77SAnubhab Ghosh         }
2951b1f1c77SAnubhab Ghosh 
2961b1f1c77SAnubhab Ghosh         CloseHandle(SharedMemoryFile);
2971b1f1c77SAnubhab Ghosh 
2981b1f1c77SAnubhab Ghosh #endif
2991b1f1c77SAnubhab Ghosh         {
3001b1f1c77SAnubhab Ghosh           std::lock_guard<std::mutex> Lock(Mutex);
3011b1f1c77SAnubhab Ghosh           Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
3021b1f1c77SAnubhab Ghosh         }
3031b1f1c77SAnubhab Ghosh 
3041b1f1c77SAnubhab Ghosh         OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes));
3051b1f1c77SAnubhab Ghosh       },
3061b1f1c77SAnubhab Ghosh       SAs.Instance, static_cast<uint64_t>(NumBytes));
3071b1f1c77SAnubhab Ghosh 
3081b1f1c77SAnubhab Ghosh #else
3091b1f1c77SAnubhab Ghosh   OnReserved(make_error<StringError>(
3101b1f1c77SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
3111b1f1c77SAnubhab Ghosh       inconvertibleErrorCode()));
3121b1f1c77SAnubhab Ghosh #endif
3131b1f1c77SAnubhab Ghosh }
3141b1f1c77SAnubhab Ghosh 
3151b1f1c77SAnubhab Ghosh char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
3161b1f1c77SAnubhab Ghosh   auto R = Reservations.upper_bound(Addr);
317ab492f62SAnubhab Ghosh   assert(R != Reservations.begin() && "Attempt to prepare unreserved range");
3181b1f1c77SAnubhab Ghosh   R--;
3191b1f1c77SAnubhab Ghosh 
3201b1f1c77SAnubhab Ghosh   ExecutorAddrDiff Offset = Addr - R->first;
3211b1f1c77SAnubhab Ghosh 
3221b1f1c77SAnubhab Ghosh   return static_cast<char *>(R->second.LocalAddr) + Offset;
3231b1f1c77SAnubhab Ghosh }
3241b1f1c77SAnubhab Ghosh 
3251b1f1c77SAnubhab Ghosh void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
3261b1f1c77SAnubhab Ghosh                                     OnInitializedFunction OnInitialized) {
327ab492f62SAnubhab Ghosh   auto Reservation = Reservations.upper_bound(AI.MappingBase);
328ab492f62SAnubhab Ghosh   assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range");
329ab492f62SAnubhab Ghosh   Reservation--;
330ab492f62SAnubhab Ghosh 
331ab492f62SAnubhab Ghosh   auto AllocationOffset = AI.MappingBase - Reservation->first;
3321b1f1c77SAnubhab Ghosh 
3331b1f1c77SAnubhab Ghosh   tpctypes::SharedMemoryFinalizeRequest FR;
3341b1f1c77SAnubhab Ghosh 
3351b1f1c77SAnubhab Ghosh   AI.Actions.swap(FR.Actions);
3361b1f1c77SAnubhab Ghosh 
3371b1f1c77SAnubhab Ghosh   FR.Segments.reserve(AI.Segments.size());
3381b1f1c77SAnubhab Ghosh 
3391b1f1c77SAnubhab Ghosh   for (auto Segment : AI.Segments) {
340ab492f62SAnubhab Ghosh     char *Base = static_cast<char *>(Reservation->second.LocalAddr) +
341ab492f62SAnubhab Ghosh                  AllocationOffset + Segment.Offset;
3421b1f1c77SAnubhab Ghosh     std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
3431b1f1c77SAnubhab Ghosh 
3441b1f1c77SAnubhab Ghosh     tpctypes::SharedMemorySegFinalizeRequest SegReq;
345e994f84cSLang Hames     SegReq.RAG = {Segment.AG.getMemProt(),
346e994f84cSLang Hames                   Segment.AG.getMemLifetime() == MemLifetime::Finalize};
3471b1f1c77SAnubhab Ghosh     SegReq.Addr = AI.MappingBase + Segment.Offset;
3481b1f1c77SAnubhab Ghosh     SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
3491b1f1c77SAnubhab Ghosh 
3501b1f1c77SAnubhab Ghosh     FR.Segments.push_back(SegReq);
3511b1f1c77SAnubhab Ghosh   }
3521b1f1c77SAnubhab Ghosh 
3531b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3541b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>(
3551b1f1c77SAnubhab Ghosh       SAs.Initialize,
3561b1f1c77SAnubhab Ghosh       [OnInitialized = std::move(OnInitialized)](
3571b1f1c77SAnubhab Ghosh           Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
3581b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3591b1f1c77SAnubhab Ghosh           cantFail(Result.takeError());
3601b1f1c77SAnubhab Ghosh           return OnInitialized(std::move(SerializationErr));
3611b1f1c77SAnubhab Ghosh         }
3621b1f1c77SAnubhab Ghosh 
3631b1f1c77SAnubhab Ghosh         OnInitialized(std::move(Result));
3641b1f1c77SAnubhab Ghosh       },
3650ecfee0bSAnubhab Ghosh       SAs.Instance, Reservation->first, std::move(FR));
3661b1f1c77SAnubhab Ghosh }
3671b1f1c77SAnubhab Ghosh 
3681b1f1c77SAnubhab Ghosh void SharedMemoryMapper::deinitialize(
3691b1f1c77SAnubhab Ghosh     ArrayRef<ExecutorAddr> Allocations,
3701b1f1c77SAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
3711b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3721b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>(
3731b1f1c77SAnubhab Ghosh       SAs.Deinitialize,
3741b1f1c77SAnubhab Ghosh       [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
3751b1f1c77SAnubhab Ghosh                                                      Error Result) mutable {
3761b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3771b1f1c77SAnubhab Ghosh           cantFail(std::move(Result));
3781b1f1c77SAnubhab Ghosh           return OnDeinitialized(std::move(SerializationErr));
3791b1f1c77SAnubhab Ghosh         }
3801b1f1c77SAnubhab Ghosh 
3811b1f1c77SAnubhab Ghosh         OnDeinitialized(std::move(Result));
3821b1f1c77SAnubhab Ghosh       },
3831b1f1c77SAnubhab Ghosh       SAs.Instance, Allocations);
3841b1f1c77SAnubhab Ghosh }
3851b1f1c77SAnubhab Ghosh 
3861b1f1c77SAnubhab Ghosh void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
3871b1f1c77SAnubhab Ghosh                                  OnReleasedFunction OnReleased) {
388ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
3891b1f1c77SAnubhab Ghosh   Error Err = Error::success();
3901b1f1c77SAnubhab Ghosh 
3911b1f1c77SAnubhab Ghosh   {
3921b1f1c77SAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
3931b1f1c77SAnubhab Ghosh 
3941b1f1c77SAnubhab Ghosh     for (auto Base : Bases) {
3951b1f1c77SAnubhab Ghosh 
3961b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX)
3971b1f1c77SAnubhab Ghosh 
398ee736519SFanbo Meng #if defined(__MVS__)
399ee736519SFanbo Meng       if (shmdt(Reservations[Base].LocalAddr) < 0)
400ee736519SFanbo Meng         Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode()));
401ee736519SFanbo Meng #else
4021b1f1c77SAnubhab Ghosh       if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0)
403ba13fa2aSMichael Spencer         Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode()));
404ee736519SFanbo Meng #endif
4051b1f1c77SAnubhab Ghosh 
4061b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
4071b1f1c77SAnubhab Ghosh 
4081b1f1c77SAnubhab Ghosh       if (!UnmapViewOfFile(Reservations[Base].LocalAddr))
40946bc1b56SMartin Storsjö         Err = joinErrors(std::move(Err),
4101b1f1c77SAnubhab Ghosh                          errorCodeToError(mapWindowsError(GetLastError())));
4111b1f1c77SAnubhab Ghosh 
4121b1f1c77SAnubhab Ghosh #endif
4131b1f1c77SAnubhab Ghosh 
4141b1f1c77SAnubhab Ghosh       Reservations.erase(Base);
4151b1f1c77SAnubhab Ghosh     }
4161b1f1c77SAnubhab Ghosh   }
4171b1f1c77SAnubhab Ghosh 
4181b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
4191b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>(
4201b1f1c77SAnubhab Ghosh       SAs.Release,
4211b1f1c77SAnubhab Ghosh       [OnReleased = std::move(OnReleased),
4221b1f1c77SAnubhab Ghosh        Err = std::move(Err)](Error SerializationErr, Error Result) mutable {
4231b1f1c77SAnubhab Ghosh         if (SerializationErr) {
4241b1f1c77SAnubhab Ghosh           cantFail(std::move(Result));
4251b1f1c77SAnubhab Ghosh           return OnReleased(
4261b1f1c77SAnubhab Ghosh               joinErrors(std::move(Err), std::move(SerializationErr)));
4271b1f1c77SAnubhab Ghosh         }
4281b1f1c77SAnubhab Ghosh 
4291b1f1c77SAnubhab Ghosh         return OnReleased(joinErrors(std::move(Err), std::move(Result)));
4301b1f1c77SAnubhab Ghosh       },
4311b1f1c77SAnubhab Ghosh       SAs.Instance, Bases);
4321b1f1c77SAnubhab Ghosh #else
4331b1f1c77SAnubhab Ghosh   OnReleased(make_error<StringError>(
4341b1f1c77SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
4351b1f1c77SAnubhab Ghosh       inconvertibleErrorCode()));
4361b1f1c77SAnubhab Ghosh #endif
4371b1f1c77SAnubhab Ghosh }
4381b1f1c77SAnubhab Ghosh 
4391b1f1c77SAnubhab Ghosh SharedMemoryMapper::~SharedMemoryMapper() {
4401c25ce17SAlexandre Ganea   std::lock_guard<std::mutex> Lock(Mutex);
4413019f488SLang Hames   for (const auto &R : Reservations) {
4421b1f1c77SAnubhab Ghosh 
4431134d3a0SAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
4441134d3a0SAnubhab Ghosh 
445ee736519SFanbo Meng #if defined(__MVS__)
446ee736519SFanbo Meng     shmdt(R.second.LocalAddr);
447ee736519SFanbo Meng #else
4481134d3a0SAnubhab Ghosh     munmap(R.second.LocalAddr, R.second.Size);
449ee736519SFanbo Meng #endif
4501134d3a0SAnubhab Ghosh 
4511134d3a0SAnubhab Ghosh #elif defined(_WIN32)
4521134d3a0SAnubhab Ghosh 
4531134d3a0SAnubhab Ghosh     UnmapViewOfFile(R.second.LocalAddr);
4541134d3a0SAnubhab Ghosh 
4551c2ee6bdSDavid Blaikie #else
4561c2ee6bdSDavid Blaikie 
4571c2ee6bdSDavid Blaikie     (void)R;
4581c2ee6bdSDavid Blaikie 
4591134d3a0SAnubhab Ghosh #endif
4601134d3a0SAnubhab Ghosh   }
4611b1f1c77SAnubhab Ghosh }
4621b1f1c77SAnubhab Ghosh 
46379fbee3cSAnubhab Ghosh } // namespace orc
46479fbee3cSAnubhab Ghosh 
46579fbee3cSAnubhab Ghosh } // namespace llvm
466