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 
14b3293305SAnubhab Ghosh #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
151b1f1c77SAnubhab Ghosh #include <fcntl.h>
161b1f1c77SAnubhab Ghosh #include <sys/mman.h>
171b1f1c77SAnubhab Ghosh #include <unistd.h>
181b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
191b1f1c77SAnubhab Ghosh #include <windows.h>
201b1f1c77SAnubhab Ghosh #endif
211b1f1c77SAnubhab Ghosh 
2279fbee3cSAnubhab Ghosh namespace llvm {
2379fbee3cSAnubhab Ghosh namespace orc {
2479fbee3cSAnubhab Ghosh 
~MemoryMapper()2579fbee3cSAnubhab Ghosh MemoryMapper::~MemoryMapper() {}
2679fbee3cSAnubhab Ghosh 
InProcessMemoryMapper(size_t PageSize)274fcf8434SAnubhab Ghosh InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize)
284fcf8434SAnubhab Ghosh     : PageSize(PageSize) {}
294fcf8434SAnubhab Ghosh 
304fcf8434SAnubhab Ghosh Expected<std::unique_ptr<InProcessMemoryMapper>>
Create()314fcf8434SAnubhab Ghosh InProcessMemoryMapper::Create() {
324fcf8434SAnubhab Ghosh   auto PageSize = sys::Process::getPageSize();
334fcf8434SAnubhab Ghosh   if (!PageSize)
344fcf8434SAnubhab Ghosh     return PageSize.takeError();
354fcf8434SAnubhab Ghosh   return std::make_unique<InProcessMemoryMapper>(*PageSize);
364fcf8434SAnubhab Ghosh }
374fcf8434SAnubhab Ghosh 
reserve(size_t NumBytes,OnReservedFunction OnReserved)3879fbee3cSAnubhab Ghosh void InProcessMemoryMapper::reserve(size_t NumBytes,
3979fbee3cSAnubhab Ghosh                                     OnReservedFunction OnReserved) {
4079fbee3cSAnubhab Ghosh   std::error_code EC;
4179fbee3cSAnubhab Ghosh   auto MB = sys::Memory::allocateMappedMemory(
4279fbee3cSAnubhab Ghosh       NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
4379fbee3cSAnubhab Ghosh 
4479fbee3cSAnubhab Ghosh   if (EC)
4579fbee3cSAnubhab Ghosh     return OnReserved(errorCodeToError(EC));
4679fbee3cSAnubhab Ghosh 
4779fbee3cSAnubhab Ghosh   {
4879fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
4979fbee3cSAnubhab Ghosh     Reservations[MB.base()].Size = MB.allocatedSize();
5079fbee3cSAnubhab Ghosh   }
5179fbee3cSAnubhab Ghosh 
5279fbee3cSAnubhab Ghosh   OnReserved(
5379fbee3cSAnubhab Ghosh       ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
5479fbee3cSAnubhab Ghosh }
5579fbee3cSAnubhab Ghosh 
prepare(ExecutorAddr Addr,size_t ContentSize)5679fbee3cSAnubhab Ghosh char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
5779fbee3cSAnubhab Ghosh   return Addr.toPtr<char *>();
5879fbee3cSAnubhab Ghosh }
5979fbee3cSAnubhab Ghosh 
initialize(MemoryMapper::AllocInfo & AI,OnInitializedFunction OnInitialized)6079fbee3cSAnubhab Ghosh void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
6179fbee3cSAnubhab Ghosh                                        OnInitializedFunction OnInitialized) {
6279fbee3cSAnubhab Ghosh   ExecutorAddr MinAddr(~0ULL);
6379fbee3cSAnubhab Ghosh 
6479fbee3cSAnubhab Ghosh   for (auto &Segment : AI.Segments) {
6579fbee3cSAnubhab Ghosh     auto Base = AI.MappingBase + Segment.Offset;
6679fbee3cSAnubhab Ghosh     auto Size = Segment.ContentSize + Segment.ZeroFillSize;
6779fbee3cSAnubhab Ghosh 
6879fbee3cSAnubhab Ghosh     if (Base < MinAddr)
6979fbee3cSAnubhab Ghosh       MinAddr = Base;
7079fbee3cSAnubhab Ghosh 
7179fbee3cSAnubhab Ghosh     std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
7279fbee3cSAnubhab Ghosh                 Segment.ZeroFillSize);
7379fbee3cSAnubhab Ghosh 
7479fbee3cSAnubhab Ghosh     if (auto EC = sys::Memory::protectMappedMemory({Base.toPtr<void *>(), Size},
7579fbee3cSAnubhab Ghosh                                                    Segment.Prot)) {
7679fbee3cSAnubhab Ghosh       return OnInitialized(errorCodeToError(EC));
7779fbee3cSAnubhab Ghosh     }
7879fbee3cSAnubhab Ghosh     if (Segment.Prot & sys::Memory::MF_EXEC)
7979fbee3cSAnubhab Ghosh       sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
8079fbee3cSAnubhab Ghosh   }
8179fbee3cSAnubhab Ghosh 
8279fbee3cSAnubhab Ghosh   auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
8379fbee3cSAnubhab Ghosh   if (!DeinitializeActions)
8479fbee3cSAnubhab Ghosh     return OnInitialized(DeinitializeActions.takeError());
8579fbee3cSAnubhab Ghosh 
8679fbee3cSAnubhab Ghosh   {
8779fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
8879fbee3cSAnubhab Ghosh     Allocations[MinAddr].DeinitializationActions =
8979fbee3cSAnubhab Ghosh         std::move(*DeinitializeActions);
9079fbee3cSAnubhab Ghosh     Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
9179fbee3cSAnubhab Ghosh   }
9279fbee3cSAnubhab Ghosh 
9379fbee3cSAnubhab Ghosh   OnInitialized(MinAddr);
9479fbee3cSAnubhab Ghosh }
9579fbee3cSAnubhab Ghosh 
deinitialize(ArrayRef<ExecutorAddr> Bases,MemoryMapper::OnDeinitializedFunction OnDeinitialized)9679fbee3cSAnubhab Ghosh void InProcessMemoryMapper::deinitialize(
9779fbee3cSAnubhab Ghosh     ArrayRef<ExecutorAddr> Bases,
9879fbee3cSAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
9979fbee3cSAnubhab Ghosh   Error AllErr = Error::success();
10079fbee3cSAnubhab Ghosh 
10179fbee3cSAnubhab Ghosh   {
10279fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
10379fbee3cSAnubhab Ghosh 
10479fbee3cSAnubhab Ghosh     for (auto Base : Bases) {
10579fbee3cSAnubhab Ghosh 
10679fbee3cSAnubhab Ghosh       if (Error Err = shared::runDeallocActions(
10779fbee3cSAnubhab Ghosh               Allocations[Base].DeinitializationActions)) {
10879fbee3cSAnubhab Ghosh         AllErr = joinErrors(std::move(AllErr), std::move(Err));
10979fbee3cSAnubhab Ghosh       }
11079fbee3cSAnubhab Ghosh 
11179fbee3cSAnubhab Ghosh       Allocations.erase(Base);
11279fbee3cSAnubhab Ghosh     }
11379fbee3cSAnubhab Ghosh   }
11479fbee3cSAnubhab Ghosh 
11579fbee3cSAnubhab Ghosh   OnDeinitialized(std::move(AllErr));
11679fbee3cSAnubhab Ghosh }
11779fbee3cSAnubhab Ghosh 
release(ArrayRef<ExecutorAddr> Bases,OnReleasedFunction OnReleased)11879fbee3cSAnubhab Ghosh void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
11979fbee3cSAnubhab Ghosh                                     OnReleasedFunction OnReleased) {
12079fbee3cSAnubhab Ghosh   Error Err = Error::success();
12179fbee3cSAnubhab Ghosh 
12279fbee3cSAnubhab Ghosh   for (auto Base : Bases) {
12379fbee3cSAnubhab Ghosh     std::vector<ExecutorAddr> AllocAddrs;
12479fbee3cSAnubhab Ghosh     size_t Size;
12579fbee3cSAnubhab Ghosh     {
12679fbee3cSAnubhab Ghosh       std::lock_guard<std::mutex> Lock(Mutex);
12779fbee3cSAnubhab Ghosh       auto &R = Reservations[Base.toPtr<void *>()];
12879fbee3cSAnubhab Ghosh       Size = R.Size;
12979fbee3cSAnubhab Ghosh       AllocAddrs.swap(R.Allocations);
13079fbee3cSAnubhab Ghosh     }
13179fbee3cSAnubhab Ghosh 
13279fbee3cSAnubhab Ghosh     // deinitialize sub allocations
13379fbee3cSAnubhab Ghosh     std::promise<MSVCPError> P;
13479fbee3cSAnubhab Ghosh     auto F = P.get_future();
13579fbee3cSAnubhab Ghosh     deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
13679fbee3cSAnubhab Ghosh     if (Error E = F.get()) {
13779fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), std::move(E));
13879fbee3cSAnubhab Ghosh     }
13979fbee3cSAnubhab Ghosh 
14079fbee3cSAnubhab Ghosh     // free the memory
14179fbee3cSAnubhab Ghosh     auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
14279fbee3cSAnubhab Ghosh 
14379fbee3cSAnubhab Ghosh     auto EC = sys::Memory::releaseMappedMemory(MB);
14479fbee3cSAnubhab Ghosh     if (EC) {
14579fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), errorCodeToError(EC));
14679fbee3cSAnubhab Ghosh     }
14779fbee3cSAnubhab Ghosh 
14879fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
14979fbee3cSAnubhab Ghosh     Reservations.erase(Base.toPtr<void *>());
15079fbee3cSAnubhab Ghosh   }
15179fbee3cSAnubhab Ghosh 
15279fbee3cSAnubhab Ghosh   OnReleased(std::move(Err));
15379fbee3cSAnubhab Ghosh }
15479fbee3cSAnubhab Ghosh 
~InProcessMemoryMapper()15579fbee3cSAnubhab Ghosh InProcessMemoryMapper::~InProcessMemoryMapper() {
15679fbee3cSAnubhab Ghosh   std::vector<ExecutorAddr> ReservationAddrs;
15779fbee3cSAnubhab Ghosh   {
15879fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
15979fbee3cSAnubhab Ghosh 
16079fbee3cSAnubhab Ghosh     ReservationAddrs.reserve(Reservations.size());
16179fbee3cSAnubhab Ghosh     for (const auto &R : Reservations) {
16279fbee3cSAnubhab Ghosh       ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
16379fbee3cSAnubhab Ghosh     }
16479fbee3cSAnubhab Ghosh   }
16579fbee3cSAnubhab Ghosh 
16679fbee3cSAnubhab Ghosh   std::promise<MSVCPError> P;
16779fbee3cSAnubhab Ghosh   auto F = P.get_future();
16879fbee3cSAnubhab Ghosh   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
16979fbee3cSAnubhab Ghosh   cantFail(F.get());
17079fbee3cSAnubhab Ghosh }
17179fbee3cSAnubhab Ghosh 
1721b1f1c77SAnubhab Ghosh // SharedMemoryMapper
1731b1f1c77SAnubhab Ghosh 
SharedMemoryMapper(ExecutorProcessControl & EPC,SymbolAddrs SAs,size_t PageSize)1744fcf8434SAnubhab Ghosh SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC,
1754fcf8434SAnubhab Ghosh                                        SymbolAddrs SAs, size_t PageSize)
176b3293305SAnubhab Ghosh     : EPC(EPC), SAs(SAs), PageSize(PageSize) {
177b3293305SAnubhab Ghosh #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32)
178b3293305SAnubhab Ghosh   llvm_unreachable("SharedMemoryMapper is not supported on this platform yet");
179b3293305SAnubhab Ghosh #endif
180b3293305SAnubhab Ghosh }
1814fcf8434SAnubhab Ghosh 
1824fcf8434SAnubhab Ghosh Expected<std::unique_ptr<SharedMemoryMapper>>
Create(ExecutorProcessControl & EPC,SymbolAddrs SAs)1834fcf8434SAnubhab Ghosh SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
184b3293305SAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
1854fcf8434SAnubhab Ghosh   auto PageSize = sys::Process::getPageSize();
1864fcf8434SAnubhab Ghosh   if (!PageSize)
1874fcf8434SAnubhab Ghosh     return PageSize.takeError();
1884fcf8434SAnubhab Ghosh 
1894fcf8434SAnubhab Ghosh   return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
190b3293305SAnubhab Ghosh #else
191b3293305SAnubhab Ghosh   return make_error<StringError>(
192b3293305SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
193b3293305SAnubhab Ghosh       inconvertibleErrorCode());
194b3293305SAnubhab Ghosh #endif
1954fcf8434SAnubhab Ghosh }
1964fcf8434SAnubhab Ghosh 
reserve(size_t NumBytes,OnReservedFunction OnReserved)1971b1f1c77SAnubhab Ghosh void SharedMemoryMapper::reserve(size_t NumBytes,
1981b1f1c77SAnubhab Ghosh                                  OnReservedFunction OnReserved) {
199b3293305SAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2001b1f1c77SAnubhab Ghosh 
2011b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
2021b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>(
2031b1f1c77SAnubhab Ghosh       SAs.Reserve,
2041b1f1c77SAnubhab Ghosh       [this, NumBytes, OnReserved = std::move(OnReserved)](
2051b1f1c77SAnubhab Ghosh           Error SerializationErr,
2061b1f1c77SAnubhab Ghosh           Expected<std::pair<ExecutorAddr, std::string>> Result) mutable {
2071b1f1c77SAnubhab Ghosh         if (SerializationErr) {
2081b1f1c77SAnubhab Ghosh           cantFail(Result.takeError());
2091b1f1c77SAnubhab Ghosh           return OnReserved(std::move(SerializationErr));
2101b1f1c77SAnubhab Ghosh         }
2111b1f1c77SAnubhab Ghosh 
2121b1f1c77SAnubhab Ghosh         if (!Result)
2131b1f1c77SAnubhab Ghosh           return OnReserved(Result.takeError());
2141b1f1c77SAnubhab Ghosh 
2151b1f1c77SAnubhab Ghosh         ExecutorAddr RemoteAddr;
2161b1f1c77SAnubhab Ghosh         std::string SharedMemoryName;
2171b1f1c77SAnubhab Ghosh         std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result);
2181b1f1c77SAnubhab Ghosh 
2191b1f1c77SAnubhab Ghosh         void *LocalAddr = nullptr;
2201b1f1c77SAnubhab Ghosh 
2211b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX)
2221b1f1c77SAnubhab Ghosh 
2231b1f1c77SAnubhab Ghosh         int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
2241b1f1c77SAnubhab Ghosh         if (SharedMemoryFile < 0) {
2251b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(
2261b1f1c77SAnubhab Ghosh               std::error_code(errno, std::generic_category())));
2271b1f1c77SAnubhab Ghosh         }
2281b1f1c77SAnubhab Ghosh 
2291b1f1c77SAnubhab Ghosh         // this prevents other processes from accessing it by name
2301b1f1c77SAnubhab Ghosh         shm_unlink(SharedMemoryName.c_str());
2311b1f1c77SAnubhab Ghosh 
2321b1f1c77SAnubhab Ghosh         LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
2331b1f1c77SAnubhab Ghosh                          SharedMemoryFile, 0);
2341b1f1c77SAnubhab Ghosh         if (LocalAddr == MAP_FAILED) {
2351b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(
2361b1f1c77SAnubhab Ghosh               std::error_code(errno, std::generic_category())));
2371b1f1c77SAnubhab Ghosh         }
2381b1f1c77SAnubhab Ghosh 
2391b1f1c77SAnubhab Ghosh         close(SharedMemoryFile);
2401b1f1c77SAnubhab Ghosh 
2411b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
2421b1f1c77SAnubhab Ghosh 
2431b1f1c77SAnubhab Ghosh         std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
2441b1f1c77SAnubhab Ghosh                                           SharedMemoryName.end());
2451b1f1c77SAnubhab Ghosh         HANDLE SharedMemoryFile = OpenFileMappingW(
2461b1f1c77SAnubhab Ghosh             FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
2471b1f1c77SAnubhab Ghosh         if (!SharedMemoryFile)
2481b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2491b1f1c77SAnubhab Ghosh 
2501b1f1c77SAnubhab Ghosh         LocalAddr =
2511b1f1c77SAnubhab Ghosh             MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
2521b1f1c77SAnubhab Ghosh         if (!LocalAddr) {
2531b1f1c77SAnubhab Ghosh           CloseHandle(SharedMemoryFile);
2541b1f1c77SAnubhab Ghosh           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2551b1f1c77SAnubhab Ghosh         }
2561b1f1c77SAnubhab Ghosh 
2571b1f1c77SAnubhab Ghosh         CloseHandle(SharedMemoryFile);
2581b1f1c77SAnubhab Ghosh 
2591b1f1c77SAnubhab Ghosh #endif
2601b1f1c77SAnubhab Ghosh         {
2611b1f1c77SAnubhab Ghosh           std::lock_guard<std::mutex> Lock(Mutex);
2621b1f1c77SAnubhab Ghosh           Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
2631b1f1c77SAnubhab Ghosh         }
2641b1f1c77SAnubhab Ghosh 
2651b1f1c77SAnubhab Ghosh         OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes));
2661b1f1c77SAnubhab Ghosh       },
2671b1f1c77SAnubhab Ghosh       SAs.Instance, static_cast<uint64_t>(NumBytes));
2681b1f1c77SAnubhab Ghosh 
2691b1f1c77SAnubhab Ghosh #else
2701b1f1c77SAnubhab Ghosh   OnReserved(make_error<StringError>(
2711b1f1c77SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
2721b1f1c77SAnubhab Ghosh       inconvertibleErrorCode()));
2731b1f1c77SAnubhab Ghosh #endif
2741b1f1c77SAnubhab Ghosh }
2751b1f1c77SAnubhab Ghosh 
prepare(ExecutorAddr Addr,size_t ContentSize)2761b1f1c77SAnubhab Ghosh char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
2771b1f1c77SAnubhab Ghosh   auto R = Reservations.upper_bound(Addr);
2781b1f1c77SAnubhab Ghosh   assert(R != Reservations.begin() && "Attempt to prepare unknown range");
2791b1f1c77SAnubhab Ghosh   R--;
2801b1f1c77SAnubhab Ghosh 
2811b1f1c77SAnubhab Ghosh   ExecutorAddrDiff Offset = Addr - R->first;
2821b1f1c77SAnubhab Ghosh 
2831b1f1c77SAnubhab Ghosh   return static_cast<char *>(R->second.LocalAddr) + Offset;
2841b1f1c77SAnubhab Ghosh }
2851b1f1c77SAnubhab Ghosh 
initialize(MemoryMapper::AllocInfo & AI,OnInitializedFunction OnInitialized)2861b1f1c77SAnubhab Ghosh void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
2871b1f1c77SAnubhab Ghosh                                     OnInitializedFunction OnInitialized) {
2881b1f1c77SAnubhab Ghosh   auto Reservation = Reservations.find(AI.MappingBase);
2891b1f1c77SAnubhab Ghosh   assert(Reservation != Reservations.end() &&
2901b1f1c77SAnubhab Ghosh          "Attempt to initialize unreserved range");
2911b1f1c77SAnubhab Ghosh 
2921b1f1c77SAnubhab Ghosh   tpctypes::SharedMemoryFinalizeRequest FR;
2931b1f1c77SAnubhab Ghosh 
2941b1f1c77SAnubhab Ghosh   AI.Actions.swap(FR.Actions);
2951b1f1c77SAnubhab Ghosh 
2961b1f1c77SAnubhab Ghosh   FR.Segments.reserve(AI.Segments.size());
2971b1f1c77SAnubhab Ghosh 
2981b1f1c77SAnubhab Ghosh   for (auto Segment : AI.Segments) {
2991b1f1c77SAnubhab Ghosh     char *Base =
3001b1f1c77SAnubhab Ghosh         static_cast<char *>(Reservation->second.LocalAddr) + Segment.Offset;
3011b1f1c77SAnubhab Ghosh     std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
3021b1f1c77SAnubhab Ghosh 
3031b1f1c77SAnubhab Ghosh     tpctypes::SharedMemorySegFinalizeRequest SegReq;
3041b1f1c77SAnubhab Ghosh     SegReq.Prot = tpctypes::toWireProtectionFlags(
3051b1f1c77SAnubhab Ghosh         static_cast<sys::Memory::ProtectionFlags>(Segment.Prot));
3061b1f1c77SAnubhab Ghosh     SegReq.Addr = AI.MappingBase + Segment.Offset;
3071b1f1c77SAnubhab Ghosh     SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
3081b1f1c77SAnubhab Ghosh 
3091b1f1c77SAnubhab Ghosh     FR.Segments.push_back(SegReq);
3101b1f1c77SAnubhab Ghosh   }
3111b1f1c77SAnubhab Ghosh 
3121b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3131b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>(
3141b1f1c77SAnubhab Ghosh       SAs.Initialize,
3151b1f1c77SAnubhab Ghosh       [OnInitialized = std::move(OnInitialized)](
3161b1f1c77SAnubhab Ghosh           Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
3171b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3181b1f1c77SAnubhab Ghosh           cantFail(Result.takeError());
3191b1f1c77SAnubhab Ghosh           return OnInitialized(std::move(SerializationErr));
3201b1f1c77SAnubhab Ghosh         }
3211b1f1c77SAnubhab Ghosh 
3221b1f1c77SAnubhab Ghosh         OnInitialized(std::move(Result));
3231b1f1c77SAnubhab Ghosh       },
3241b1f1c77SAnubhab Ghosh       SAs.Instance, AI.MappingBase, std::move(FR));
3251b1f1c77SAnubhab Ghosh }
3261b1f1c77SAnubhab Ghosh 
deinitialize(ArrayRef<ExecutorAddr> Allocations,MemoryMapper::OnDeinitializedFunction OnDeinitialized)3271b1f1c77SAnubhab Ghosh void SharedMemoryMapper::deinitialize(
3281b1f1c77SAnubhab Ghosh     ArrayRef<ExecutorAddr> Allocations,
3291b1f1c77SAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
3301b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3311b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>(
3321b1f1c77SAnubhab Ghosh       SAs.Deinitialize,
3331b1f1c77SAnubhab Ghosh       [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
3341b1f1c77SAnubhab Ghosh                                                      Error Result) mutable {
3351b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3361b1f1c77SAnubhab Ghosh           cantFail(std::move(Result));
3371b1f1c77SAnubhab Ghosh           return OnDeinitialized(std::move(SerializationErr));
3381b1f1c77SAnubhab Ghosh         }
3391b1f1c77SAnubhab Ghosh 
3401b1f1c77SAnubhab Ghosh         OnDeinitialized(std::move(Result));
3411b1f1c77SAnubhab Ghosh       },
3421b1f1c77SAnubhab Ghosh       SAs.Instance, Allocations);
3431b1f1c77SAnubhab Ghosh }
3441b1f1c77SAnubhab Ghosh 
release(ArrayRef<ExecutorAddr> Bases,OnReleasedFunction OnReleased)3451b1f1c77SAnubhab Ghosh void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
3461b1f1c77SAnubhab Ghosh                                  OnReleasedFunction OnReleased) {
347b3293305SAnubhab Ghosh #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
3481b1f1c77SAnubhab Ghosh   Error Err = Error::success();
3491b1f1c77SAnubhab Ghosh 
3501b1f1c77SAnubhab Ghosh   {
3511b1f1c77SAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
3521b1f1c77SAnubhab Ghosh 
3531b1f1c77SAnubhab Ghosh     for (auto Base : Bases) {
3541b1f1c77SAnubhab Ghosh 
3551b1f1c77SAnubhab Ghosh #if defined(LLVM_ON_UNIX)
3561b1f1c77SAnubhab Ghosh 
3571b1f1c77SAnubhab Ghosh       if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0)
3581b1f1c77SAnubhab Ghosh         Err = joinErrors(std::move(Err), errorCodeToError(std::error_code(
3591b1f1c77SAnubhab Ghosh                                              errno, std::generic_category())));
3601b1f1c77SAnubhab Ghosh 
3611b1f1c77SAnubhab Ghosh #elif defined(_WIN32)
3621b1f1c77SAnubhab Ghosh 
3631b1f1c77SAnubhab Ghosh       if (!UnmapViewOfFile(Reservations[Base].LocalAddr))
364*bf956104SMartin Storsjö         Err = joinErrors(std::move(Err),
3651b1f1c77SAnubhab Ghosh                          errorCodeToError(mapWindowsError(GetLastError())));
3661b1f1c77SAnubhab Ghosh 
3671b1f1c77SAnubhab Ghosh #endif
3681b1f1c77SAnubhab Ghosh 
3691b1f1c77SAnubhab Ghosh       Reservations.erase(Base);
3701b1f1c77SAnubhab Ghosh     }
3711b1f1c77SAnubhab Ghosh   }
3721b1f1c77SAnubhab Ghosh 
3731b1f1c77SAnubhab Ghosh   EPC.callSPSWrapperAsync<
3741b1f1c77SAnubhab Ghosh       rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>(
3751b1f1c77SAnubhab Ghosh       SAs.Release,
3761b1f1c77SAnubhab Ghosh       [OnReleased = std::move(OnReleased),
3771b1f1c77SAnubhab Ghosh        Err = std::move(Err)](Error SerializationErr, Error Result) mutable {
3781b1f1c77SAnubhab Ghosh         if (SerializationErr) {
3791b1f1c77SAnubhab Ghosh           cantFail(std::move(Result));
3801b1f1c77SAnubhab Ghosh           return OnReleased(
3811b1f1c77SAnubhab Ghosh               joinErrors(std::move(Err), std::move(SerializationErr)));
3821b1f1c77SAnubhab Ghosh         }
3831b1f1c77SAnubhab Ghosh 
3841b1f1c77SAnubhab Ghosh         return OnReleased(joinErrors(std::move(Err), std::move(Result)));
3851b1f1c77SAnubhab Ghosh       },
3861b1f1c77SAnubhab Ghosh       SAs.Instance, Bases);
3871b1f1c77SAnubhab Ghosh #else
3881b1f1c77SAnubhab Ghosh   OnReleased(make_error<StringError>(
3891b1f1c77SAnubhab Ghosh       "SharedMemoryMapper is not supported on this platform yet",
3901b1f1c77SAnubhab Ghosh       inconvertibleErrorCode()));
3911b1f1c77SAnubhab Ghosh #endif
3921b1f1c77SAnubhab Ghosh }
3931b1f1c77SAnubhab Ghosh 
~SharedMemoryMapper()3941b1f1c77SAnubhab Ghosh SharedMemoryMapper::~SharedMemoryMapper() {
3951b1f1c77SAnubhab Ghosh   std::vector<ExecutorAddr> ReservationAddrs;
3961b1f1c77SAnubhab Ghosh   if (!Reservations.empty()) {
3971b1f1c77SAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
3981b1f1c77SAnubhab Ghosh     {
3991b1f1c77SAnubhab Ghosh       ReservationAddrs.reserve(Reservations.size());
4001b1f1c77SAnubhab Ghosh       for (const auto &R : Reservations) {
4011b1f1c77SAnubhab Ghosh         ReservationAddrs.push_back(R.first);
4021b1f1c77SAnubhab Ghosh       }
4031b1f1c77SAnubhab Ghosh     }
4041b1f1c77SAnubhab Ghosh   }
4051b1f1c77SAnubhab Ghosh 
4061b1f1c77SAnubhab Ghosh   std::promise<MSVCPError> P;
4071b1f1c77SAnubhab Ghosh   auto F = P.get_future();
4081b1f1c77SAnubhab Ghosh   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
4091b1f1c77SAnubhab Ghosh   // FIXME: Release can actually fail. The error should be propagated.
4101b1f1c77SAnubhab Ghosh   // Meanwhile, a better option is to explicitly call release().
4111b1f1c77SAnubhab Ghosh   cantFail(F.get());
4121b1f1c77SAnubhab Ghosh }
4131b1f1c77SAnubhab Ghosh 
41479fbee3cSAnubhab Ghosh } // namespace orc
41579fbee3cSAnubhab Ghosh 
41679fbee3cSAnubhab Ghosh } // namespace llvm
417