xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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