xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp (revision 79fbee3cc562f59c7cd9c293074216107dfac08d)
1*79fbee3cSAnubhab Ghosh //===- MemoryMapper.cpp - Cross-process memory mapper ------------*- C++ -*-==//
2*79fbee3cSAnubhab Ghosh //
3*79fbee3cSAnubhab Ghosh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*79fbee3cSAnubhab Ghosh // See https://llvm.org/LICENSE.txt for license information.
5*79fbee3cSAnubhab Ghosh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*79fbee3cSAnubhab Ghosh //
7*79fbee3cSAnubhab Ghosh //===----------------------------------------------------------------------===//
8*79fbee3cSAnubhab Ghosh 
9*79fbee3cSAnubhab Ghosh #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
10*79fbee3cSAnubhab Ghosh 
11*79fbee3cSAnubhab Ghosh namespace llvm {
12*79fbee3cSAnubhab Ghosh namespace orc {
13*79fbee3cSAnubhab Ghosh 
14*79fbee3cSAnubhab Ghosh MemoryMapper::~MemoryMapper() {}
15*79fbee3cSAnubhab Ghosh 
16*79fbee3cSAnubhab Ghosh void InProcessMemoryMapper::reserve(size_t NumBytes,
17*79fbee3cSAnubhab Ghosh                                     OnReservedFunction OnReserved) {
18*79fbee3cSAnubhab Ghosh   std::error_code EC;
19*79fbee3cSAnubhab Ghosh   auto MB = sys::Memory::allocateMappedMemory(
20*79fbee3cSAnubhab Ghosh       NumBytes, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
21*79fbee3cSAnubhab Ghosh 
22*79fbee3cSAnubhab Ghosh   if (EC)
23*79fbee3cSAnubhab Ghosh     return OnReserved(errorCodeToError(EC));
24*79fbee3cSAnubhab Ghosh 
25*79fbee3cSAnubhab Ghosh   {
26*79fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
27*79fbee3cSAnubhab Ghosh     Reservations[MB.base()].Size = MB.allocatedSize();
28*79fbee3cSAnubhab Ghosh   }
29*79fbee3cSAnubhab Ghosh 
30*79fbee3cSAnubhab Ghosh   OnReserved(
31*79fbee3cSAnubhab Ghosh       ExecutorAddrRange(ExecutorAddr::fromPtr(MB.base()), MB.allocatedSize()));
32*79fbee3cSAnubhab Ghosh }
33*79fbee3cSAnubhab Ghosh 
34*79fbee3cSAnubhab Ghosh char *InProcessMemoryMapper::prepare(ExecutorAddr Addr, size_t ContentSize) {
35*79fbee3cSAnubhab Ghosh   return Addr.toPtr<char *>();
36*79fbee3cSAnubhab Ghosh }
37*79fbee3cSAnubhab Ghosh 
38*79fbee3cSAnubhab Ghosh void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
39*79fbee3cSAnubhab Ghosh                                        OnInitializedFunction OnInitialized) {
40*79fbee3cSAnubhab Ghosh   ExecutorAddr MinAddr(~0ULL);
41*79fbee3cSAnubhab Ghosh 
42*79fbee3cSAnubhab Ghosh   for (auto &Segment : AI.Segments) {
43*79fbee3cSAnubhab Ghosh     auto Base = AI.MappingBase + Segment.Offset;
44*79fbee3cSAnubhab Ghosh     auto Size = Segment.ContentSize + Segment.ZeroFillSize;
45*79fbee3cSAnubhab Ghosh 
46*79fbee3cSAnubhab Ghosh     if (Base < MinAddr)
47*79fbee3cSAnubhab Ghosh       MinAddr = Base;
48*79fbee3cSAnubhab Ghosh 
49*79fbee3cSAnubhab Ghosh     std::memset((Base + Segment.ContentSize).toPtr<void *>(), 0,
50*79fbee3cSAnubhab Ghosh                 Segment.ZeroFillSize);
51*79fbee3cSAnubhab Ghosh 
52*79fbee3cSAnubhab Ghosh     if (auto EC = sys::Memory::protectMappedMemory({Base.toPtr<void *>(), Size},
53*79fbee3cSAnubhab Ghosh                                                    Segment.Prot)) {
54*79fbee3cSAnubhab Ghosh       return OnInitialized(errorCodeToError(EC));
55*79fbee3cSAnubhab Ghosh     }
56*79fbee3cSAnubhab Ghosh     if (Segment.Prot & sys::Memory::MF_EXEC)
57*79fbee3cSAnubhab Ghosh       sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
58*79fbee3cSAnubhab Ghosh   }
59*79fbee3cSAnubhab Ghosh 
60*79fbee3cSAnubhab Ghosh   auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
61*79fbee3cSAnubhab Ghosh   if (!DeinitializeActions)
62*79fbee3cSAnubhab Ghosh     return OnInitialized(DeinitializeActions.takeError());
63*79fbee3cSAnubhab Ghosh 
64*79fbee3cSAnubhab Ghosh   {
65*79fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
66*79fbee3cSAnubhab Ghosh     Allocations[MinAddr].DeinitializationActions =
67*79fbee3cSAnubhab Ghosh         std::move(*DeinitializeActions);
68*79fbee3cSAnubhab Ghosh     Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
69*79fbee3cSAnubhab Ghosh   }
70*79fbee3cSAnubhab Ghosh 
71*79fbee3cSAnubhab Ghosh   OnInitialized(MinAddr);
72*79fbee3cSAnubhab Ghosh }
73*79fbee3cSAnubhab Ghosh 
74*79fbee3cSAnubhab Ghosh void InProcessMemoryMapper::deinitialize(
75*79fbee3cSAnubhab Ghosh     ArrayRef<ExecutorAddr> Bases,
76*79fbee3cSAnubhab Ghosh     MemoryMapper::OnDeinitializedFunction OnDeinitialized) {
77*79fbee3cSAnubhab Ghosh   Error AllErr = Error::success();
78*79fbee3cSAnubhab Ghosh 
79*79fbee3cSAnubhab Ghosh   {
80*79fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
81*79fbee3cSAnubhab Ghosh 
82*79fbee3cSAnubhab Ghosh     for (auto Base : Bases) {
83*79fbee3cSAnubhab Ghosh 
84*79fbee3cSAnubhab Ghosh       if (Error Err = shared::runDeallocActions(
85*79fbee3cSAnubhab Ghosh               Allocations[Base].DeinitializationActions)) {
86*79fbee3cSAnubhab Ghosh         AllErr = joinErrors(std::move(AllErr), std::move(Err));
87*79fbee3cSAnubhab Ghosh       }
88*79fbee3cSAnubhab Ghosh 
89*79fbee3cSAnubhab Ghosh       Allocations.erase(Base);
90*79fbee3cSAnubhab Ghosh     }
91*79fbee3cSAnubhab Ghosh   }
92*79fbee3cSAnubhab Ghosh 
93*79fbee3cSAnubhab Ghosh   OnDeinitialized(std::move(AllErr));
94*79fbee3cSAnubhab Ghosh }
95*79fbee3cSAnubhab Ghosh 
96*79fbee3cSAnubhab Ghosh void InProcessMemoryMapper::release(ArrayRef<ExecutorAddr> Bases,
97*79fbee3cSAnubhab Ghosh                                     OnReleasedFunction OnReleased) {
98*79fbee3cSAnubhab Ghosh   Error Err = Error::success();
99*79fbee3cSAnubhab Ghosh 
100*79fbee3cSAnubhab Ghosh   for (auto Base : Bases) {
101*79fbee3cSAnubhab Ghosh     std::vector<ExecutorAddr> AllocAddrs;
102*79fbee3cSAnubhab Ghosh     size_t Size;
103*79fbee3cSAnubhab Ghosh     {
104*79fbee3cSAnubhab Ghosh       std::lock_guard<std::mutex> Lock(Mutex);
105*79fbee3cSAnubhab Ghosh       auto &R = Reservations[Base.toPtr<void *>()];
106*79fbee3cSAnubhab Ghosh       Size = R.Size;
107*79fbee3cSAnubhab Ghosh       AllocAddrs.swap(R.Allocations);
108*79fbee3cSAnubhab Ghosh     }
109*79fbee3cSAnubhab Ghosh 
110*79fbee3cSAnubhab Ghosh     // deinitialize sub allocations
111*79fbee3cSAnubhab Ghosh     std::promise<MSVCPError> P;
112*79fbee3cSAnubhab Ghosh     auto F = P.get_future();
113*79fbee3cSAnubhab Ghosh     deinitialize(AllocAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
114*79fbee3cSAnubhab Ghosh     if (Error E = F.get()) {
115*79fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), std::move(E));
116*79fbee3cSAnubhab Ghosh     }
117*79fbee3cSAnubhab Ghosh 
118*79fbee3cSAnubhab Ghosh     // free the memory
119*79fbee3cSAnubhab Ghosh     auto MB = sys::MemoryBlock(Base.toPtr<void *>(), Size);
120*79fbee3cSAnubhab Ghosh 
121*79fbee3cSAnubhab Ghosh     auto EC = sys::Memory::releaseMappedMemory(MB);
122*79fbee3cSAnubhab Ghosh     if (EC) {
123*79fbee3cSAnubhab Ghosh       Err = joinErrors(std::move(Err), errorCodeToError(EC));
124*79fbee3cSAnubhab Ghosh     }
125*79fbee3cSAnubhab Ghosh 
126*79fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
127*79fbee3cSAnubhab Ghosh     Reservations.erase(Base.toPtr<void *>());
128*79fbee3cSAnubhab Ghosh   }
129*79fbee3cSAnubhab Ghosh 
130*79fbee3cSAnubhab Ghosh   OnReleased(std::move(Err));
131*79fbee3cSAnubhab Ghosh }
132*79fbee3cSAnubhab Ghosh 
133*79fbee3cSAnubhab Ghosh InProcessMemoryMapper::~InProcessMemoryMapper() {
134*79fbee3cSAnubhab Ghosh   std::vector<ExecutorAddr> ReservationAddrs;
135*79fbee3cSAnubhab Ghosh   {
136*79fbee3cSAnubhab Ghosh     std::lock_guard<std::mutex> Lock(Mutex);
137*79fbee3cSAnubhab Ghosh 
138*79fbee3cSAnubhab Ghosh     ReservationAddrs.reserve(Reservations.size());
139*79fbee3cSAnubhab Ghosh     for (const auto &R : Reservations) {
140*79fbee3cSAnubhab Ghosh       ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
141*79fbee3cSAnubhab Ghosh     }
142*79fbee3cSAnubhab Ghosh   }
143*79fbee3cSAnubhab Ghosh 
144*79fbee3cSAnubhab Ghosh   std::promise<MSVCPError> P;
145*79fbee3cSAnubhab Ghosh   auto F = P.get_future();
146*79fbee3cSAnubhab Ghosh   release(ReservationAddrs, [&](Error Err) { P.set_value(std::move(Err)); });
147*79fbee3cSAnubhab Ghosh   cantFail(F.get());
148*79fbee3cSAnubhab Ghosh }
149*79fbee3cSAnubhab Ghosh 
150*79fbee3cSAnubhab Ghosh } // namespace orc
151*79fbee3cSAnubhab Ghosh 
152*79fbee3cSAnubhab Ghosh } // namespace llvm
153