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