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