Skip to content

Commit 3b5842c

Browse files
committed
[ORC] Make runAllocActions and runDeallocActions asynchorous.
Part of ongoing work to make core ORC operations asynchronous. This only affects the runner utilities, not the AllocationActions themselves. The AllocationActions will be made asynchronous in a future patch.
1 parent 864a53b commit 3b5842c

File tree

5 files changed

+95
-47
lines changed

5 files changed

+95
-47
lines changed

llvm/include/llvm/ExecutionEngine/Orc/Shared/AllocationActions.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_ALLOCATIONACTIONS_H
1414
#define LLVM_EXECUTIONENGINE_ORC_SHARED_ALLOCATIONACTIONS_H
1515

16+
#include "llvm/ADT/FunctionExtras.h"
1617
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
1718
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
1819
#include "llvm/Support/Memory.h"
@@ -52,6 +53,9 @@ inline size_t numDeallocActions(const AllocActions &AAs) {
5253
AAs, [](const AllocActionCallPair &P) { return !!P.Dealloc; });
5354
}
5455

56+
using OnRunFinalizeActionsCompleteFn =
57+
unique_function<void(Expected<std::vector<WrapperFunctionCall>>)>;
58+
5559
/// Run finalize actions.
5660
///
5761
/// If any finalize action fails then the corresponding dealloc actions will be
@@ -62,13 +66,16 @@ inline size_t numDeallocActions(const AllocActions &AAs) {
6266
/// be returned. The dealloc actions should be run by calling
6367
/// runDeallocationActions. If this function succeeds then the AA argument will
6468
/// be cleared before the function returns.
65-
Expected<std::vector<WrapperFunctionCall>>
66-
runFinalizeActions(AllocActions &AAs);
69+
void runFinalizeActions(AllocActions &AAs,
70+
OnRunFinalizeActionsCompleteFn OnComplete);
71+
72+
using OnRunDeallocActionsComeleteFn = unique_function<void(Error)>;
6773

6874
/// Run deallocation actions.
6975
/// Dealloc actions will be run in reverse order (from last element of DAs to
7076
/// first).
71-
Error runDeallocActions(ArrayRef<WrapperFunctionCall> DAs);
77+
void runDeallocActions(ArrayRef<WrapperFunctionCall> DAs,
78+
OnRunDeallocActionsComeleteFn OnComplete);
7279

7380
using SPSAllocActionCallPair =
7481
SPSTuple<SPSWrapperFunctionCall, SPSWrapperFunctionCall>;

llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp

+32-21
Original file line numberDiff line numberDiff line change
@@ -260,17 +260,22 @@ class InProcessMemoryManager::IPInFlightAlloc
260260
}
261261

262262
// Run finalization actions.
263-
auto DeallocActions = runFinalizeActions(G->allocActions());
264-
if (!DeallocActions) {
265-
OnFinalized(DeallocActions.takeError());
266-
return;
267-
}
263+
using WrapperFunctionCall = orc::shared::WrapperFunctionCall;
264+
runFinalizeActions(
265+
G->allocActions(),
266+
[this, OnFinalized = std::move(OnFinalized)](
267+
Expected<std::vector<WrapperFunctionCall>> DeallocActions) mutable {
268+
completeFinalization(std::move(OnFinalized),
269+
std::move(DeallocActions));
270+
});
271+
}
268272

269-
// Release the finalize segments slab.
270-
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments)) {
271-
OnFinalized(errorCodeToError(EC));
272-
return;
273-
}
273+
void abandon(OnAbandonedFunction OnAbandoned) override {
274+
Error Err = Error::success();
275+
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments))
276+
Err = joinErrors(std::move(Err), errorCodeToError(EC));
277+
if (auto EC = sys::Memory::releaseMappedMemory(StandardSegments))
278+
Err = joinErrors(std::move(Err), errorCodeToError(EC));
274279

275280
#ifndef NDEBUG
276281
// Set 'G' to null to flag that we've been successfully finalized.
@@ -279,17 +284,22 @@ class InProcessMemoryManager::IPInFlightAlloc
279284
G = nullptr;
280285
#endif
281286

282-
// Continue with finalized allocation.
283-
OnFinalized(MemMgr.createFinalizedAlloc(std::move(StandardSegments),
284-
std::move(*DeallocActions)));
287+
OnAbandoned(std::move(Err));
285288
}
286289

287-
void abandon(OnAbandonedFunction OnAbandoned) override {
288-
Error Err = Error::success();
289-
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments))
290-
Err = joinErrors(std::move(Err), errorCodeToError(EC));
291-
if (auto EC = sys::Memory::releaseMappedMemory(StandardSegments))
292-
Err = joinErrors(std::move(Err), errorCodeToError(EC));
290+
private:
291+
void completeFinalization(
292+
OnFinalizedFunction OnFinalized,
293+
Expected<std::vector<orc::shared::WrapperFunctionCall>> DeallocActions) {
294+
295+
if (!DeallocActions)
296+
return OnFinalized(DeallocActions.takeError());
297+
298+
// Release the finalize segments slab.
299+
if (auto EC = sys::Memory::releaseMappedMemory(FinalizationSegments)) {
300+
OnFinalized(errorCodeToError(EC));
301+
return;
302+
}
293303

294304
#ifndef NDEBUG
295305
// Set 'G' to null to flag that we've been successfully finalized.
@@ -298,10 +308,11 @@ class InProcessMemoryManager::IPInFlightAlloc
298308
G = nullptr;
299309
#endif
300310

301-
OnAbandoned(std::move(Err));
311+
// Continue with finalized allocation.
312+
OnFinalized(MemMgr.createFinalizedAlloc(std::move(StandardSegments),
313+
std::move(*DeallocActions)));
302314
}
303315

304-
private:
305316
Error applyProtections() {
306317
for (auto &KV : BL.segments()) {
307318
const auto &AG = KV.first;

llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp

+18-8
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,27 @@ void InProcessMemoryMapper::initialize(MemoryMapper::AllocInfo &AI,
9090
sys::Memory::InvalidateInstructionCache(Base.toPtr<void *>(), Size);
9191
}
9292

93-
auto DeinitializeActions = shared::runFinalizeActions(AI.Actions);
94-
if (!DeinitializeActions)
95-
return OnInitialized(DeinitializeActions.takeError());
93+
std::vector<shared::WrapperFunctionCall> DeinitializeActions;
94+
{
95+
std::promise<MSVCPExpected<std::vector<shared::WrapperFunctionCall>>> P;
96+
auto F = P.get_future();
97+
shared::runFinalizeActions(
98+
AI.Actions, [&](Expected<std::vector<shared::WrapperFunctionCall>> R) {
99+
P.set_value(std::move(R));
100+
});
101+
if (auto DeinitializeActionsOrErr = F.get())
102+
DeinitializeActions = std::move(*DeinitializeActionsOrErr);
103+
else
104+
return OnInitialized(DeinitializeActionsOrErr.takeError());
105+
}
96106

97107
{
98108
std::lock_guard<std::mutex> Lock(Mutex);
99109

100110
// This is the maximum range whose permission have been possibly modified
101111
auto &Alloc = Allocations[MinAddr];
102112
Alloc.Size = MaxAddr - MinAddr;
103-
Alloc.DeinitializationActions = std::move(*DeinitializeActions);
113+
Alloc.DeinitializationActions = std::move(DeinitializeActions);
104114
Reservations[AI.MappingBase.toPtr<void *>()].Allocations.push_back(MinAddr);
105115
}
106116

@@ -117,10 +127,10 @@ void InProcessMemoryMapper::deinitialize(
117127

118128
for (auto Base : llvm::reverse(Bases)) {
119129

120-
if (Error Err = shared::runDeallocActions(
121-
Allocations[Base].DeinitializationActions)) {
122-
AllErr = joinErrors(std::move(AllErr), std::move(Err));
123-
}
130+
shared::runDeallocActions(
131+
Allocations[Base].DeinitializationActions, [&](Error Err) {
132+
AllErr = joinErrors(std::move(AllErr), std::move(Err));
133+
});
124134

125135
// Reset protections to read/write so the area can be reused
126136
if (auto EC = sys::Memory::protectMappedMemory(

llvm/lib/ExecutionEngine/Orc/Shared/AllocationActions.cpp

+15-7
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,39 @@ namespace llvm {
1212
namespace orc {
1313
namespace shared {
1414

15-
Expected<std::vector<WrapperFunctionCall>>
16-
runFinalizeActions(AllocActions &AAs) {
15+
void runFinalizeActions(AllocActions &AAs,
16+
OnRunFinalizeActionsCompleteFn OnComplete) {
1717
std::vector<WrapperFunctionCall> DeallocActions;
1818
DeallocActions.reserve(numDeallocActions(AAs));
1919

2020
for (auto &AA : AAs) {
2121
if (AA.Finalize)
22-
if (auto Err = AA.Finalize.runWithSPSRetErrorMerged())
23-
return joinErrors(std::move(Err), runDeallocActions(DeallocActions));
22+
23+
if (auto Err = AA.Finalize.runWithSPSRetErrorMerged()) {
24+
while (!DeallocActions.empty()) {
25+
Err = joinErrors(std::move(Err),
26+
DeallocActions.back().runWithSPSRetErrorMerged());
27+
DeallocActions.pop_back();
28+
}
29+
return OnComplete(std::move(Err));
30+
}
2431

2532
if (AA.Dealloc)
2633
DeallocActions.push_back(std::move(AA.Dealloc));
2734
}
2835

2936
AAs.clear();
30-
return DeallocActions;
37+
OnComplete(std::move(DeallocActions));
3138
}
3239

33-
Error runDeallocActions(ArrayRef<WrapperFunctionCall> DAs) {
40+
void runDeallocActions(ArrayRef<WrapperFunctionCall> DAs,
41+
OnRunDeallocActionsComeleteFn OnComplete) {
3442
Error Err = Error::success();
3543
while (!DAs.empty()) {
3644
Err = joinErrors(std::move(Err), DAs.back().runWithSPSRetErrorMerged());
3745
DAs = DAs.drop_back();
3846
}
39-
return Err;
47+
OnComplete(std::move(Err));
4048
}
4149

4250
} // namespace shared

llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp

+20-8
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h"
1010
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
1111
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12+
#include "llvm/Support/MSVCErrorWorkarounds.h"
1213
#include "llvm/Support/Process.h"
1314
#include "llvm/Support/WindowsError.h"
15+
#include <future>
1416
#include <sstream>
1517

1618
#if defined(LLVM_ON_UNIX)
@@ -181,15 +183,24 @@ Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
181183
}
182184

183185
// Run finalization actions and get deinitlization action list.
184-
auto DeinitializeActions = shared::runFinalizeActions(FR.Actions);
185-
if (!DeinitializeActions) {
186-
return DeinitializeActions.takeError();
186+
std::vector<shared::WrapperFunctionCall> DeinitializeActions;
187+
{
188+
std::promise<MSVCPExpected<std::vector<shared::WrapperFunctionCall>>> P;
189+
auto F = P.get_future();
190+
shared::runFinalizeActions(
191+
FR.Actions, [&](Expected<std::vector<shared::WrapperFunctionCall>> R) {
192+
P.set_value(std::move(R));
193+
});
194+
if (auto DeinitializeActionsOrErr = F.get())
195+
DeinitializeActions = std::move(*DeinitializeActionsOrErr);
196+
else
197+
return DeinitializeActionsOrErr.takeError();
187198
}
188199

189200
{
190201
std::lock_guard<std::mutex> Lock(Mutex);
191202
Allocations[MinAddr].DeinitializationActions =
192-
std::move(*DeinitializeActions);
203+
std::move(DeinitializeActions);
193204
Reservations[Reservation.toPtr<void *>()].Allocations.push_back(MinAddr);
194205
}
195206

@@ -210,10 +221,11 @@ Error ExecutorSharedMemoryMapperService::deinitialize(
210221
std::lock_guard<std::mutex> Lock(Mutex);
211222

212223
for (auto Base : llvm::reverse(Bases)) {
213-
if (Error Err = shared::runDeallocActions(
214-
Allocations[Base].DeinitializationActions)) {
215-
AllErr = joinErrors(std::move(AllErr), std::move(Err));
216-
}
224+
shared::runDeallocActions(
225+
Allocations[Base].DeinitializationActions, [&](Error Err) {
226+
if (Err)
227+
AllErr = joinErrors(std::move(AllErr), std::move(Err));
228+
});
217229

218230
// Remove the allocation from the allocation list of its reservation
219231
for (auto &Reservation : Reservations) {

0 commit comments

Comments
 (0)