1145449b1SDimitry Andric //===- MemoryMapper.cpp - Cross-process memory mapper ------------*- C++ -*-==//
2145449b1SDimitry Andric //
3145449b1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4145449b1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5145449b1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6145449b1SDimitry Andric //
7145449b1SDimitry Andric //===----------------------------------------------------------------------===//
8145449b1SDimitry Andric
9145449b1SDimitry Andric #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
10145449b1SDimitry Andric
114b4fe385SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
124b4fe385SDimitry Andric #include "llvm/Support/WindowsError.h"
134b4fe385SDimitry Andric
14e3b55780SDimitry Andric #include <algorithm>
15e3b55780SDimitry Andric
16e3b55780SDimitry Andric #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
174b4fe385SDimitry Andric #include <fcntl.h>
184b4fe385SDimitry Andric #include <sys/mman.h>
19ac9a064cSDimitry Andric #if defined(__MVS__)
20ac9a064cSDimitry Andric #include "llvm/Support/BLAKE3.h"
21ac9a064cSDimitry Andric #include <sys/shm.h>
22ac9a064cSDimitry Andric #endif
234b4fe385SDimitry Andric #include <unistd.h>
244b4fe385SDimitry Andric #elif defined(_WIN32)
254b4fe385SDimitry Andric #include <windows.h>
264b4fe385SDimitry Andric #endif
274b4fe385SDimitry Andric
28145449b1SDimitry Andric namespace llvm {
29145449b1SDimitry Andric namespace orc {
30145449b1SDimitry Andric
~MemoryMapper()31145449b1SDimitry Andric MemoryMapper::~MemoryMapper() {}
32145449b1SDimitry Andric
InProcessMemoryMapper(size_t PageSize)334b4fe385SDimitry Andric InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize)
344b4fe385SDimitry Andric : PageSize(PageSize) {}
354b4fe385SDimitry Andric
364b4fe385SDimitry Andric Expected<std::unique_ptr<InProcessMemoryMapper>>
Create()374b4fe385SDimitry Andric InProcessMemoryMapper::Create() {
384b4fe385SDimitry Andric auto PageSize = sys::Process::getPageSize();
394b4fe385SDimitry Andric if (!PageSize)
404b4fe385SDimitry Andric return PageSize.takeError();
414b4fe385SDimitry Andric return std::make_unique<InProcessMemoryMapper>(*PageSize);
424b4fe385SDimitry Andric }
434b4fe385SDimitry Andric
reserve(size_t NumBytes,OnReservedFunction OnReserved)44145449b1SDimitry Andric void InProcessMemoryMapper::reserve(size_t NumBytes,
45145449b1SDimitry Andric OnReservedFunction OnReserved) {
46145449b1SDimitry Andric std::error_code EC;
47145449b1SDimitry Andric auto MB = sys::Memory::allocateMappedMemory(
48145449b1SDimitry Andric NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
49145449b1SDimitry Andric
50145449b1SDimitry Andric if (EC)
51145449b1SDimitry Andric return OnReserved(errorCodeToError(EC));
52145449b1SDimitry Andric
53145449b1SDimitry Andric {
54145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
55145449b1SDimitry Andric Reservations[MB.base()].Size = MB.allocatedSize();
56145449b1SDimitry Andric }
57145449b1SDimitry Andric
58145449b1SDimitry Andric OnReserved(
59145449b1SDimitry Andric ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
60145449b1SDimitry Andric }
61145449b1SDimitry Andric
prepare(ExecutorAddr Addr,size_t ContentSize)62145449b1SDimitry Andric char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
63145449b1SDimitry Andric return Addr.toPtr<char *>();
64145449b1SDimitry Andric }
65145449b1SDimitry Andric
initialize(MemoryMapper::AllocInfo & AI,OnInitializedFunction OnInitialized)66145449b1SDimitry Andric void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
67145449b1SDimitry Andric OnInitializedFunction OnInitialized) {
68145449b1SDimitry Andric ExecutorAddr MinAddr(~0ULL);
69e3b55780SDimitry Andric ExecutorAddr MaxAddr(0);
70145449b1SDimitry Andric
71e3b55780SDimitry Andric // FIXME: Release finalize lifetime segments.
72145449b1SDimitry Andric for (auto &Segment : AI.Segments) {
73145449b1SDimitry Andric auto Base = AI.MappingBase + Segment.Offset;
74145449b1SDimitry Andric auto Size = Segment.ContentSize + Segment.ZeroFillSize;
75145449b1SDimitry Andric
76145449b1SDimitry Andric if (Base < MinAddr)
77145449b1SDimitry Andric MinAddr = Base;
78145449b1SDimitry Andric
79e3b55780SDimitry Andric if (Base + Size > MaxAddr)
80e3b55780SDimitry Andric MaxAddr = Base + Size;
81e3b55780SDimitry Andric
82145449b1SDimitry Andric std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
83145449b1SDimitry Andric Segment.ZeroFillSize);
84145449b1SDimitry Andric
85e3b55780SDimitry Andric if (auto EC = sys::Memory::protectMappedMemory(
86e3b55780SDimitry Andric {Base.toPtr<void *>(), Size},
87e3b55780SDimitry Andric toSysMemoryProtectionFlags(Segment.AG.getMemProt()))) {
88145449b1SDimitry Andric return OnInitialized(errorCodeToError(EC));
89145449b1SDimitry Andric }
90e3b55780SDimitry Andric if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
91145449b1SDimitry Andric sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
92145449b1SDimitry Andric }
93145449b1SDimitry Andric
94145449b1SDimitry Andric auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
95145449b1SDimitry Andric if (!DeinitializeActions)
96145449b1SDimitry Andric return OnInitialized(DeinitializeActions.takeError());
97145449b1SDimitry Andric
98145449b1SDimitry Andric {
99145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
100e3b55780SDimitry Andric
101e3b55780SDimitry Andric // This is the maximum range whose permission have been possibly modified
102e3b55780SDimitry Andric Allocations[MinAddr].Size = MaxAddr - MinAddr;
103145449b1SDimitry Andric Allocations[MinAddr].DeinitializationActions =
104145449b1SDimitry Andric std::move(*DeinitializeActions);
105145449b1SDimitry Andric Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
106145449b1SDimitry Andric }
107145449b1SDimitry Andric
108145449b1SDimitry Andric OnInitialized(MinAddr);
109145449b1SDimitry Andric }
110145449b1SDimitry Andric
deinitialize(ArrayRef<ExecutorAddr> Bases,MemoryMapper::OnDeinitializedFunction OnDeinitialized)111145449b1SDimitry Andric void InProcessMemoryMapper::deinitialize(
112145449b1SDimitry Andric ArrayRef<ExecutorAddr> Bases,
113145449b1SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
114145449b1SDimitry Andric Error AllErr = Error::success();
115145449b1SDimitry Andric
116145449b1SDimitry Andric {
117145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
118145449b1SDimitry Andric
119e3b55780SDimitry Andric for (auto Base : llvm::reverse(Bases)) {
120145449b1SDimitry Andric
121145449b1SDimitry Andric if (Error Err = shared::runDeallocActions(
122145449b1SDimitry Andric Allocations[Base].DeinitializationActions)) {
123145449b1SDimitry Andric AllErr = joinErrors(std::move(AllErr), std::move(Err));
124145449b1SDimitry Andric }
125145449b1SDimitry Andric
126e3b55780SDimitry Andric // Reset protections to read/write so the area can be reused
127e3b55780SDimitry Andric if (auto EC = sys::Memory::protectMappedMemory(
128e3b55780SDimitry Andric {Base.toPtr<void *>(), Allocations[Base].Size},
129e3b55780SDimitry Andric sys::Memory::ProtectionFlags::MF_READ |
130e3b55780SDimitry Andric sys::Memory::ProtectionFlags::MF_WRITE)) {
131e3b55780SDimitry Andric AllErr = joinErrors(std::move(AllErr), errorCodeToError(EC));
132e3b55780SDimitry Andric }
133e3b55780SDimitry Andric
134145449b1SDimitry Andric Allocations.erase(Base);
135145449b1SDimitry Andric }
136145449b1SDimitry Andric }
137145449b1SDimitry Andric
138145449b1SDimitry Andric OnDeinitialized(std::move(AllErr));
139145449b1SDimitry Andric }
140145449b1SDimitry Andric
release(ArrayRef<ExecutorAddr> Bases,OnReleasedFunction OnReleased)141145449b1SDimitry Andric void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
142145449b1SDimitry Andric OnReleasedFunction OnReleased) {
143145449b1SDimitry Andric Error Err = Error::success();
144145449b1SDimitry Andric
145145449b1SDimitry Andric for (auto Base : Bases) {
146145449b1SDimitry Andric std::vector<ExecutorAddr> AllocAddrs;
147145449b1SDimitry Andric size_t Size;
148145449b1SDimitry Andric {
149145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
150145449b1SDimitry Andric auto &R = Reservations[Base.toPtr<void *>()];
151145449b1SDimitry Andric Size = R.Size;
152145449b1SDimitry Andric AllocAddrs.swap(R.Allocations);
153145449b1SDimitry Andric }
154145449b1SDimitry Andric
155145449b1SDimitry Andric // deinitialize sub allocations
156145449b1SDimitry Andric std::promise<MSVCPError> P;
157145449b1SDimitry Andric auto F = P.get_future();
158145449b1SDimitry Andric deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
159145449b1SDimitry Andric if (Error E = F.get()) {
160145449b1SDimitry Andric Err = joinErrors(std::move(Err), std::move(E));
161145449b1SDimitry Andric }
162145449b1SDimitry Andric
163145449b1SDimitry Andric // free the memory
164145449b1SDimitry Andric auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
165145449b1SDimitry Andric
166145449b1SDimitry Andric auto EC = sys::Memory::releaseMappedMemory(MB);
167145449b1SDimitry Andric if (EC) {
168145449b1SDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(EC));
169145449b1SDimitry Andric }
170145449b1SDimitry Andric
171145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
172145449b1SDimitry Andric Reservations.erase(Base.toPtr<void *>());
173145449b1SDimitry Andric }
174145449b1SDimitry Andric
175145449b1SDimitry Andric OnReleased(std::move(Err));
176145449b1SDimitry Andric }
177145449b1SDimitry Andric
~InProcessMemoryMapper()178145449b1SDimitry Andric InProcessMemoryMapper::~InProcessMemoryMapper() {
179145449b1SDimitry Andric std::vector<ExecutorAddr> ReservationAddrs;
180145449b1SDimitry Andric {
181145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
182145449b1SDimitry Andric
183145449b1SDimitry Andric ReservationAddrs.reserve(Reservations.size());
184145449b1SDimitry Andric for (const auto &R : Reservations) {
185145449b1SDimitry Andric ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
186145449b1SDimitry Andric }
187145449b1SDimitry Andric }
188145449b1SDimitry Andric
189145449b1SDimitry Andric std::promise<MSVCPError> P;
190145449b1SDimitry Andric auto F = P.get_future();
191145449b1SDimitry Andric release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
192145449b1SDimitry Andric cantFail(F.get());
193145449b1SDimitry Andric }
194145449b1SDimitry Andric
1954b4fe385SDimitry Andric // SharedMemoryMapper
1964b4fe385SDimitry Andric
SharedMemoryMapper(ExecutorProcessControl & EPC,SymbolAddrs SAs,size_t PageSize)1974b4fe385SDimitry Andric SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC,
1984b4fe385SDimitry Andric SymbolAddrs SAs, size_t PageSize)
199e3b55780SDimitry Andric : EPC(EPC), SAs(SAs), PageSize(PageSize) {
200e3b55780SDimitry Andric #if (!defined(LLVM_ON_UNIX) || defined(__ANDROID__)) && !defined(_WIN32)
201e3b55780SDimitry Andric llvm_unreachable("SharedMemoryMapper is not supported on this platform yet");
202e3b55780SDimitry Andric #endif
203e3b55780SDimitry Andric }
2044b4fe385SDimitry Andric
2054b4fe385SDimitry Andric Expected<std::unique_ptr<SharedMemoryMapper>>
Create(ExecutorProcessControl & EPC,SymbolAddrs SAs)2064b4fe385SDimitry Andric SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
207e3b55780SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2084b4fe385SDimitry Andric auto PageSize = sys::Process::getPageSize();
2094b4fe385SDimitry Andric if (!PageSize)
2104b4fe385SDimitry Andric return PageSize.takeError();
2114b4fe385SDimitry Andric
2124b4fe385SDimitry Andric return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
213e3b55780SDimitry Andric #else
214e3b55780SDimitry Andric return make_error<StringError>(
215e3b55780SDimitry Andric "SharedMemoryMapper is not supported on this platform yet",
216e3b55780SDimitry Andric inconvertibleErrorCode());
217e3b55780SDimitry Andric #endif
2184b4fe385SDimitry Andric }
2194b4fe385SDimitry Andric
reserve(size_t NumBytes,OnReservedFunction OnReserved)2204b4fe385SDimitry Andric void SharedMemoryMapper::reserve(size_t NumBytes,
2214b4fe385SDimitry Andric OnReservedFunction OnReserved) {
222e3b55780SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
2234b4fe385SDimitry Andric
2244b4fe385SDimitry Andric EPC.callSPSWrapperAsync<
2254b4fe385SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>(
2264b4fe385SDimitry Andric SAs.Reserve,
2274b4fe385SDimitry Andric [this, NumBytes, OnReserved = std::move(OnReserved)](
2284b4fe385SDimitry Andric Error SerializationErr,
2294b4fe385SDimitry Andric Expected<std::pair<ExecutorAddr, std::string>> Result) mutable {
2304b4fe385SDimitry Andric if (SerializationErr) {
2314b4fe385SDimitry Andric cantFail(Result.takeError());
2324b4fe385SDimitry Andric return OnReserved(std::move(SerializationErr));
2334b4fe385SDimitry Andric }
2344b4fe385SDimitry Andric
2354b4fe385SDimitry Andric if (!Result)
2364b4fe385SDimitry Andric return OnReserved(Result.takeError());
2374b4fe385SDimitry Andric
2384b4fe385SDimitry Andric ExecutorAddr RemoteAddr;
2394b4fe385SDimitry Andric std::string SharedMemoryName;
2404b4fe385SDimitry Andric std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result);
2414b4fe385SDimitry Andric
2424b4fe385SDimitry Andric void *LocalAddr = nullptr;
2434b4fe385SDimitry Andric
2444b4fe385SDimitry Andric #if defined(LLVM_ON_UNIX)
2454b4fe385SDimitry Andric
246ac9a064cSDimitry Andric #if defined(__MVS__)
247ac9a064cSDimitry Andric ArrayRef<uint8_t> Data(
248ac9a064cSDimitry Andric reinterpret_cast<const uint8_t *>(SharedMemoryName.c_str()),
249ac9a064cSDimitry Andric SharedMemoryName.size());
250ac9a064cSDimitry Andric auto HashedName = BLAKE3::hash<sizeof(key_t)>(Data);
251ac9a064cSDimitry Andric key_t Key = *reinterpret_cast<key_t *>(HashedName.data());
252ac9a064cSDimitry Andric int SharedMemoryId =
253ac9a064cSDimitry Andric shmget(Key, NumBytes, IPC_CREAT | __IPC_SHAREAS | 0700);
254ac9a064cSDimitry Andric if (SharedMemoryId < 0) {
2554b4fe385SDimitry Andric return OnReserved(errorCodeToError(
2564b4fe385SDimitry Andric std::error_code(errno, std::generic_category())));
2574b4fe385SDimitry Andric }
258ac9a064cSDimitry Andric LocalAddr = shmat(SharedMemoryId, nullptr, 0);
259ac9a064cSDimitry Andric if (LocalAddr == reinterpret_cast<void *>(-1)) {
260ac9a064cSDimitry Andric return OnReserved(errorCodeToError(
261ac9a064cSDimitry Andric std::error_code(errno, std::generic_category())));
262ac9a064cSDimitry Andric }
263ac9a064cSDimitry Andric #else
264ac9a064cSDimitry Andric int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
265ac9a064cSDimitry Andric if (SharedMemoryFile < 0) {
266ac9a064cSDimitry Andric return OnReserved(errorCodeToError(errnoAsErrorCode()));
267ac9a064cSDimitry Andric }
2684b4fe385SDimitry Andric
2694b4fe385SDimitry Andric // this prevents other processes from accessing it by name
2704b4fe385SDimitry Andric shm_unlink(SharedMemoryName.c_str());
2714b4fe385SDimitry Andric
2724b4fe385SDimitry Andric LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
2734b4fe385SDimitry Andric SharedMemoryFile, 0);
2744b4fe385SDimitry Andric if (LocalAddr == MAP_FAILED) {
275ac9a064cSDimitry Andric return OnReserved(errorCodeToError(errnoAsErrorCode()));
2764b4fe385SDimitry Andric }
2774b4fe385SDimitry Andric
2784b4fe385SDimitry Andric close(SharedMemoryFile);
279ac9a064cSDimitry Andric #endif
2804b4fe385SDimitry Andric
2814b4fe385SDimitry Andric #elif defined(_WIN32)
2824b4fe385SDimitry Andric
2834b4fe385SDimitry Andric std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
2844b4fe385SDimitry Andric SharedMemoryName.end());
2854b4fe385SDimitry Andric HANDLE SharedMemoryFile = OpenFileMappingW(
2864b4fe385SDimitry Andric FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
2874b4fe385SDimitry Andric if (!SharedMemoryFile)
2884b4fe385SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2894b4fe385SDimitry Andric
2904b4fe385SDimitry Andric LocalAddr =
2914b4fe385SDimitry Andric MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
2924b4fe385SDimitry Andric if (!LocalAddr) {
2934b4fe385SDimitry Andric CloseHandle(SharedMemoryFile);
2944b4fe385SDimitry Andric return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
2954b4fe385SDimitry Andric }
2964b4fe385SDimitry Andric
2974b4fe385SDimitry Andric CloseHandle(SharedMemoryFile);
2984b4fe385SDimitry Andric
2994b4fe385SDimitry Andric #endif
3004b4fe385SDimitry Andric {
3014b4fe385SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
3024b4fe385SDimitry Andric Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
3034b4fe385SDimitry Andric }
3044b4fe385SDimitry Andric
3054b4fe385SDimitry Andric OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes));
3064b4fe385SDimitry Andric },
3074b4fe385SDimitry Andric SAs.Instance, static_cast<uint64_t>(NumBytes));
3084b4fe385SDimitry Andric
3094b4fe385SDimitry Andric #else
3104b4fe385SDimitry Andric OnReserved(make_error<StringError>(
3114b4fe385SDimitry Andric "SharedMemoryMapper is not supported on this platform yet",
3124b4fe385SDimitry Andric inconvertibleErrorCode()));
3134b4fe385SDimitry Andric #endif
3144b4fe385SDimitry Andric }
3154b4fe385SDimitry Andric
prepare(ExecutorAddr Addr,size_t ContentSize)3164b4fe385SDimitry Andric char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
3174b4fe385SDimitry Andric auto R = Reservations.upper_bound(Addr);
318e3b55780SDimitry Andric assert(R != Reservations.begin() && "Attempt to prepare unreserved range");
3194b4fe385SDimitry Andric R--;
3204b4fe385SDimitry Andric
3214b4fe385SDimitry Andric ExecutorAddrDiff Offset = Addr - R->first;
3224b4fe385SDimitry Andric
3234b4fe385SDimitry Andric return static_cast<char *>(R->second.LocalAddr) + Offset;
3244b4fe385SDimitry Andric }
3254b4fe385SDimitry Andric
initialize(MemoryMapper::AllocInfo & AI,OnInitializedFunction OnInitialized)3264b4fe385SDimitry Andric void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
3274b4fe385SDimitry Andric OnInitializedFunction OnInitialized) {
328e3b55780SDimitry Andric auto Reservation = Reservations.upper_bound(AI.MappingBase);
329e3b55780SDimitry Andric assert(Reservation != Reservations.begin() && "Attempt to initialize unreserved range");
330e3b55780SDimitry Andric Reservation--;
331e3b55780SDimitry Andric
332e3b55780SDimitry Andric auto AllocationOffset = AI.MappingBase - Reservation->first;
3334b4fe385SDimitry Andric
3344b4fe385SDimitry Andric tpctypes::SharedMemoryFinalizeRequest FR;
3354b4fe385SDimitry Andric
3364b4fe385SDimitry Andric AI.Actions.swap(FR.Actions);
3374b4fe385SDimitry Andric
3384b4fe385SDimitry Andric FR.Segments.reserve(AI.Segments.size());
3394b4fe385SDimitry Andric
3404b4fe385SDimitry Andric for (auto Segment : AI.Segments) {
341e3b55780SDimitry Andric char *Base = static_cast<char *>(Reservation->second.LocalAddr) +
342e3b55780SDimitry Andric AllocationOffset + Segment.Offset;
3434b4fe385SDimitry Andric std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
3444b4fe385SDimitry Andric
3454b4fe385SDimitry Andric tpctypes::SharedMemorySegFinalizeRequest SegReq;
346b1c73532SDimitry Andric SegReq.RAG = {Segment.AG.getMemProt(),
347b1c73532SDimitry Andric Segment.AG.getMemLifetime() == MemLifetime::Finalize};
3484b4fe385SDimitry Andric SegReq.Addr = AI.MappingBase + Segment.Offset;
3494b4fe385SDimitry Andric SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
3504b4fe385SDimitry Andric
3514b4fe385SDimitry Andric FR.Segments.push_back(SegReq);
3524b4fe385SDimitry Andric }
3534b4fe385SDimitry Andric
3544b4fe385SDimitry Andric EPC.callSPSWrapperAsync<
3554b4fe385SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>(
3564b4fe385SDimitry Andric SAs.Initialize,
3574b4fe385SDimitry Andric [OnInitialized = std::move(OnInitialized)](
3584b4fe385SDimitry Andric Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
3594b4fe385SDimitry Andric if (SerializationErr) {
3604b4fe385SDimitry Andric cantFail(Result.takeError());
3614b4fe385SDimitry Andric return OnInitialized(std::move(SerializationErr));
3624b4fe385SDimitry Andric }
3634b4fe385SDimitry Andric
3644b4fe385SDimitry Andric OnInitialized(std::move(Result));
3654b4fe385SDimitry Andric },
366e3b55780SDimitry Andric SAs.Instance, Reservation->first, std::move(FR));
3674b4fe385SDimitry Andric }
3684b4fe385SDimitry Andric
deinitialize(ArrayRef<ExecutorAddr> Allocations,MemoryMapper::OnDeinitializedFunction OnDeinitialized)3694b4fe385SDimitry Andric void SharedMemoryMapper::deinitialize(
3704b4fe385SDimitry Andric ArrayRef<ExecutorAddr> Allocations,
3714b4fe385SDimitry Andric MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
3724b4fe385SDimitry Andric EPC.callSPSWrapperAsync<
3734b4fe385SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>(
3744b4fe385SDimitry Andric SAs.Deinitialize,
3754b4fe385SDimitry Andric [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
3764b4fe385SDimitry Andric Error Result) mutable {
3774b4fe385SDimitry Andric if (SerializationErr) {
3784b4fe385SDimitry Andric cantFail(std::move(Result));
3794b4fe385SDimitry Andric return OnDeinitialized(std::move(SerializationErr));
3804b4fe385SDimitry Andric }
3814b4fe385SDimitry Andric
3824b4fe385SDimitry Andric OnDeinitialized(std::move(Result));
3834b4fe385SDimitry Andric },
3844b4fe385SDimitry Andric SAs.Instance, Allocations);
3854b4fe385SDimitry Andric }
3864b4fe385SDimitry Andric
release(ArrayRef<ExecutorAddr> Bases,OnReleasedFunction OnReleased)3874b4fe385SDimitry Andric void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
3884b4fe385SDimitry Andric OnReleasedFunction OnReleased) {
389e3b55780SDimitry Andric #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
3904b4fe385SDimitry Andric Error Err = Error::success();
3914b4fe385SDimitry Andric
3924b4fe385SDimitry Andric {
3934b4fe385SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
3944b4fe385SDimitry Andric
3954b4fe385SDimitry Andric for (auto Base : Bases) {
3964b4fe385SDimitry Andric
3974b4fe385SDimitry Andric #if defined(LLVM_ON_UNIX)
3984b4fe385SDimitry Andric
399ac9a064cSDimitry Andric #if defined(__MVS__)
400ac9a064cSDimitry Andric if (shmdt(Reservations[Base].LocalAddr) < 0)
401ac9a064cSDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode()));
402ac9a064cSDimitry Andric #else
4034b4fe385SDimitry Andric if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0)
404ac9a064cSDimitry Andric Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode()));
405ac9a064cSDimitry Andric #endif
4064b4fe385SDimitry Andric
4074b4fe385SDimitry Andric #elif defined(_WIN32)
4084b4fe385SDimitry Andric
4094b4fe385SDimitry Andric if (!UnmapViewOfFile(Reservations[Base].LocalAddr))
410e3b55780SDimitry Andric Err = joinErrors(std::move(Err),
4114b4fe385SDimitry Andric errorCodeToError(mapWindowsError(GetLastError())));
4124b4fe385SDimitry Andric
4134b4fe385SDimitry Andric #endif
4144b4fe385SDimitry Andric
4154b4fe385SDimitry Andric Reservations.erase(Base);
4164b4fe385SDimitry Andric }
4174b4fe385SDimitry Andric }
4184b4fe385SDimitry Andric
4194b4fe385SDimitry Andric EPC.callSPSWrapperAsync<
4204b4fe385SDimitry Andric rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>(
4214b4fe385SDimitry Andric SAs.Release,
4224b4fe385SDimitry Andric [OnReleased = std::move(OnReleased),
4234b4fe385SDimitry Andric Err = std::move(Err)](Error SerializationErr, Error Result) mutable {
4244b4fe385SDimitry Andric if (SerializationErr) {
4254b4fe385SDimitry Andric cantFail(std::move(Result));
4264b4fe385SDimitry Andric return OnReleased(
4274b4fe385SDimitry Andric joinErrors(std::move(Err), std::move(SerializationErr)));
4284b4fe385SDimitry Andric }
4294b4fe385SDimitry Andric
4304b4fe385SDimitry Andric return OnReleased(joinErrors(std::move(Err), std::move(Result)));
4314b4fe385SDimitry Andric },
4324b4fe385SDimitry Andric SAs.Instance, Bases);
4334b4fe385SDimitry Andric #else
4344b4fe385SDimitry Andric OnReleased(make_error<StringError>(
4354b4fe385SDimitry Andric "SharedMemoryMapper is not supported on this platform yet",
4364b4fe385SDimitry Andric inconvertibleErrorCode()));
4374b4fe385SDimitry Andric #endif
4384b4fe385SDimitry Andric }
4394b4fe385SDimitry Andric
~SharedMemoryMapper()4404b4fe385SDimitry Andric SharedMemoryMapper::~SharedMemoryMapper() {
4414b4fe385SDimitry Andric std::lock_guard<std::mutex> Lock(Mutex);
4424b4fe385SDimitry Andric for (const auto &R : Reservations) {
4434b4fe385SDimitry Andric
444e3b55780SDimitry Andric #if defined(LLVM_ON_UNIX) && !defined(__ANDROID__)
445e3b55780SDimitry Andric
446ac9a064cSDimitry Andric #if defined(__MVS__)
447ac9a064cSDimitry Andric shmdt(R.second.LocalAddr);
448ac9a064cSDimitry Andric #else
449e3b55780SDimitry Andric munmap(R.second.LocalAddr, R.second.Size);
450ac9a064cSDimitry Andric #endif
451e3b55780SDimitry Andric
452e3b55780SDimitry Andric #elif defined(_WIN32)
453e3b55780SDimitry Andric
454e3b55780SDimitry Andric UnmapViewOfFile(R.second.LocalAddr);
455e3b55780SDimitry Andric
456e3b55780SDimitry Andric #else
457e3b55780SDimitry Andric
458e3b55780SDimitry Andric (void)R;
459e3b55780SDimitry Andric
460e3b55780SDimitry Andric #endif
461e3b55780SDimitry Andric }
4624b4fe385SDimitry Andric }
4634b4fe385SDimitry Andric
464145449b1SDimitry Andric } // namespace orc
465145449b1SDimitry Andric
466145449b1SDimitry Andric } // namespace llvm
467