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