xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
181ad6265SDimitry Andric //===- MemoryMapper.cpp - Cross-process memory mapper ------------*- C++ -*-==//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
1081ad6265SDimitry Andric 
11*fcaf7f86SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12*fcaf7f86SDimitry Andric #include "llvm/Support/WindowsError.h"
13*fcaf7f86SDimitry Andric 
14*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX)
15*fcaf7f86SDimitry Andric #include <fcntl.h>
16*fcaf7f86SDimitry Andric #include <sys/mman.h>
17*fcaf7f86SDimitry Andric #include <unistd.h>
18*fcaf7f86SDimitry Andric #elif defined(_WIN32)
19*fcaf7f86SDimitry Andric #include <windows.h>
20*fcaf7f86SDimitry Andric #endif
21*fcaf7f86SDimitry Andric 
2281ad6265SDimitry Andric namespace llvm {
2381ad6265SDimitry Andric namespace orc {
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric MemoryMapper::~MemoryMapper() {}
2681ad6265SDimitry Andric 
27*fcaf7f86SDimitry Andric InProcessMemoryMapper::InProcessMemoryMapper(size_t PageSize)
28*fcaf7f86SDimitry Andric     : PageSize(PageSize) {}
29*fcaf7f86SDimitry Andric 
30*fcaf7f86SDimitry Andric Expected<std::unique_ptr<InProcessMemoryMapper>>
31*fcaf7f86SDimitry Andric InProcessMemoryMapper::Create() {
32*fcaf7f86SDimitry Andric   auto PageSize = sys::Process::getPageSize();
33*fcaf7f86SDimitry Andric   if (!PageSize)
34*fcaf7f86SDimitry Andric     return PageSize.takeError();
35*fcaf7f86SDimitry Andric   return std::make_unique<InProcessMemoryMapper>(*PageSize);
36*fcaf7f86SDimitry Andric }
37*fcaf7f86SDimitry Andric 
3881ad6265SDimitry Andric void InProcessMemoryMapper::reserve(size_t NumBytes,
3981ad6265SDimitry Andric                                     OnReservedFunction OnReserved) {
4081ad6265SDimitry Andric   std::error_code EC;
4181ad6265SDimitry Andric   auto MB = sys::Memory::allocateMappedMemory(
4281ad6265SDimitry Andric       NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
4381ad6265SDimitry Andric 
4481ad6265SDimitry Andric   if (EC)
4581ad6265SDimitry Andric     return OnReserved(errorCodeToError(EC));
4681ad6265SDimitry Andric 
4781ad6265SDimitry Andric   {
4881ad6265SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
4981ad6265SDimitry Andric     Reservations[MB.base()].Size = MB.allocatedSize();
5081ad6265SDimitry Andric   }
5181ad6265SDimitry Andric 
5281ad6265SDimitry Andric   OnReserved(
5381ad6265SDimitry Andric       ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
5481ad6265SDimitry Andric }
5581ad6265SDimitry Andric 
5681ad6265SDimitry Andric char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
5781ad6265SDimitry Andric   return Addr.toPtr<char *>();
5881ad6265SDimitry Andric }
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
6181ad6265SDimitry Andric                                        OnInitializedFunction OnInitialized) {
6281ad6265SDimitry Andric   ExecutorAddr MinAddr(~0ULL);
6381ad6265SDimitry Andric 
6481ad6265SDimitry Andric   for (auto &Segment : AI.Segments) {
6581ad6265SDimitry Andric     auto Base = AI.MappingBase + Segment.Offset;
6681ad6265SDimitry Andric     auto Size = Segment.ContentSize + Segment.ZeroFillSize;
6781ad6265SDimitry Andric 
6881ad6265SDimitry Andric     if (Base < MinAddr)
6981ad6265SDimitry Andric       MinAddr = Base;
7081ad6265SDimitry Andric 
7181ad6265SDimitry Andric     std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
7281ad6265SDimitry Andric                 Segment.ZeroFillSize);
7381ad6265SDimitry Andric 
7481ad6265SDimitry Andric     if (auto EC = sys::Memory::protectMappedMemory({Base.toPtr<void *>(), Size},
7581ad6265SDimitry Andric                                                    Segment.Prot)) {
7681ad6265SDimitry Andric       return OnInitialized(errorCodeToError(EC));
7781ad6265SDimitry Andric     }
7881ad6265SDimitry Andric     if (Segment.Prot & sys::Memory::MF_EXEC)
7981ad6265SDimitry Andric       sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
8081ad6265SDimitry Andric   }
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric   auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
8381ad6265SDimitry Andric   if (!DeinitializeActions)
8481ad6265SDimitry Andric     return OnInitialized(DeinitializeActions.takeError());
8581ad6265SDimitry Andric 
8681ad6265SDimitry Andric   {
8781ad6265SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
8881ad6265SDimitry Andric     Allocations[MinAddr].DeinitializationActions =
8981ad6265SDimitry Andric         std::move(*DeinitializeActions);
9081ad6265SDimitry Andric     Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
9181ad6265SDimitry Andric   }
9281ad6265SDimitry Andric 
9381ad6265SDimitry Andric   OnInitialized(MinAddr);
9481ad6265SDimitry Andric }
9581ad6265SDimitry Andric 
9681ad6265SDimitry Andric void InProcessMemoryMapper::deinitialize(
9781ad6265SDimitry Andric     ArrayRef<ExecutorAddr> Bases,
9881ad6265SDimitry Andric     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
9981ad6265SDimitry Andric   Error AllErr = Error::success();
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric   {
10281ad6265SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
10381ad6265SDimitry Andric 
10481ad6265SDimitry Andric     for (auto Base : Bases) {
10581ad6265SDimitry Andric 
10681ad6265SDimitry Andric       if (Error Err = shared::runDeallocActions(
10781ad6265SDimitry Andric               Allocations[Base].DeinitializationActions)) {
10881ad6265SDimitry Andric         AllErr = joinErrors(std::move(AllErr), std::move(Err));
10981ad6265SDimitry Andric       }
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric       Allocations.erase(Base);
11281ad6265SDimitry Andric     }
11381ad6265SDimitry Andric   }
11481ad6265SDimitry Andric 
11581ad6265SDimitry Andric   OnDeinitialized(std::move(AllErr));
11681ad6265SDimitry Andric }
11781ad6265SDimitry Andric 
11881ad6265SDimitry Andric void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
11981ad6265SDimitry Andric                                     OnReleasedFunction OnReleased) {
12081ad6265SDimitry Andric   Error Err = Error::success();
12181ad6265SDimitry Andric 
12281ad6265SDimitry Andric   for (auto Base : Bases) {
12381ad6265SDimitry Andric     std::vector<ExecutorAddr> AllocAddrs;
12481ad6265SDimitry Andric     size_t Size;
12581ad6265SDimitry Andric     {
12681ad6265SDimitry Andric       std::lock_guard<std::mutex> Lock(Mutex);
12781ad6265SDimitry Andric       auto &R = Reservations[Base.toPtr<void *>()];
12881ad6265SDimitry Andric       Size = R.Size;
12981ad6265SDimitry Andric       AllocAddrs.swap(R.Allocations);
13081ad6265SDimitry Andric     }
13181ad6265SDimitry Andric 
13281ad6265SDimitry Andric     // deinitialize sub allocations
13381ad6265SDimitry Andric     std::promise<MSVCPError> P;
13481ad6265SDimitry Andric     auto F = P.get_future();
13581ad6265SDimitry Andric     deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
13681ad6265SDimitry Andric     if (Error E = F.get()) {
13781ad6265SDimitry Andric       Err = joinErrors(std::move(Err), std::move(E));
13881ad6265SDimitry Andric     }
13981ad6265SDimitry Andric 
14081ad6265SDimitry Andric     // free the memory
14181ad6265SDimitry Andric     auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
14281ad6265SDimitry Andric 
14381ad6265SDimitry Andric     auto EC = sys::Memory::releaseMappedMemory(MB);
14481ad6265SDimitry Andric     if (EC) {
14581ad6265SDimitry Andric       Err = joinErrors(std::move(Err), errorCodeToError(EC));
14681ad6265SDimitry Andric     }
14781ad6265SDimitry Andric 
14881ad6265SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
14981ad6265SDimitry Andric     Reservations.erase(Base.toPtr<void *>());
15081ad6265SDimitry Andric   }
15181ad6265SDimitry Andric 
15281ad6265SDimitry Andric   OnReleased(std::move(Err));
15381ad6265SDimitry Andric }
15481ad6265SDimitry Andric 
15581ad6265SDimitry Andric InProcessMemoryMapper::~InProcessMemoryMapper() {
15681ad6265SDimitry Andric   std::vector<ExecutorAddr> ReservationAddrs;
15781ad6265SDimitry Andric   {
15881ad6265SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
15981ad6265SDimitry Andric 
16081ad6265SDimitry Andric     ReservationAddrs.reserve(Reservations.size());
16181ad6265SDimitry Andric     for (const auto &R : Reservations) {
16281ad6265SDimitry Andric       ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
16381ad6265SDimitry Andric     }
16481ad6265SDimitry Andric   }
16581ad6265SDimitry Andric 
16681ad6265SDimitry Andric   std::promise<MSVCPError> P;
16781ad6265SDimitry Andric   auto F = P.get_future();
16881ad6265SDimitry Andric   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
16981ad6265SDimitry Andric   cantFail(F.get());
17081ad6265SDimitry Andric }
17181ad6265SDimitry Andric 
172*fcaf7f86SDimitry Andric // SharedMemoryMapper
173*fcaf7f86SDimitry Andric 
174*fcaf7f86SDimitry Andric SharedMemoryMapper::SharedMemoryMapper(ExecutorProcessControl &EPC,
175*fcaf7f86SDimitry Andric                                        SymbolAddrs SAs, size_t PageSize)
176*fcaf7f86SDimitry Andric     : EPC(EPC), SAs(SAs), PageSize(PageSize) {}
177*fcaf7f86SDimitry Andric 
178*fcaf7f86SDimitry Andric Expected<std::unique_ptr<SharedMemoryMapper>>
179*fcaf7f86SDimitry Andric SharedMemoryMapper::Create(ExecutorProcessControl &EPC, SymbolAddrs SAs) {
180*fcaf7f86SDimitry Andric   auto PageSize = sys::Process::getPageSize();
181*fcaf7f86SDimitry Andric   if (!PageSize)
182*fcaf7f86SDimitry Andric     return PageSize.takeError();
183*fcaf7f86SDimitry Andric 
184*fcaf7f86SDimitry Andric   return std::make_unique<SharedMemoryMapper>(EPC, SAs, *PageSize);
185*fcaf7f86SDimitry Andric }
186*fcaf7f86SDimitry Andric 
187*fcaf7f86SDimitry Andric void SharedMemoryMapper::reserve(size_t NumBytes,
188*fcaf7f86SDimitry Andric                                  OnReservedFunction OnReserved) {
189*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) || defined(_WIN32)
190*fcaf7f86SDimitry Andric 
191*fcaf7f86SDimitry Andric   EPC.callSPSWrapperAsync<
192*fcaf7f86SDimitry Andric       rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>(
193*fcaf7f86SDimitry Andric       SAs.Reserve,
194*fcaf7f86SDimitry Andric       [this, NumBytes, OnReserved = std::move(OnReserved)](
195*fcaf7f86SDimitry Andric           Error SerializationErr,
196*fcaf7f86SDimitry Andric           Expected<std::pair<ExecutorAddr, std::string>> Result) mutable {
197*fcaf7f86SDimitry Andric         if (SerializationErr) {
198*fcaf7f86SDimitry Andric           cantFail(Result.takeError());
199*fcaf7f86SDimitry Andric           return OnReserved(std::move(SerializationErr));
200*fcaf7f86SDimitry Andric         }
201*fcaf7f86SDimitry Andric 
202*fcaf7f86SDimitry Andric         if (!Result)
203*fcaf7f86SDimitry Andric           return OnReserved(Result.takeError());
204*fcaf7f86SDimitry Andric 
205*fcaf7f86SDimitry Andric         ExecutorAddr RemoteAddr;
206*fcaf7f86SDimitry Andric         std::string SharedMemoryName;
207*fcaf7f86SDimitry Andric         std::tie(RemoteAddr, SharedMemoryName) = std::move(*Result);
208*fcaf7f86SDimitry Andric 
209*fcaf7f86SDimitry Andric         void *LocalAddr = nullptr;
210*fcaf7f86SDimitry Andric 
211*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX)
212*fcaf7f86SDimitry Andric 
213*fcaf7f86SDimitry Andric         int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700);
214*fcaf7f86SDimitry Andric         if (SharedMemoryFile < 0) {
215*fcaf7f86SDimitry Andric           return OnReserved(errorCodeToError(
216*fcaf7f86SDimitry Andric               std::error_code(errno, std::generic_category())));
217*fcaf7f86SDimitry Andric         }
218*fcaf7f86SDimitry Andric 
219*fcaf7f86SDimitry Andric         // this prevents other processes from accessing it by name
220*fcaf7f86SDimitry Andric         shm_unlink(SharedMemoryName.c_str());
221*fcaf7f86SDimitry Andric 
222*fcaf7f86SDimitry Andric         LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
223*fcaf7f86SDimitry Andric                          SharedMemoryFile, 0);
224*fcaf7f86SDimitry Andric         if (LocalAddr == MAP_FAILED) {
225*fcaf7f86SDimitry Andric           return OnReserved(errorCodeToError(
226*fcaf7f86SDimitry Andric               std::error_code(errno, std::generic_category())));
227*fcaf7f86SDimitry Andric         }
228*fcaf7f86SDimitry Andric 
229*fcaf7f86SDimitry Andric         close(SharedMemoryFile);
230*fcaf7f86SDimitry Andric 
231*fcaf7f86SDimitry Andric #elif defined(_WIN32)
232*fcaf7f86SDimitry Andric 
233*fcaf7f86SDimitry Andric         std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
234*fcaf7f86SDimitry Andric                                           SharedMemoryName.end());
235*fcaf7f86SDimitry Andric         HANDLE SharedMemoryFile = OpenFileMappingW(
236*fcaf7f86SDimitry Andric             FILE_MAP_ALL_ACCESS, FALSE, WideSharedMemoryName.c_str());
237*fcaf7f86SDimitry Andric         if (!SharedMemoryFile)
238*fcaf7f86SDimitry Andric           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
239*fcaf7f86SDimitry Andric 
240*fcaf7f86SDimitry Andric         LocalAddr =
241*fcaf7f86SDimitry Andric             MapViewOfFile(SharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
242*fcaf7f86SDimitry Andric         if (!LocalAddr) {
243*fcaf7f86SDimitry Andric           CloseHandle(SharedMemoryFile);
244*fcaf7f86SDimitry Andric           return OnReserved(errorCodeToError(mapWindowsError(GetLastError())));
245*fcaf7f86SDimitry Andric         }
246*fcaf7f86SDimitry Andric 
247*fcaf7f86SDimitry Andric         CloseHandle(SharedMemoryFile);
248*fcaf7f86SDimitry Andric 
249*fcaf7f86SDimitry Andric #endif
250*fcaf7f86SDimitry Andric         {
251*fcaf7f86SDimitry Andric           std::lock_guard<std::mutex> Lock(Mutex);
252*fcaf7f86SDimitry Andric           Reservations.insert({RemoteAddr, {LocalAddr, NumBytes}});
253*fcaf7f86SDimitry Andric         }
254*fcaf7f86SDimitry Andric 
255*fcaf7f86SDimitry Andric         OnReserved(ExecutorAddrRange(RemoteAddr, NumBytes));
256*fcaf7f86SDimitry Andric       },
257*fcaf7f86SDimitry Andric       SAs.Instance, static_cast<uint64_t>(NumBytes));
258*fcaf7f86SDimitry Andric 
259*fcaf7f86SDimitry Andric #else
260*fcaf7f86SDimitry Andric   OnReserved(make_error<StringError>(
261*fcaf7f86SDimitry Andric       "SharedMemoryMapper is not supported on this platform yet",
262*fcaf7f86SDimitry Andric       inconvertibleErrorCode()));
263*fcaf7f86SDimitry Andric #endif
264*fcaf7f86SDimitry Andric }
265*fcaf7f86SDimitry Andric 
266*fcaf7f86SDimitry Andric char *SharedMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
267*fcaf7f86SDimitry Andric   auto R = Reservations.upper_bound(Addr);
268*fcaf7f86SDimitry Andric   assert(R != Reservations.begin() && "Attempt to prepare unknown range");
269*fcaf7f86SDimitry Andric   R--;
270*fcaf7f86SDimitry Andric 
271*fcaf7f86SDimitry Andric   ExecutorAddrDiff Offset = Addr - R->first;
272*fcaf7f86SDimitry Andric 
273*fcaf7f86SDimitry Andric   return static_cast<char *>(R->second.LocalAddr) + Offset;
274*fcaf7f86SDimitry Andric }
275*fcaf7f86SDimitry Andric 
276*fcaf7f86SDimitry Andric void SharedMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
277*fcaf7f86SDimitry Andric                                     OnInitializedFunction OnInitialized) {
278*fcaf7f86SDimitry Andric   auto Reservation = Reservations.find(AI.MappingBase);
279*fcaf7f86SDimitry Andric   assert(Reservation != Reservations.end() &&
280*fcaf7f86SDimitry Andric          "Attempt to initialize unreserved range");
281*fcaf7f86SDimitry Andric 
282*fcaf7f86SDimitry Andric   tpctypes::SharedMemoryFinalizeRequest FR;
283*fcaf7f86SDimitry Andric 
284*fcaf7f86SDimitry Andric   AI.Actions.swap(FR.Actions);
285*fcaf7f86SDimitry Andric 
286*fcaf7f86SDimitry Andric   FR.Segments.reserve(AI.Segments.size());
287*fcaf7f86SDimitry Andric 
288*fcaf7f86SDimitry Andric   for (auto Segment : AI.Segments) {
289*fcaf7f86SDimitry Andric     char *Base =
290*fcaf7f86SDimitry Andric         static_cast<char *>(Reservation->second.LocalAddr) + Segment.Offset;
291*fcaf7f86SDimitry Andric     std::memset(Base + Segment.ContentSize, 0, Segment.ZeroFillSize);
292*fcaf7f86SDimitry Andric 
293*fcaf7f86SDimitry Andric     tpctypes::SharedMemorySegFinalizeRequest SegReq;
294*fcaf7f86SDimitry Andric     SegReq.Prot = tpctypes::toWireProtectionFlags(
295*fcaf7f86SDimitry Andric         static_cast<sys::Memory::ProtectionFlags>(Segment.Prot));
296*fcaf7f86SDimitry Andric     SegReq.Addr = AI.MappingBase + Segment.Offset;
297*fcaf7f86SDimitry Andric     SegReq.Size = Segment.ContentSize + Segment.ZeroFillSize;
298*fcaf7f86SDimitry Andric 
299*fcaf7f86SDimitry Andric     FR.Segments.push_back(SegReq);
300*fcaf7f86SDimitry Andric   }
301*fcaf7f86SDimitry Andric 
302*fcaf7f86SDimitry Andric   EPC.callSPSWrapperAsync<
303*fcaf7f86SDimitry Andric       rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>(
304*fcaf7f86SDimitry Andric       SAs.Initialize,
305*fcaf7f86SDimitry Andric       [OnInitialized = std::move(OnInitialized)](
306*fcaf7f86SDimitry Andric           Error SerializationErr, Expected<ExecutorAddr> Result) mutable {
307*fcaf7f86SDimitry Andric         if (SerializationErr) {
308*fcaf7f86SDimitry Andric           cantFail(Result.takeError());
309*fcaf7f86SDimitry Andric           return OnInitialized(std::move(SerializationErr));
310*fcaf7f86SDimitry Andric         }
311*fcaf7f86SDimitry Andric 
312*fcaf7f86SDimitry Andric         OnInitialized(std::move(Result));
313*fcaf7f86SDimitry Andric       },
314*fcaf7f86SDimitry Andric       SAs.Instance, AI.MappingBase, std::move(FR));
315*fcaf7f86SDimitry Andric }
316*fcaf7f86SDimitry Andric 
317*fcaf7f86SDimitry Andric void SharedMemoryMapper::deinitialize(
318*fcaf7f86SDimitry Andric     ArrayRef<ExecutorAddr> Allocations,
319*fcaf7f86SDimitry Andric     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
320*fcaf7f86SDimitry Andric   EPC.callSPSWrapperAsync<
321*fcaf7f86SDimitry Andric       rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>(
322*fcaf7f86SDimitry Andric       SAs.Deinitialize,
323*fcaf7f86SDimitry Andric       [OnDeinitialized = std::move(OnDeinitialized)](Error SerializationErr,
324*fcaf7f86SDimitry Andric                                                      Error Result) mutable {
325*fcaf7f86SDimitry Andric         if (SerializationErr) {
326*fcaf7f86SDimitry Andric           cantFail(std::move(Result));
327*fcaf7f86SDimitry Andric           return OnDeinitialized(std::move(SerializationErr));
328*fcaf7f86SDimitry Andric         }
329*fcaf7f86SDimitry Andric 
330*fcaf7f86SDimitry Andric         OnDeinitialized(std::move(Result));
331*fcaf7f86SDimitry Andric       },
332*fcaf7f86SDimitry Andric       SAs.Instance, Allocations);
333*fcaf7f86SDimitry Andric }
334*fcaf7f86SDimitry Andric 
335*fcaf7f86SDimitry Andric void SharedMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
336*fcaf7f86SDimitry Andric                                  OnReleasedFunction OnReleased) {
337*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX) || defined(_WIN32)
338*fcaf7f86SDimitry Andric   Error Err = Error::success();
339*fcaf7f86SDimitry Andric 
340*fcaf7f86SDimitry Andric   {
341*fcaf7f86SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
342*fcaf7f86SDimitry Andric 
343*fcaf7f86SDimitry Andric     for (auto Base : Bases) {
344*fcaf7f86SDimitry Andric 
345*fcaf7f86SDimitry Andric #if defined(LLVM_ON_UNIX)
346*fcaf7f86SDimitry Andric 
347*fcaf7f86SDimitry Andric       if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0)
348*fcaf7f86SDimitry Andric         Err = joinErrors(std::move(Err), errorCodeToError(std::error_code(
349*fcaf7f86SDimitry Andric                                              errno, std::generic_category())));
350*fcaf7f86SDimitry Andric 
351*fcaf7f86SDimitry Andric #elif defined(_WIN32)
352*fcaf7f86SDimitry Andric 
353*fcaf7f86SDimitry Andric       if (!UnmapViewOfFile(Reservations[Base].LocalAddr))
354*fcaf7f86SDimitry Andric         joinErrors(std::move(Err),
355*fcaf7f86SDimitry Andric                    errorCodeToError(mapWindowsError(GetLastError())));
356*fcaf7f86SDimitry Andric 
357*fcaf7f86SDimitry Andric #endif
358*fcaf7f86SDimitry Andric 
359*fcaf7f86SDimitry Andric       Reservations.erase(Base);
360*fcaf7f86SDimitry Andric     }
361*fcaf7f86SDimitry Andric   }
362*fcaf7f86SDimitry Andric 
363*fcaf7f86SDimitry Andric   EPC.callSPSWrapperAsync<
364*fcaf7f86SDimitry Andric       rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>(
365*fcaf7f86SDimitry Andric       SAs.Release,
366*fcaf7f86SDimitry Andric       [OnReleased = std::move(OnReleased),
367*fcaf7f86SDimitry Andric        Err = std::move(Err)](Error SerializationErr, Error Result) mutable {
368*fcaf7f86SDimitry Andric         if (SerializationErr) {
369*fcaf7f86SDimitry Andric           cantFail(std::move(Result));
370*fcaf7f86SDimitry Andric           return OnReleased(
371*fcaf7f86SDimitry Andric               joinErrors(std::move(Err), std::move(SerializationErr)));
372*fcaf7f86SDimitry Andric         }
373*fcaf7f86SDimitry Andric 
374*fcaf7f86SDimitry Andric         return OnReleased(joinErrors(std::move(Err), std::move(Result)));
375*fcaf7f86SDimitry Andric       },
376*fcaf7f86SDimitry Andric       SAs.Instance, Bases);
377*fcaf7f86SDimitry Andric #else
378*fcaf7f86SDimitry Andric   OnReleased(make_error<StringError>(
379*fcaf7f86SDimitry Andric       "SharedMemoryMapper is not supported on this platform yet",
380*fcaf7f86SDimitry Andric       inconvertibleErrorCode()));
381*fcaf7f86SDimitry Andric #endif
382*fcaf7f86SDimitry Andric }
383*fcaf7f86SDimitry Andric 
384*fcaf7f86SDimitry Andric SharedMemoryMapper::~SharedMemoryMapper() {
385*fcaf7f86SDimitry Andric   std::vector<ExecutorAddr> ReservationAddrs;
386*fcaf7f86SDimitry Andric   if (!Reservations.empty()) {
387*fcaf7f86SDimitry Andric     std::lock_guard<std::mutex> Lock(Mutex);
388*fcaf7f86SDimitry Andric     {
389*fcaf7f86SDimitry Andric       ReservationAddrs.reserve(Reservations.size());
390*fcaf7f86SDimitry Andric       for (const auto &R : Reservations) {
391*fcaf7f86SDimitry Andric         ReservationAddrs.push_back(R.first);
392*fcaf7f86SDimitry Andric       }
393*fcaf7f86SDimitry Andric     }
394*fcaf7f86SDimitry Andric   }
395*fcaf7f86SDimitry Andric 
396*fcaf7f86SDimitry Andric   std::promise<MSVCPError> P;
397*fcaf7f86SDimitry Andric   auto F = P.get_future();
398*fcaf7f86SDimitry Andric   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
399*fcaf7f86SDimitry Andric   // FIXME: Release can actually fail. The error should be propagated.
400*fcaf7f86SDimitry Andric   // Meanwhile, a better option is to explicitly call release().
401*fcaf7f86SDimitry Andric   cantFail(F.get());
402*fcaf7f86SDimitry Andric }
403*fcaf7f86SDimitry Andric 
40481ad6265SDimitry Andric } // namespace orc
40581ad6265SDimitry Andric 
40681ad6265SDimitry Andric } // namespace llvm
407