xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1c0981da4SDimitry Andric //===------- SimpleEPCServer.cpp - EPC over simple abstract channel -------===//
2c0981da4SDimitry Andric //
3c0981da4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c0981da4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5c0981da4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c0981da4SDimitry Andric //
7c0981da4SDimitry Andric //===----------------------------------------------------------------------===//
8c0981da4SDimitry Andric 
9c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h"
10c0981da4SDimitry Andric 
11b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12c0981da4SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
13b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
14c0981da4SDimitry Andric #include "llvm/Support/FormatVariadic.h"
15c0981da4SDimitry Andric #include "llvm/Support/Process.h"
167fa27ce4SDimitry Andric #include "llvm/TargetParser/Host.h"
17c0981da4SDimitry Andric 
18c0981da4SDimitry Andric #include "OrcRTBootstrap.h"
19c0981da4SDimitry Andric 
20c0981da4SDimitry Andric #define DEBUG_TYPE "orc"
21c0981da4SDimitry Andric 
22c0981da4SDimitry Andric using namespace llvm::orc::shared;
23c0981da4SDimitry Andric 
24c0981da4SDimitry Andric namespace llvm {
25c0981da4SDimitry Andric namespace orc {
26c0981da4SDimitry Andric 
27145449b1SDimitry Andric ExecutorBootstrapService::~ExecutorBootstrapService() = default;
28c0981da4SDimitry Andric 
29145449b1SDimitry Andric SimpleRemoteEPCServer::Dispatcher::~Dispatcher() = default;
30c0981da4SDimitry Andric 
31c0981da4SDimitry Andric #if LLVM_ENABLE_THREADS
dispatch(unique_function<void ()> Work)32c0981da4SDimitry Andric void SimpleRemoteEPCServer::ThreadDispatcher::dispatch(
33c0981da4SDimitry Andric     unique_function<void()> Work) {
34c0981da4SDimitry Andric   {
35c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(DispatchMutex);
36c0981da4SDimitry Andric     if (!Running)
37c0981da4SDimitry Andric       return;
38c0981da4SDimitry Andric     ++Outstanding;
39c0981da4SDimitry Andric   }
40c0981da4SDimitry Andric 
41c0981da4SDimitry Andric   std::thread([this, Work = std::move(Work)]() mutable {
42c0981da4SDimitry Andric     Work();
43c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(DispatchMutex);
44c0981da4SDimitry Andric     --Outstanding;
45c0981da4SDimitry Andric     OutstandingCV.notify_all();
46c0981da4SDimitry Andric   }).detach();
47c0981da4SDimitry Andric }
48c0981da4SDimitry Andric 
shutdown()49c0981da4SDimitry Andric void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() {
50c0981da4SDimitry Andric   std::unique_lock<std::mutex> Lock(DispatchMutex);
51c0981da4SDimitry Andric   Running = false;
52c0981da4SDimitry Andric   OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });
53c0981da4SDimitry Andric }
54c0981da4SDimitry Andric #endif
55c0981da4SDimitry Andric 
defaultBootstrapSymbols()56c0981da4SDimitry Andric StringMap<ExecutorAddr> SimpleRemoteEPCServer::defaultBootstrapSymbols() {
57c0981da4SDimitry Andric   StringMap<ExecutorAddr> DBS;
58c0981da4SDimitry Andric   rt_bootstrap::addTo(DBS);
59c0981da4SDimitry Andric   return DBS;
60c0981da4SDimitry Andric }
61c0981da4SDimitry Andric 
62c0981da4SDimitry Andric Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>
handleMessage(SimpleRemoteEPCOpcode OpC,uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)63c0981da4SDimitry Andric SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
64c0981da4SDimitry Andric                                      ExecutorAddr TagAddr,
65c0981da4SDimitry Andric                                      SimpleRemoteEPCArgBytesVector ArgBytes) {
66c0981da4SDimitry Andric 
67c0981da4SDimitry Andric   LLVM_DEBUG({
68c0981da4SDimitry Andric     dbgs() << "SimpleRemoteEPCServer::handleMessage: opc = ";
69c0981da4SDimitry Andric     switch (OpC) {
70c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Setup:
71c0981da4SDimitry Andric       dbgs() << "Setup";
72c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
737fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Setup?");
74c0981da4SDimitry Andric       break;
75c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Hangup:
76c0981da4SDimitry Andric       dbgs() << "Hangup";
77c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
787fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
79c0981da4SDimitry Andric       break;
80c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Result:
81c0981da4SDimitry Andric       dbgs() << "Result";
827fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Result?");
83c0981da4SDimitry Andric       break;
84c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::CallWrapper:
85c0981da4SDimitry Andric       dbgs() << "CallWrapper";
86c0981da4SDimitry Andric       break;
87c0981da4SDimitry Andric     }
887fa27ce4SDimitry Andric     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
89c0981da4SDimitry Andric            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
90c0981da4SDimitry Andric            << " bytes\n";
91c0981da4SDimitry Andric   });
92c0981da4SDimitry Andric 
93c0981da4SDimitry Andric   using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
94c0981da4SDimitry Andric   if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
95c0981da4SDimitry Andric     return make_error<StringError>("Unexpected opcode",
96c0981da4SDimitry Andric                                    inconvertibleErrorCode());
97c0981da4SDimitry Andric 
98c0981da4SDimitry Andric   // TODO: Clean detach message?
99c0981da4SDimitry Andric   switch (OpC) {
100c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::Setup:
101c0981da4SDimitry Andric     return make_error<StringError>("Unexpected Setup opcode",
102c0981da4SDimitry Andric                                    inconvertibleErrorCode());
103c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::Hangup:
104c0981da4SDimitry Andric     return SimpleRemoteEPCTransportClient::EndSession;
105c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::Result:
106c0981da4SDimitry Andric     if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
107c0981da4SDimitry Andric       return std::move(Err);
108c0981da4SDimitry Andric     break;
109c0981da4SDimitry Andric   case SimpleRemoteEPCOpcode::CallWrapper:
110c0981da4SDimitry Andric     handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
111c0981da4SDimitry Andric     break;
112c0981da4SDimitry Andric   }
113c0981da4SDimitry Andric   return ContinueSession;
114c0981da4SDimitry Andric }
115c0981da4SDimitry Andric 
waitForDisconnect()116c0981da4SDimitry Andric Error SimpleRemoteEPCServer::waitForDisconnect() {
117c0981da4SDimitry Andric   std::unique_lock<std::mutex> Lock(ServerStateMutex);
118c0981da4SDimitry Andric   ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; });
119c0981da4SDimitry Andric   return std::move(ShutdownErr);
120c0981da4SDimitry Andric }
121c0981da4SDimitry Andric 
handleDisconnect(Error Err)122c0981da4SDimitry Andric void SimpleRemoteEPCServer::handleDisconnect(Error Err) {
123c0981da4SDimitry Andric   PendingJITDispatchResultsMap TmpPending;
124c0981da4SDimitry Andric 
125c0981da4SDimitry Andric   {
126c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(ServerStateMutex);
127c0981da4SDimitry Andric     std::swap(TmpPending, PendingJITDispatchResults);
128c0981da4SDimitry Andric     RunState = ServerShuttingDown;
129c0981da4SDimitry Andric   }
130c0981da4SDimitry Andric 
131c0981da4SDimitry Andric   // Send out-of-band errors to any waiting threads.
132c0981da4SDimitry Andric   for (auto &KV : TmpPending)
133c0981da4SDimitry Andric     KV.second->set_value(
134c0981da4SDimitry Andric         shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));
135c0981da4SDimitry Andric 
136c0981da4SDimitry Andric   // Wait for dispatcher to clear.
137c0981da4SDimitry Andric   D->shutdown();
138c0981da4SDimitry Andric 
139c0981da4SDimitry Andric   // Shut down services.
140c0981da4SDimitry Andric   while (!Services.empty()) {
141c0981da4SDimitry Andric     ShutdownErr =
142c0981da4SDimitry Andric       joinErrors(std::move(ShutdownErr), Services.back()->shutdown());
143c0981da4SDimitry Andric     Services.pop_back();
144c0981da4SDimitry Andric   }
145c0981da4SDimitry Andric 
146c0981da4SDimitry Andric   std::lock_guard<std::mutex> Lock(ServerStateMutex);
147c0981da4SDimitry Andric   ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err));
148c0981da4SDimitry Andric   RunState = ServerShutDown;
149c0981da4SDimitry Andric   ShutdownCV.notify_all();
150c0981da4SDimitry Andric }
151c0981da4SDimitry Andric 
sendMessage(SimpleRemoteEPCOpcode OpC,uint64_t SeqNo,ExecutorAddr TagAddr,ArrayRef<char> ArgBytes)152c0981da4SDimitry Andric Error SimpleRemoteEPCServer::sendMessage(SimpleRemoteEPCOpcode OpC,
153c0981da4SDimitry Andric                                          uint64_t SeqNo, ExecutorAddr TagAddr,
154c0981da4SDimitry Andric                                          ArrayRef<char> ArgBytes) {
155c0981da4SDimitry Andric 
156c0981da4SDimitry Andric   LLVM_DEBUG({
157c0981da4SDimitry Andric     dbgs() << "SimpleRemoteEPCServer::sendMessage: opc = ";
158c0981da4SDimitry Andric     switch (OpC) {
159c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Setup:
160c0981da4SDimitry Andric       dbgs() << "Setup";
161c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
1627fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Setup?");
163c0981da4SDimitry Andric       break;
164c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Hangup:
165c0981da4SDimitry Andric       dbgs() << "Hangup";
166c0981da4SDimitry Andric       assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
1677fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Hangup?");
168c0981da4SDimitry Andric       break;
169c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::Result:
170c0981da4SDimitry Andric       dbgs() << "Result";
1717fa27ce4SDimitry Andric       assert(!TagAddr && "Non-zero TagAddr for Result?");
172c0981da4SDimitry Andric       break;
173c0981da4SDimitry Andric     case SimpleRemoteEPCOpcode::CallWrapper:
174c0981da4SDimitry Andric       dbgs() << "CallWrapper";
175c0981da4SDimitry Andric       break;
176c0981da4SDimitry Andric     }
1777fa27ce4SDimitry Andric     dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr
178c0981da4SDimitry Andric            << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
179c0981da4SDimitry Andric            << " bytes\n";
180c0981da4SDimitry Andric   });
181c0981da4SDimitry Andric   auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
182c0981da4SDimitry Andric   LLVM_DEBUG({
183c0981da4SDimitry Andric     if (Err)
184c0981da4SDimitry Andric       dbgs() << "  \\--> SimpleRemoteEPC::sendMessage failed\n";
185c0981da4SDimitry Andric   });
186c0981da4SDimitry Andric   return Err;
187c0981da4SDimitry Andric }
188c0981da4SDimitry Andric 
sendSetupMessage(StringMap<std::vector<char>> BootstrapMap,StringMap<ExecutorAddr> BootstrapSymbols)189c0981da4SDimitry Andric Error SimpleRemoteEPCServer::sendSetupMessage(
1907fa27ce4SDimitry Andric     StringMap<std::vector<char>> BootstrapMap,
191c0981da4SDimitry Andric     StringMap<ExecutorAddr> BootstrapSymbols) {
192c0981da4SDimitry Andric 
193c0981da4SDimitry Andric   using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
194c0981da4SDimitry Andric 
195c0981da4SDimitry Andric   std::vector<char> SetupPacket;
196c0981da4SDimitry Andric   SimpleRemoteEPCExecutorInfo EI;
197c0981da4SDimitry Andric   EI.TargetTriple = sys::getProcessTriple();
198c0981da4SDimitry Andric   if (auto PageSize = sys::Process::getPageSize())
199c0981da4SDimitry Andric     EI.PageSize = *PageSize;
200c0981da4SDimitry Andric   else
201c0981da4SDimitry Andric     return PageSize.takeError();
2027fa27ce4SDimitry Andric   EI.BootstrapMap = std::move(BootstrapMap);
203c0981da4SDimitry Andric   EI.BootstrapSymbols = std::move(BootstrapSymbols);
204c0981da4SDimitry Andric 
205c0981da4SDimitry Andric   assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) &&
206c0981da4SDimitry Andric          "Dispatch context name should not be set");
207c0981da4SDimitry Andric   assert(!EI.BootstrapSymbols.count(DispatchFnName) &&
208c0981da4SDimitry Andric          "Dispatch function name should not be set");
209c0981da4SDimitry Andric   EI.BootstrapSymbols[ExecutorSessionObjectName] = ExecutorAddr::fromPtr(this);
210c0981da4SDimitry Andric   EI.BootstrapSymbols[DispatchFnName] = ExecutorAddr::fromPtr(jitDispatchEntry);
211b1c73532SDimitry Andric   EI.BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] =
212b1c73532SDimitry Andric       ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper);
213b1c73532SDimitry Andric   EI.BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] =
214b1c73532SDimitry Andric       ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
215c0981da4SDimitry Andric 
216c0981da4SDimitry Andric   using SPSSerialize =
217c0981da4SDimitry Andric       shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
218c0981da4SDimitry Andric   auto SetupPacketBytes =
219c0981da4SDimitry Andric       shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI));
220c0981da4SDimitry Andric   shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size());
221c0981da4SDimitry Andric   if (!SPSSerialize::serialize(OB, EI))
222c0981da4SDimitry Andric     return make_error<StringError>("Could not send setup packet",
223c0981da4SDimitry Andric                                    inconvertibleErrorCode());
224c0981da4SDimitry Andric 
225c0981da4SDimitry Andric   return sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddr(),
226c0981da4SDimitry Andric                      {SetupPacketBytes.data(), SetupPacketBytes.size()});
227c0981da4SDimitry Andric }
228c0981da4SDimitry Andric 
handleResult(uint64_t SeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)229c0981da4SDimitry Andric Error SimpleRemoteEPCServer::handleResult(
230c0981da4SDimitry Andric     uint64_t SeqNo, ExecutorAddr TagAddr,
231c0981da4SDimitry Andric     SimpleRemoteEPCArgBytesVector ArgBytes) {
232c0981da4SDimitry Andric   std::promise<shared::WrapperFunctionResult> *P = nullptr;
233c0981da4SDimitry Andric   {
234c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(ServerStateMutex);
235c0981da4SDimitry Andric     auto I = PendingJITDispatchResults.find(SeqNo);
236c0981da4SDimitry Andric     if (I == PendingJITDispatchResults.end())
237c0981da4SDimitry Andric       return make_error<StringError>("No call for sequence number " +
238c0981da4SDimitry Andric                                          Twine(SeqNo),
239c0981da4SDimitry Andric                                      inconvertibleErrorCode());
240c0981da4SDimitry Andric     P = I->second;
241c0981da4SDimitry Andric     PendingJITDispatchResults.erase(I);
242c0981da4SDimitry Andric     releaseSeqNo(SeqNo);
243c0981da4SDimitry Andric   }
244c0981da4SDimitry Andric   auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size());
245c0981da4SDimitry Andric   memcpy(R.data(), ArgBytes.data(), ArgBytes.size());
246c0981da4SDimitry Andric   P->set_value(std::move(R));
247c0981da4SDimitry Andric   return Error::success();
248c0981da4SDimitry Andric }
249c0981da4SDimitry Andric 
handleCallWrapper(uint64_t RemoteSeqNo,ExecutorAddr TagAddr,SimpleRemoteEPCArgBytesVector ArgBytes)250c0981da4SDimitry Andric void SimpleRemoteEPCServer::handleCallWrapper(
251c0981da4SDimitry Andric     uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
252c0981da4SDimitry Andric     SimpleRemoteEPCArgBytesVector ArgBytes) {
253c0981da4SDimitry Andric   D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
254c0981da4SDimitry Andric     using WrapperFnTy =
255c0981da4SDimitry Andric         shared::CWrapperFunctionResult (*)(const char *, size_t);
256c0981da4SDimitry Andric     auto *Fn = TagAddr.toPtr<WrapperFnTy>();
257c0981da4SDimitry Andric     shared::WrapperFunctionResult ResultBytes(
258c0981da4SDimitry Andric         Fn(ArgBytes.data(), ArgBytes.size()));
259c0981da4SDimitry Andric     if (auto Err = sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
260c0981da4SDimitry Andric                                ExecutorAddr(),
261c0981da4SDimitry Andric                                {ResultBytes.data(), ResultBytes.size()}))
262c0981da4SDimitry Andric       ReportError(std::move(Err));
263c0981da4SDimitry Andric   });
264c0981da4SDimitry Andric }
265c0981da4SDimitry Andric 
266c0981da4SDimitry Andric shared::WrapperFunctionResult
doJITDispatch(const void * FnTag,const char * ArgData,size_t ArgSize)267c0981da4SDimitry Andric SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData,
268c0981da4SDimitry Andric                                      size_t ArgSize) {
269c0981da4SDimitry Andric   uint64_t SeqNo;
270c0981da4SDimitry Andric   std::promise<shared::WrapperFunctionResult> ResultP;
271c0981da4SDimitry Andric   auto ResultF = ResultP.get_future();
272c0981da4SDimitry Andric   {
273c0981da4SDimitry Andric     std::lock_guard<std::mutex> Lock(ServerStateMutex);
274c0981da4SDimitry Andric     if (RunState != ServerRunning)
275c0981da4SDimitry Andric       return shared::WrapperFunctionResult::createOutOfBandError(
276c0981da4SDimitry Andric           "jit_dispatch not available (EPC server shut down)");
277c0981da4SDimitry Andric 
278c0981da4SDimitry Andric     SeqNo = getNextSeqNo();
279c0981da4SDimitry Andric     assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use");
280c0981da4SDimitry Andric     PendingJITDispatchResults[SeqNo] = &ResultP;
281c0981da4SDimitry Andric   }
282c0981da4SDimitry Andric 
283c0981da4SDimitry Andric   if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
284c0981da4SDimitry Andric                              ExecutorAddr::fromPtr(FnTag), {ArgData, ArgSize}))
285c0981da4SDimitry Andric     ReportError(std::move(Err));
286c0981da4SDimitry Andric 
287c0981da4SDimitry Andric   return ResultF.get();
288c0981da4SDimitry Andric }
289c0981da4SDimitry Andric 
290c0981da4SDimitry Andric shared::CWrapperFunctionResult
jitDispatchEntry(void * DispatchCtx,const void * FnTag,const char * ArgData,size_t ArgSize)291c0981da4SDimitry Andric SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag,
292c0981da4SDimitry Andric                                         const char *ArgData, size_t ArgSize) {
293c0981da4SDimitry Andric   return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx)
294c0981da4SDimitry Andric       ->doJITDispatch(FnTag, ArgData, ArgSize)
295c0981da4SDimitry Andric       .release();
296c0981da4SDimitry Andric }
297c0981da4SDimitry Andric 
298c0981da4SDimitry Andric } // end namespace orc
299c0981da4SDimitry Andric } // end namespace llvm
300