1349cc55cSDimitry Andric //===------- SimpleEPCServer.cpp - EPC over simple abstract channel -------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric
9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h"
10349cc55cSDimitry Andric
11*5f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
13*5f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
14349cc55cSDimitry Andric #include "llvm/Support/FormatVariadic.h"
15349cc55cSDimitry Andric #include "llvm/Support/Process.h"
1606c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
17349cc55cSDimitry Andric
18349cc55cSDimitry Andric #include "OrcRTBootstrap.h"
19349cc55cSDimitry Andric
20349cc55cSDimitry Andric #define DEBUG_TYPE "orc"
21349cc55cSDimitry Andric
22349cc55cSDimitry Andric using namespace llvm::orc::shared;
23349cc55cSDimitry Andric
24349cc55cSDimitry Andric namespace llvm {
25349cc55cSDimitry Andric namespace orc {
26349cc55cSDimitry Andric
2781ad6265SDimitry Andric ExecutorBootstrapService::~ExecutorBootstrapService() = default;
28349cc55cSDimitry Andric
2981ad6265SDimitry Andric SimpleRemoteEPCServer::Dispatcher::~Dispatcher() = default;
30349cc55cSDimitry Andric
31349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS
dispatch(unique_function<void ()> Work)32349cc55cSDimitry Andric void SimpleRemoteEPCServer::ThreadDispatcher::dispatch(
33349cc55cSDimitry Andric unique_function<void()> Work) {
34349cc55cSDimitry Andric {
35349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex);
36349cc55cSDimitry Andric if (!Running)
37349cc55cSDimitry Andric return;
38349cc55cSDimitry Andric ++Outstanding;
39349cc55cSDimitry Andric }
40349cc55cSDimitry Andric
41349cc55cSDimitry Andric std::thread([this, Work = std::move(Work)]() mutable {
42349cc55cSDimitry Andric Work();
43349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex);
44349cc55cSDimitry Andric --Outstanding;
45349cc55cSDimitry Andric OutstandingCV.notify_all();
46349cc55cSDimitry Andric }).detach();
47349cc55cSDimitry Andric }
48349cc55cSDimitry Andric
shutdown()49349cc55cSDimitry Andric void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() {
50349cc55cSDimitry Andric std::unique_lock<std::mutex> Lock(DispatchMutex);
51349cc55cSDimitry Andric Running = false;
52349cc55cSDimitry Andric OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
53349cc55cSDimitry Andric }
54349cc55cSDimitry Andric #endif
55349cc55cSDimitry Andric
defaultBootstrapSymbols()56349cc55cSDimitry Andric StringMap<ExecutorAddr> SimpleRemoteEPCServer::defaultBootstrapSymbols() {
57349cc55cSDimitry Andric StringMap<ExecutorAddr> DBS;
58349cc55cSDimitry Andric rt_bootstrap::addTo(DBS);
59349cc55cSDimitry Andric return DBS;
60349cc55cSDimitry Andric }
61349cc55cSDimitry Andric
62349cc55cSDimitry Andric Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
handleMessage(SimpleRemoteEPCOpcode OpC,uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)63349cc55cSDimitry Andric SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
64349cc55cSDimitry Andric ExecutorAddr TagAddr,
65349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) {
66349cc55cSDimitry Andric
67349cc55cSDimitry Andric LLVM_DEBUG({
68349cc55cSDimitry Andric dbgs() << "SimpleRemoteEPCServer::handleMessage: opc = ";
69349cc55cSDimitry Andric switch (OpC) {
70349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Setup:
71349cc55cSDimitry Andric dbgs() << "Setup";
72349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
7306c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Setup?");
74349cc55cSDimitry Andric break;
75349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Hangup:
76349cc55cSDimitry Andric dbgs() << "Hangup";
77349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
7806c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Hangup?");
79349cc55cSDimitry Andric break;
80349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Result:
81349cc55cSDimitry Andric dbgs() << "Result";
8206c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Result?");
83349cc55cSDimitry Andric break;
84349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::CallWrapper:
85349cc55cSDimitry Andric dbgs() << "CallWrapper";
86349cc55cSDimitry Andric break;
87349cc55cSDimitry Andric }
8806c3fb27SDimitry Andric dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
89349cc55cSDimitry Andric << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
90349cc55cSDimitry Andric << " bytes\n";
91349cc55cSDimitry Andric });
92349cc55cSDimitry Andric
93349cc55cSDimitry Andric using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
94349cc55cSDimitry Andric if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
95349cc55cSDimitry Andric return make_error<StringError>("Unexpected opcode",
96349cc55cSDimitry Andric inconvertibleErrorCode());
97349cc55cSDimitry Andric
98349cc55cSDimitry Andric // TODO: Clean detach message?
99349cc55cSDimitry Andric switch (OpC) {
100349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Setup:
101349cc55cSDimitry Andric return make_error<StringError>("Unexpected Setup opcode",
102349cc55cSDimitry Andric inconvertibleErrorCode());
103349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Hangup:
104349cc55cSDimitry Andric return SimpleRemoteEPCTransportClient::EndSession;
105349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Result:
106349cc55cSDimitry Andric if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
107349cc55cSDimitry Andric return std::move(Err);
108349cc55cSDimitry Andric break;
109349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::CallWrapper:
110349cc55cSDimitry Andric handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
111349cc55cSDimitry Andric break;
112349cc55cSDimitry Andric }
113349cc55cSDimitry Andric return ContinueSession;
114349cc55cSDimitry Andric }
115349cc55cSDimitry Andric
waitForDisconnect()116349cc55cSDimitry Andric Error SimpleRemoteEPCServer::waitForDisconnect() {
117349cc55cSDimitry Andric std::unique_lock<std::mutex> Lock(ServerStateMutex);
118349cc55cSDimitry Andric ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; });
119349cc55cSDimitry Andric return std::move(ShutdownErr);
120349cc55cSDimitry Andric }
121349cc55cSDimitry Andric
handleDisconnect(Error Err)122349cc55cSDimitry Andric void SimpleRemoteEPCServer::handleDisconnect(Error Err) {
123349cc55cSDimitry Andric PendingJITDispatchResultsMap TmpPending;
124349cc55cSDimitry Andric
125349cc55cSDimitry Andric {
126349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex);
127349cc55cSDimitry Andric std::swap(TmpPending, PendingJITDispatchResults);
128349cc55cSDimitry Andric RunState = ServerShuttingDown;
129349cc55cSDimitry Andric }
130349cc55cSDimitry Andric
131349cc55cSDimitry Andric // Send out-of-band errors to any waiting threads.
132349cc55cSDimitry Andric for (auto &KV : TmpPending)
133349cc55cSDimitry Andric KV.second->set_value(
134349cc55cSDimitry Andric shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
135349cc55cSDimitry Andric
136349cc55cSDimitry Andric // Wait for dispatcher to clear.
137349cc55cSDimitry Andric D->shutdown();
138349cc55cSDimitry Andric
139349cc55cSDimitry Andric // Shut down services.
140349cc55cSDimitry Andric while (!Services.empty()) {
141349cc55cSDimitry Andric ShutdownErr =
142349cc55cSDimitry Andric joinErrors(std::move(ShutdownErr), Services.back()->shutdown());
143349cc55cSDimitry Andric Services.pop_back();
144349cc55cSDimitry Andric }
145349cc55cSDimitry Andric
146349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex);
147349cc55cSDimitry Andric ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err));
148349cc55cSDimitry Andric RunState = ServerShutDown;
149349cc55cSDimitry Andric ShutdownCV.notify_all();
150349cc55cSDimitry Andric }
151349cc55cSDimitry Andric
sendMessage(SimpleRemoteEPCOpcode OpC,uint64_t SeqNo,ExecutorAddr TagAddr,ArrayRef<char> ArgBytes)152349cc55cSDimitry Andric Error SimpleRemoteEPCServer::sendMessage(SimpleRemoteEPCOpcode OpC,
153349cc55cSDimitry Andric uint64_t SeqNo, ExecutorAddr TagAddr,
154349cc55cSDimitry Andric ArrayRef<char> ArgBytes) {
155349cc55cSDimitry Andric
156349cc55cSDimitry Andric LLVM_DEBUG({
157349cc55cSDimitry Andric dbgs() << "SimpleRemoteEPCServer::sendMessage: opc = ";
158349cc55cSDimitry Andric switch (OpC) {
159349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Setup:
160349cc55cSDimitry Andric dbgs() << "Setup";
161349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
16206c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Setup?");
163349cc55cSDimitry Andric break;
164349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Hangup:
165349cc55cSDimitry Andric dbgs() << "Hangup";
166349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
16706c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Hangup?");
168349cc55cSDimitry Andric break;
169349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Result:
170349cc55cSDimitry Andric dbgs() << "Result";
17106c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Result?");
172349cc55cSDimitry Andric break;
173349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::CallWrapper:
174349cc55cSDimitry Andric dbgs() << "CallWrapper";
175349cc55cSDimitry Andric break;
176349cc55cSDimitry Andric }
17706c3fb27SDimitry Andric dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
178349cc55cSDimitry Andric << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
179349cc55cSDimitry Andric << " bytes\n";
180349cc55cSDimitry Andric });
181349cc55cSDimitry Andric auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
182349cc55cSDimitry Andric LLVM_DEBUG({
183349cc55cSDimitry Andric if (Err)
184349cc55cSDimitry Andric dbgs() << " \\--> SimpleRemoteEPC::sendMessage failed\n";
185349cc55cSDimitry Andric });
186349cc55cSDimitry Andric return Err;
187349cc55cSDimitry Andric }
188349cc55cSDimitry Andric
sendSetupMessage(StringMap<std::vector<char>> BootstrapMap,StringMap<ExecutorAddr> BootstrapSymbols)189349cc55cSDimitry Andric Error SimpleRemoteEPCServer::sendSetupMessage(
19006c3fb27SDimitry Andric StringMap<std::vector<char>> BootstrapMap,
191349cc55cSDimitry Andric StringMap<ExecutorAddr> BootstrapSymbols) {
192349cc55cSDimitry Andric
193349cc55cSDimitry Andric using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
194349cc55cSDimitry Andric
195349cc55cSDimitry Andric std::vector<char> SetupPacket;
196349cc55cSDimitry Andric SimpleRemoteEPCExecutorInfo EI;
197349cc55cSDimitry Andric EI.TargetTriple = sys::getProcessTriple();
198349cc55cSDimitry Andric if (auto PageSize = sys::Process::getPageSize())
199349cc55cSDimitry Andric EI.PageSize = *PageSize;
200349cc55cSDimitry Andric else
201349cc55cSDimitry Andric return PageSize.takeError();
20206c3fb27SDimitry Andric EI.BootstrapMap = std::move(BootstrapMap);
203349cc55cSDimitry Andric EI.BootstrapSymbols = std::move(BootstrapSymbols);
204349cc55cSDimitry Andric
205349cc55cSDimitry Andric assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) &&
206349cc55cSDimitry Andric "Dispatch context name should not be set");
207349cc55cSDimitry Andric assert(!EI.BootstrapSymbols.count(DispatchFnName) &&
208349cc55cSDimitry Andric "Dispatch function name should not be set");
209349cc55cSDimitry Andric EI.BootstrapSymbols[ExecutorSessionObjectName] = ExecutorAddr::fromPtr(this);
210349cc55cSDimitry Andric EI.BootstrapSymbols[DispatchFnName] = ExecutorAddr::fromPtr(jitDispatchEntry);
211*5f757f3fSDimitry Andric EI.BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] =
212*5f757f3fSDimitry Andric ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper);
213*5f757f3fSDimitry Andric EI.BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] =
214*5f757f3fSDimitry Andric ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
215349cc55cSDimitry Andric
216349cc55cSDimitry Andric using SPSSerialize =
217349cc55cSDimitry Andric shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
218349cc55cSDimitry Andric auto SetupPacketBytes =
219349cc55cSDimitry Andric shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI));
220349cc55cSDimitry Andric shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size());
221349cc55cSDimitry Andric if (!SPSSerialize::serialize(OB, EI))
222349cc55cSDimitry Andric return make_error<StringError>("Could not send setup packet",
223349cc55cSDimitry Andric inconvertibleErrorCode());
224349cc55cSDimitry Andric
225349cc55cSDimitry Andric return sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddr(),
226349cc55cSDimitry Andric {SetupPacketBytes.data(), SetupPacketBytes.size()});
227349cc55cSDimitry Andric }
228349cc55cSDimitry Andric
handleResult(uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)229349cc55cSDimitry Andric Error SimpleRemoteEPCServer::handleResult(
230349cc55cSDimitry Andric uint64_t SeqNo, ExecutorAddr TagAddr,
231349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) {
232349cc55cSDimitry Andric std::promise<shared::WrapperFunctionResult> *P = nullptr;
233349cc55cSDimitry Andric {
234349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex);
235349cc55cSDimitry Andric auto I = PendingJITDispatchResults.find(SeqNo);
236349cc55cSDimitry Andric if (I == PendingJITDispatchResults.end())
237349cc55cSDimitry Andric return make_error<StringError>("No call for sequence number " +
238349cc55cSDimitry Andric Twine(SeqNo),
239349cc55cSDimitry Andric inconvertibleErrorCode());
240349cc55cSDimitry Andric P = I->second;
241349cc55cSDimitry Andric PendingJITDispatchResults.erase(I);
242349cc55cSDimitry Andric releaseSeqNo(SeqNo);
243349cc55cSDimitry Andric }
244349cc55cSDimitry Andric auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size());
245349cc55cSDimitry Andric memcpy(R.data(), ArgBytes.data(), ArgBytes.size());
246349cc55cSDimitry Andric P->set_value(std::move(R));
247349cc55cSDimitry Andric return Error::success();
248349cc55cSDimitry Andric }
249349cc55cSDimitry Andric
handleCallWrapper(uint64_t RemoteSeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)250349cc55cSDimitry Andric void SimpleRemoteEPCServer::handleCallWrapper(
251349cc55cSDimitry Andric uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
252349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) {
253349cc55cSDimitry Andric D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
254349cc55cSDimitry Andric using WrapperFnTy =
255349cc55cSDimitry Andric shared::CWrapperFunctionResult (*)(const char *, size_t);
256349cc55cSDimitry Andric auto *Fn = TagAddr.toPtr<WrapperFnTy>();
257349cc55cSDimitry Andric shared::WrapperFunctionResult ResultBytes(
258349cc55cSDimitry Andric Fn(ArgBytes.data(), ArgBytes.size()));
259349cc55cSDimitry Andric if (auto Err = sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
260349cc55cSDimitry Andric ExecutorAddr(),
261349cc55cSDimitry Andric {ResultBytes.data(), ResultBytes.size()}))
262349cc55cSDimitry Andric ReportError(std::move(Err));
263349cc55cSDimitry Andric });
264349cc55cSDimitry Andric }
265349cc55cSDimitry Andric
266349cc55cSDimitry Andric shared::WrapperFunctionResult
doJITDispatch(const void * FnTag,const char * ArgData,size_t ArgSize)267349cc55cSDimitry Andric SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData,
268349cc55cSDimitry Andric size_t ArgSize) {
269349cc55cSDimitry Andric uint64_t SeqNo;
270349cc55cSDimitry Andric std::promise<shared::WrapperFunctionResult> ResultP;
271349cc55cSDimitry Andric auto ResultF = ResultP.get_future();
272349cc55cSDimitry Andric {
273349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex);
274349cc55cSDimitry Andric if (RunState != ServerRunning)
275349cc55cSDimitry Andric return shared::WrapperFunctionResult::createOutOfBandError(
276349cc55cSDimitry Andric "jit_dispatch not available (EPC server shut down)");
277349cc55cSDimitry Andric
278349cc55cSDimitry Andric SeqNo = getNextSeqNo();
279349cc55cSDimitry Andric assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use");
280349cc55cSDimitry Andric PendingJITDispatchResults[SeqNo] = &ResultP;
281349cc55cSDimitry Andric }
282349cc55cSDimitry Andric
283349cc55cSDimitry Andric if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
284349cc55cSDimitry Andric ExecutorAddr::fromPtr(FnTag), {ArgData, ArgSize}))
285349cc55cSDimitry Andric ReportError(std::move(Err));
286349cc55cSDimitry Andric
287349cc55cSDimitry Andric return ResultF.get();
288349cc55cSDimitry Andric }
289349cc55cSDimitry Andric
290349cc55cSDimitry Andric shared::CWrapperFunctionResult
jitDispatchEntry(void * DispatchCtx,const void * FnTag,const char * ArgData,size_t ArgSize)291349cc55cSDimitry Andric SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag,
292349cc55cSDimitry Andric const char *ArgData, size_t ArgSize) {
293349cc55cSDimitry Andric return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx)
294349cc55cSDimitry Andric ->doJITDispatch(FnTag, ArgData, ArgSize)
295349cc55cSDimitry Andric .release();
296349cc55cSDimitry Andric }
297349cc55cSDimitry Andric
298349cc55cSDimitry Andric } // end namespace orc
299349cc55cSDimitry Andric } // end namespace llvm
300