xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp (revision 1c2ee6bdceaa608fee9095f948dca724ddf15b83)
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 
111b1f1c77SAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
121b1f1c77SAnubhab Ghosh #include "llvm/Support/WindowsError.h"
131b1f1c77SAnubhab Ghosh 
140ecfee0bSAnubhab Ghosh #include <algorithm>
150ecfee0bSAnubhab Ghosh 
16ac3cb4ecSAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
171b1f1c77SAnubhab Ghosh #include <fcntl.h>
181b1f1c77SAnubhab Ghosh #include <sys/mman.h>
191b1f1c77SAnubhab Ghosh #include <unistd.h>
201b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
211b1f1c77SAnubhab Ghosh #include <windows.h>
221b1f1c77SAnubhab Ghosh #endif
231b1f1c77SAnubhab Ghosh 
2479fbee3cSAnubhab Ghosh namespace llvm {
2579fbee3cSAnubhab Ghosh namespace orc {
2679fbee3cSAnubhab Ghosh 
2779fbee3cSAnubhab Ghosh MemoryMapper::~MemoryMapper() {}
2879fbee3cSAnubhab Ghosh 
294fcf8434SAnubhab Ghosh InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize)
304fcf8434SAnubhab Ghosh     : PageSize(PageSize) {}
314fcf8434SAnubhab Ghosh 
324fcf8434SAnubhab Ghosh Expected<std::unique_ptr<InProcessMemoryMapper>>
334fcf8434SAnubhab Ghosh InProcessMemoryMapper::Create() {
344fcf8434SAnubhab Ghosh   auto PageSize = sys::Process::getPageSize();
354fcf8434SAnubhab Ghosh   if (!PageSize)
364fcf8434SAnubhab Ghosh     return PageSize.takeError();
374fcf8434SAnubhab Ghosh   return std::make_unique<InProcessMemoryMapper>(*PageSize);
384fcf8434SAnubhab Ghosh }
394fcf8434SAnubhab Ghosh 
4079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::reserve(size_t NumBytes,
4179fbee3cSAnubhab Ghosh                                     OnReservedFunction OnReserved) {
4279fbee3cSAnubhab Ghosh   std::error_code EC;
4379fbee3cSAnubhab Ghosh   auto MB = sys::Memory::allocateMappedMemory(
4479fbee3cSAnubhab Ghosh       NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
4579fbee3cSAnubhab Ghosh 
4679fbee3cSAnubhab Ghosh   if (EC)
4779fbee3cSAnubhab Ghosh     return OnReserved(errorCodeToError(EC));
4879fbee3cSAnubhab Ghosh 
4979fbee3cSAnubhab Ghosh   {
5079fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
5179fbee3cSAnubhab Ghosh     Reservations[MB.base()].Size = MB.allocatedSize();
5279fbee3cSAnubhab Ghosh   }
5379fbee3cSAnubhab Ghosh 
5479fbee3cSAnubhab Ghosh   OnReserved(
5579fbee3cSAnubhab Ghosh       ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
5679fbee3cSAnubhab Ghosh }
5779fbee3cSAnubhab Ghosh 
5879fbee3cSAnubhab Ghosh char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
5979fbee3cSAnubhab Ghosh   return Addr.toPtr<char *>();
6079fbee3cSAnubhab Ghosh }
6179fbee3cSAnubhab Ghosh 
6279fbee3cSAnubhab Ghosh void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
6379fbee3cSAnubhab Ghosh                                        OnInitializedFunction OnInitialized) {
6479fbee3cSAnubhab Ghosh   ExecutorAddr MinAddr(~0ULL);
65a31af321SAnubhab Ghosh   ExecutorAddr MaxAddr(0);
6679fbee3cSAnubhab Ghosh 
67d3d9f7caSLang Hames   // FIXME: Release finalize lifetime segments.
6879fbee3cSAnubhab Ghosh   for (auto &Segment : AI.Segments) {
6979fbee3cSAnubhab Ghosh     auto Base = AI.MappingBase + Segment.Offset;
7079fbee3cSAnubhab Ghosh     auto Size = Segment.ContentSize + Segment.ZeroFillSize;
7179fbee3cSAnubhab Ghosh 
7279fbee3cSAnubhab Ghosh     if (Base < MinAddr)
7379fbee3cSAnubhab Ghosh       MinAddr = Base;
7479fbee3cSAnubhab Ghosh 
75a31af321SAnubhab Ghosh     if (Base + Size > MaxAddr)
76a31af321SAnubhab Ghosh       MaxAddr = Base + Size;
77a31af321SAnubhab Ghosh 
7879fbee3cSAnubhab Ghosh     std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
7979fbee3cSAnubhab Ghosh                 Segment.ZeroFillSize);
8079fbee3cSAnubhab Ghosh 
81d3d9f7caSLang Hames     if (auto EC = sys::Memory::protectMappedMemory(
82d3d9f7caSLang Hames             {Base.toPtr<void *>(), Size},
83d3d9f7caSLang Hames             toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) {
8479fbee3cSAnubhab Ghosh       return OnInitialized(errorCodeToError(EC));
8579fbee3cSAnubhab Ghosh     }
86d3d9f7caSLang Hames     if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
8779fbee3cSAnubhab Ghosh       sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
8879fbee3cSAnubhab Ghosh   }
8979fbee3cSAnubhab Ghosh 
9079fbee3cSAnubhab Ghosh   auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
9179fbee3cSAnubhab Ghosh   if (!DeinitializeActions)
9279fbee3cSAnubhab Ghosh     return OnInitialized(DeinitializeActions.takeError());
9379fbee3cSAnubhab Ghosh 
9479fbee3cSAnubhab Ghosh   {
9579fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
96a31af321SAnubhab Ghosh 
97a31af321SAnubhab Ghosh     // This is the maximum range whose permission have been possibly modified
98a31af321SAnubhab Ghosh     Allocations[MinAddr].Size = MaxAddr - MinAddr;
9979fbee3cSAnubhab Ghosh     Allocations[MinAddr].DeinitializationActions =
10079fbee3cSAnubhab Ghosh         std::move(*DeinitializeActions);
10179fbee3cSAnubhab Ghosh     Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
10279fbee3cSAnubhab Ghosh   }
10379fbee3cSAnubhab Ghosh 
10479fbee3cSAnubhab Ghosh   OnInitialized(MinAddr);
10579fbee3cSAnubhab Ghosh }
10679fbee3cSAnubhab Ghosh 
10779fbee3cSAnubhab Ghosh void InProcessMemoryMapper::deinitialize(
10879fbee3cSAnubhab Ghosh     ArrayRef<ExecutorAddr> Bases,
10979fbee3cSAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
11079fbee3cSAnubhab Ghosh   Error AllErr = Error::success();
11179fbee3cSAnubhab Ghosh 
11279fbee3cSAnubhab Ghosh   {
11379fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
11479fbee3cSAnubhab Ghosh 
115349e5bd2SLang Hames     for (auto Base : llvm::reverse(Bases)) {
11679fbee3cSAnubhab Ghosh 
11779fbee3cSAnubhab Ghosh       if (Error Err = shared::runDeallocActions(
11879fbee3cSAnubhab Ghosh               Allocations[Base].DeinitializationActions)) {
11979fbee3cSAnubhab Ghosh         AllErr = joinErrors(std::move(AllErr), std::move(Err));
12079fbee3cSAnubhab Ghosh       }
12179fbee3cSAnubhab Ghosh 
122a31af321SAnubhab Ghosh       // Reset protections to read/write so the area can be reused
123a31af321SAnubhab Ghosh       if (auto EC = sys::Memory::protectMappedMemory(
124a31af321SAnubhab Ghosh               {Base.toPtr<void *>(), Allocations[Base].Size},
125a31af321SAnubhab Ghosh               sys::Memory::ProtectionFlags::MF_READ |
126a31af321SAnubhab Ghosh                   sys::Memory::ProtectionFlags::MF_WRITE)) {
127a31af321SAnubhab Ghosh         AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC));
128a31af321SAnubhab Ghosh       }
129a31af321SAnubhab Ghosh 
13079fbee3cSAnubhab Ghosh       Allocations.erase(Base);
13179fbee3cSAnubhab Ghosh     }
13279fbee3cSAnubhab Ghosh   }
13379fbee3cSAnubhab Ghosh 
13479fbee3cSAnubhab Ghosh   OnDeinitialized(std::move(AllErr));
13579fbee3cSAnubhab Ghosh }
13679fbee3cSAnubhab Ghosh 
13779fbee3cSAnubhab Ghosh void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
13879fbee3cSAnubhab Ghosh                                     OnReleasedFunction OnReleased) {
13979fbee3cSAnubhab Ghosh   Error Err = Error::success();
14079fbee3cSAnubhab Ghosh 
14179fbee3cSAnubhab Ghosh   for (auto Base : Bases) {
14279fbee3cSAnubhab Ghosh     std::vector<ExecutorAddr> AllocAddrs;
14379fbee3cSAnubhab Ghosh     size_t Size;
14479fbee3cSAnubhab Ghosh     {
14579fbee3cSAnubhab Ghosh       std::lock_guard<std::mutex> Lock(Mutex);
14679fbee3cSAnubhab Ghosh       auto &R = Reservations[Base.toPtr<void *>()];
14779fbee3cSAnubhab Ghosh       Size = R.Size;
14879fbee3cSAnubhab Ghosh       AllocAddrs.swap(R.Allocations);
14979fbee3cSAnubhab Ghosh     }
15079fbee3cSAnubhab Ghosh 
15179fbee3cSAnubhab Ghosh     // deinitialize sub allocations
15279fbee3cSAnubhab Ghosh     std::promise<MSVCPError> P;
15379fbee3cSAnubhab Ghosh     auto F = P.get_future();
15479fbee3cSAnubhab Ghosh     deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
15579fbee3cSAnubhab Ghosh     if (Error E = F.get()) {
15679fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), std::move(E));
15779fbee3cSAnubhab Ghosh     }
15879fbee3cSAnubhab Ghosh 
15979fbee3cSAnubhab Ghosh     // free the memory
16079fbee3cSAnubhab Ghosh     auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
16179fbee3cSAnubhab Ghosh 
16279fbee3cSAnubhab Ghosh     auto EC = sys::Memory::releaseMappedMemory(MB);
16379fbee3cSAnubhab Ghosh     if (EC) {
16479fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), errorCodeToError(EC));
16579fbee3cSAnubhab Ghosh     }
16679fbee3cSAnubhab Ghosh 
16779fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
16879fbee3cSAnubhab Ghosh     Reservations.erase(Base.toPtr<void *>());
16979fbee3cSAnubhab Ghosh   }
17079fbee3cSAnubhab Ghosh 
17179fbee3cSAnubhab Ghosh   OnReleased(std::move(Err));
17279fbee3cSAnubhab Ghosh }
17379fbee3cSAnubhab Ghosh 
17479fbee3cSAnubhab Ghosh InProcessMemoryMapper::~InProcessMemoryMapper() {
17579fbee3cSAnubhab Ghosh   std::vector<ExecutorAddr> ReservationAddrs;
17679fbee3cSAnubhab Ghosh   {
17779fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
17879fbee3cSAnubhab Ghosh 
17979fbee3cSAnubhab Ghosh     ReservationAddrs.reserve(Reservations.size());
18079fbee3cSAnubhab Ghosh     for (const auto &R : Reservations) {
18179fbee3cSAnubhab Ghosh       ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
18279fbee3cSAnubhab Ghosh     }
18379fbee3cSAnubhab Ghosh   }
18479fbee3cSAnubhab Ghosh 
18579fbee3cSAnubhab Ghosh   std::promise<MSVCPError> P;
18679fbee3cSAnubhab Ghosh   auto F = P.get_future();
18779fbee3cSAnubhab Ghosh   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
18879fbee3cSAnubhab Ghosh   cantFail(F.get());
18979fbee3cSAnubhab Ghosh }
19079fbee3cSAnubhab Ghosh 
1911b1f1c77SAnubhab Ghosh // SharedMemoryMapper
1921b1f1c77SAnubhab Ghosh 
1934fcf8434SAnubhab Ghosh SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC,
1944fcf8434SAnubhab Ghosh                                        SymbolAddrs SAs, size_t PageSize)
195ac3cb4ecSAnubhab Ghosh     : EPC(EPC), SAs(SAs), PageSize(PageSize) {
196ac3cb4ecSAnubhab Ghosh #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32)
197ac3cb4ecSAnubhab Ghosh   llvm_unreachable("SharedMemoryMapper is not supported on this platform yet");
198ac3cb4ecSAnubhab Ghosh #endif
199ac3cb4ecSAnubhab Ghosh }
2004fcf8434SAnubhab Ghosh 
2014fcf8434SAnubhab Ghosh Expected<std::unique_ptr<SharedMemoryMapper>>
2024fcf8434SAnubhab Ghosh SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
203ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2044fcf8434SAnubhab Ghosh   auto PageSize = sys::Process::getPageSize();
2054fcf8434SAnubhab Ghosh   if (!PageSize)
2064fcf8434SAnubhab Ghosh     return PageSize.takeError();
2074fcf8434SAnubhab Ghosh 
2084fcf8434SAnubhab Ghosh   return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
209ac3cb4ecSAnubhab Ghosh #else
210ac3cb4ecSAnubhab Ghosh   return make_error<StringError>(
211ac3cb4ecSAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
212ac3cb4ecSAnubhab Ghosh       inconvertibleErrorCode());
213ac3cb4ecSAnubhab Ghosh #endif
2144fcf8434SAnubhab Ghosh }
2154fcf8434SAnubhab Ghosh 
2161b1f1c77SAnubhab Ghosh void SharedMemoryMapper::reserve(size_t NumBytes,
2171b1f1c77SAnubhab Ghosh                                  OnReservedFunction OnReserved) {
218ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2191b1f1c77SAnubhab Ghosh 
2201b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
2211b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>(
2221b1f1c77SAnubhab Ghosh       SAs.Reserve,
2231b1f1c77SAnubhab Ghosh       [this, NumBytes, OnReserved = std::move(OnReserved)](
2241b1f1c77SAnubhab Ghosh           Error SerializationErr,
2251b1f1c77SAnubhab Ghosh           Expected<std::pair<ExecutorAddr, std::string>> Result) mutable {
2261b1f1c77SAnubhab Ghosh         if (SerializationErr) {
2271b1f1c77SAnubhab Ghosh           cantFail(Result.takeError());
2281b1f1c77SAnubhab Ghosh           return OnReserved(std::move(SerializationErr));
2291b1f1c77SAnubhab Ghosh         }
2301b1f1c77SAnubhab Ghosh 
2311b1f1c77SAnubhab Ghosh         if (!Result)
2321b1f1c77SAnubhab Ghosh           return OnReserved(Result.takeError());
2331b1f1c77SAnubhab Ghosh 
2341b1f1c77SAnubhab Ghosh         ExecutorAddr RemoteAddr;
2351b1f1c77SAnubhab Ghosh         std::string SharedMemoryName;
2361b1f1c77SAnubhab Ghosh         std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result);
2371b1f1c77SAnubhab Ghosh 
2381b1f1c77SAnubhab Ghosh         void *LocalAddr = nullptr;
2391b1f1c77SAnubhab Ghosh 
2401b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX)
2411b1f1c77SAnubhab Ghosh 
2421b1f1c77SAnubhab Ghosh         int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
2431b1f1c77SAnubhab Ghosh         if (SharedMemoryFile < 0) {
2441b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(
2451b1f1c77SAnubhab Ghosh               std::error_code(errno, std::generic_category())));
2461b1f1c77SAnubhab Ghosh         }
2471b1f1c77SAnubhab Ghosh 
2481b1f1c77SAnubhab Ghosh         // this prevents other processes from accessing it by name
2491b1f1c77SAnubhab Ghosh         shm_unlink(SharedMemoryName.c_str());
2501b1f1c77SAnubhab Ghosh 
2511b1f1c77SAnubhab Ghosh         LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
2521b1f1c77SAnubhab Ghosh                          SharedMemoryFile, 0);
2531b1f1c77SAnubhab Ghosh         if (LocalAddr == MAP_FAILED) {
2541b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(
2551b1f1c77SAnubhab Ghosh               std::error_code(errno, std::generic_category())));
2561b1f1c77SAnubhab Ghosh         }
2571b1f1c77SAnubhab Ghosh 
2581b1f1c77SAnubhab Ghosh         close(SharedMemoryFile);
2591b1f1c77SAnubhab Ghosh 
2601b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
2611b1f1c77SAnubhab Ghosh 
2621b1f1c77SAnubhab Ghosh         std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
2631b1f1c77SAnubhab Ghosh                                           SharedMemoryName.end());
2641b1f1c77SAnubhab Ghosh         HANDLE SharedMemoryFile = OpenFileMappingW(
2651b1f1c77SAnubhab Ghosh             FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
2661b1f1c77SAnubhab Ghosh         if (!SharedMemoryFile)
2671b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2681b1f1c77SAnubhab Ghosh 
2691b1f1c77SAnubhab Ghosh         LocalAddr =
2701b1f1c77SAnubhab Ghosh             MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
2711b1f1c77SAnubhab Ghosh         if (!LocalAddr) {
2721b1f1c77SAnubhab Ghosh           CloseHandle(SharedMemoryFile);
2731b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2741b1f1c77SAnubhab Ghosh         }
2751b1f1c77SAnubhab Ghosh 
2761b1f1c77SAnubhab Ghosh         CloseHandle(SharedMemoryFile);
2771b1f1c77SAnubhab Ghosh 
2781b1f1c77SAnubhab Ghosh #endif
2791b1f1c77SAnubhab Ghosh         {
2801b1f1c77SAnubhab Ghosh           std::lock_guard<std::mutex> Lock(Mutex);
2811b1f1c77SAnubhab Ghosh           Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
2821b1f1c77SAnubhab Ghosh         }
2831b1f1c77SAnubhab Ghosh 
2841b1f1c77SAnubhab Ghosh         OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes));
2851b1f1c77SAnubhab Ghosh       },
2861b1f1c77SAnubhab Ghosh       SAs.Instance, static_cast<uint64_t>(NumBytes));
2871b1f1c77SAnubhab Ghosh 
2881b1f1c77SAnubhab Ghosh #else
2891b1f1c77SAnubhab Ghosh   OnReserved(make_error<StringError>(
2901b1f1c77SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
2911b1f1c77SAnubhab Ghosh       inconvertibleErrorCode()));
2921b1f1c77SAnubhab Ghosh #endif
2931b1f1c77SAnubhab Ghosh }
2941b1f1c77SAnubhab Ghosh 
2951b1f1c77SAnubhab Ghosh char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
2961b1f1c77SAnubhab Ghosh   auto R = Reservations.upper_bound(Addr);
297ab492f62SAnubhab Ghosh   assert(R != Reservations.begin() && "Attempt to prepare unreserved range");
2981b1f1c77SAnubhab Ghosh   R--;
2991b1f1c77SAnubhab Ghosh 
3001b1f1c77SAnubhab Ghosh   ExecutorAddrDiff Offset = Addr - R->first;
3011b1f1c77SAnubhab Ghosh 
3021b1f1c77SAnubhab Ghosh   return static_cast<char *>(R->second.LocalAddr) + Offset;
3031b1f1c77SAnubhab Ghosh }
3041b1f1c77SAnubhab Ghosh 
3051b1f1c77SAnubhab Ghosh void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
3061b1f1c77SAnubhab Ghosh                                     OnInitializedFunction OnInitialized) {
307ab492f62SAnubhab Ghosh   auto Reservation = Reservations.upper_bound(AI.MappingBase);
308ab492f62SAnubhab Ghosh   assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range");
309ab492f62SAnubhab Ghosh   Reservation--;
310ab492f62SAnubhab Ghosh 
311ab492f62SAnubhab Ghosh   auto AllocationOffset = AI.MappingBase - Reservation->first;
3121b1f1c77SAnubhab Ghosh 
3131b1f1c77SAnubhab Ghosh   tpctypes::SharedMemoryFinalizeRequest FR;
3141b1f1c77SAnubhab Ghosh 
3151b1f1c77SAnubhab Ghosh   AI.Actions.swap(FR.Actions);
3161b1f1c77SAnubhab Ghosh 
3171b1f1c77SAnubhab Ghosh   FR.Segments.reserve(AI.Segments.size());
3181b1f1c77SAnubhab Ghosh 
3191b1f1c77SAnubhab Ghosh   for (auto Segment : AI.Segments) {
320ab492f62SAnubhab Ghosh     char *Base = static_cast<char *>(Reservation->second.LocalAddr) +
321ab492f62SAnubhab Ghosh                  AllocationOffset + Segment.Offset;
3221b1f1c77SAnubhab Ghosh     std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
3231b1f1c77SAnubhab Ghosh 
3241b1f1c77SAnubhab Ghosh     tpctypes::SharedMemorySegFinalizeRequest SegReq;
325d3d9f7caSLang Hames     SegReq.AG = Segment.AG;
3261b1f1c77SAnubhab Ghosh     SegReq.Addr = AI.MappingBase + Segment.Offset;
3271b1f1c77SAnubhab Ghosh     SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
3281b1f1c77SAnubhab Ghosh 
3291b1f1c77SAnubhab Ghosh     FR.Segments.push_back(SegReq);
3301b1f1c77SAnubhab Ghosh   }
3311b1f1c77SAnubhab Ghosh 
3321b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3331b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>(
3341b1f1c77SAnubhab Ghosh       SAs.Initialize,
3351b1f1c77SAnubhab Ghosh       [OnInitialized = std::move(OnInitialized)](
3361b1f1c77SAnubhab Ghosh           Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
3371b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3381b1f1c77SAnubhab Ghosh           cantFail(Result.takeError());
3391b1f1c77SAnubhab Ghosh           return OnInitialized(std::move(SerializationErr));
3401b1f1c77SAnubhab Ghosh         }
3411b1f1c77SAnubhab Ghosh 
3421b1f1c77SAnubhab Ghosh         OnInitialized(std::move(Result));
3431b1f1c77SAnubhab Ghosh       },
3440ecfee0bSAnubhab Ghosh       SAs.Instance, Reservation->first, std::move(FR));
3451b1f1c77SAnubhab Ghosh }
3461b1f1c77SAnubhab Ghosh 
3471b1f1c77SAnubhab Ghosh void SharedMemoryMapper::deinitialize(
3481b1f1c77SAnubhab Ghosh     ArrayRef<ExecutorAddr> Allocations,
3491b1f1c77SAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
3501b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3511b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>(
3521b1f1c77SAnubhab Ghosh       SAs.Deinitialize,
3531b1f1c77SAnubhab Ghosh       [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
3541b1f1c77SAnubhab Ghosh                                                      Error Result) mutable {
3551b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3561b1f1c77SAnubhab Ghosh           cantFail(std::move(Result));
3571b1f1c77SAnubhab Ghosh           return OnDeinitialized(std::move(SerializationErr));
3581b1f1c77SAnubhab Ghosh         }
3591b1f1c77SAnubhab Ghosh 
3601b1f1c77SAnubhab Ghosh         OnDeinitialized(std::move(Result));
3611b1f1c77SAnubhab Ghosh       },
3621b1f1c77SAnubhab Ghosh       SAs.Instance, Allocations);
3631b1f1c77SAnubhab Ghosh }
3641b1f1c77SAnubhab Ghosh 
3651b1f1c77SAnubhab Ghosh void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
3661b1f1c77SAnubhab Ghosh                                  OnReleasedFunction OnReleased) {
367ac3cb4ecSAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
3681b1f1c77SAnubhab Ghosh   Error Err = Error::success();
3691b1f1c77SAnubhab Ghosh 
3701b1f1c77SAnubhab Ghosh   {
3711b1f1c77SAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
3721b1f1c77SAnubhab Ghosh 
3731b1f1c77SAnubhab Ghosh     for (auto Base : Bases) {
3741b1f1c77SAnubhab Ghosh 
3751b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX)
3761b1f1c77SAnubhab Ghosh 
3771b1f1c77SAnubhab Ghosh       if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0)
3781b1f1c77SAnubhab Ghosh         Err = joinErrors(std::move(Err), errorCodeToError(std::error_code(
3791b1f1c77SAnubhab Ghosh                                              errno, std::generic_category())));
3801b1f1c77SAnubhab Ghosh 
3811b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
3821b1f1c77SAnubhab Ghosh 
3831b1f1c77SAnubhab Ghosh       if (!UnmapViewOfFile(Reservations[Base].LocalAddr))
38446bc1b56SMartin Storsjö         Err = joinErrors(std::move(Err),
3851b1f1c77SAnubhab Ghosh                          errorCodeToError(mapWindowsError(GetLastError())));
3861b1f1c77SAnubhab Ghosh 
3871b1f1c77SAnubhab Ghosh #endif
3881b1f1c77SAnubhab Ghosh 
3891b1f1c77SAnubhab Ghosh       Reservations.erase(Base);
3901b1f1c77SAnubhab Ghosh     }
3911b1f1c77SAnubhab Ghosh   }
3921b1f1c77SAnubhab Ghosh 
3931b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3941b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>(
3951b1f1c77SAnubhab Ghosh       SAs.Release,
3961b1f1c77SAnubhab Ghosh       [OnReleased = std::move(OnReleased),
3971b1f1c77SAnubhab Ghosh        Err = std::move(Err)](Error SerializationErr, Error Result) mutable {
3981b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3991b1f1c77SAnubhab Ghosh           cantFail(std::move(Result));
4001b1f1c77SAnubhab Ghosh           return OnReleased(
4011b1f1c77SAnubhab Ghosh               joinErrors(std::move(Err), std::move(SerializationErr)));
4021b1f1c77SAnubhab Ghosh         }
4031b1f1c77SAnubhab Ghosh 
4041b1f1c77SAnubhab Ghosh         return OnReleased(joinErrors(std::move(Err), std::move(Result)));
4051b1f1c77SAnubhab Ghosh       },
4061b1f1c77SAnubhab Ghosh       SAs.Instance, Bases);
4071b1f1c77SAnubhab Ghosh #else
4081b1f1c77SAnubhab Ghosh   OnReleased(make_error<StringError>(
4091b1f1c77SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
4101b1f1c77SAnubhab Ghosh       inconvertibleErrorCode()));
4111b1f1c77SAnubhab Ghosh #endif
4121b1f1c77SAnubhab Ghosh }
4131b1f1c77SAnubhab Ghosh 
4141b1f1c77SAnubhab Ghosh SharedMemoryMapper::~SharedMemoryMapper() {
4151c25ce17SAlexandre Ganea   std::lock_guard<std::mutex> Lock(Mutex);
4163019f488SLang Hames   for (const auto &R : Reservations) {
4171b1f1c77SAnubhab Ghosh 
4181134d3a0SAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
4191134d3a0SAnubhab Ghosh 
4201134d3a0SAnubhab Ghosh     munmap(R.second.LocalAddr, R.second.Size);
4211134d3a0SAnubhab Ghosh 
4221134d3a0SAnubhab Ghosh #elif defined(_WIN32)
4231134d3a0SAnubhab Ghosh 
4241134d3a0SAnubhab Ghosh     UnmapViewOfFile(R.second.LocalAddr);
4251134d3a0SAnubhab Ghosh 
426*1c2ee6bdSDavid Blaikie #else
427*1c2ee6bdSDavid Blaikie 
428*1c2ee6bdSDavid Blaikie     (void)R;
429*1c2ee6bdSDavid Blaikie 
4301134d3a0SAnubhab Ghosh #endif
4311134d3a0SAnubhab Ghosh   }
4321b1f1c77SAnubhab Ghosh }
4331b1f1c77SAnubhab Ghosh 
43479fbee3cSAnubhab Ghosh } // namespace orc
43579fbee3cSAnubhab Ghosh 
43679fbee3cSAnubhab Ghosh } // namespace llvm
437