xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===---- SimpleRemoteEPCServer.h - EPC over abstract channel ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // EPC over simple abstract channel.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
14 #define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/FunctionExtras.h"
18 #include "llvm/Config/llvm-config.h"
19 #include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
20 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
21 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
22 #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
23 #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h"
24 #include "llvm/Support/Compiler.h"
25 #include "llvm/Support/DynamicLibrary.h"
26 #include "llvm/Support/Error.h"
27 
28 #include <condition_variable>
29 #include <future>
30 #include <memory>
31 #include <mutex>
32 
33 namespace llvm {
34 namespace orc {
35 
36 /// A simple EPC server implementation.
37 class LLVM_ABI SimpleRemoteEPCServer : public SimpleRemoteEPCTransportClient {
38 public:
39   using ReportErrorFunction = unique_function<void(Error)>;
40 
41   /// Dispatches calls to runWrapper.
42   class LLVM_ABI Dispatcher {
43   public:
44     virtual ~Dispatcher();
45     virtual void dispatch(unique_function<void()> Work) = 0;
46     virtual void shutdown() = 0;
47   };
48 
49 #if LLVM_ENABLE_THREADS
50   class LLVM_ABI ThreadDispatcher : public Dispatcher {
51   public:
52     void dispatch(unique_function<void()> Work) override;
53     void shutdown() override;
54 
55   private:
56     std::mutex DispatchMutex;
57     bool Running = true;
58     size_t Outstanding = 0;
59     std::condition_variable OutstandingCV;
60   };
61 #endif
62 
63   class Setup {
64     friend class SimpleRemoteEPCServer;
65 
66   public:
server()67     SimpleRemoteEPCServer &server() { return S; }
bootstrapMap()68     StringMap<std::vector<char>> &bootstrapMap() { return BootstrapMap; }
69     template <typename T, typename SPSTagT>
setBootstrapMapValue(std::string Key,const T & Value)70     void setBootstrapMapValue(std::string Key, const T &Value) {
71       std::vector<char> Buffer;
72       Buffer.resize(shared::SPSArgList<SPSTagT>::size(Value));
73       shared::SPSOutputBuffer OB(Buffer.data(), Buffer.size());
74       bool Success = shared::SPSArgList<SPSTagT>::serialize(OB, Value);
75       (void)Success;
76       assert(Success && "Bootstrap map value serialization failed");
77       BootstrapMap[std::move(Key)] = std::move(Buffer);
78     }
bootstrapSymbols()79     StringMap<ExecutorAddr> &bootstrapSymbols() { return BootstrapSymbols; }
services()80     std::vector<std::unique_ptr<ExecutorBootstrapService>> &services() {
81       return Services;
82     }
setDispatcher(std::unique_ptr<Dispatcher> D)83     void setDispatcher(std::unique_ptr<Dispatcher> D) { S.D = std::move(D); }
setErrorReporter(unique_function<void (Error)> ReportError)84     void setErrorReporter(unique_function<void(Error)> ReportError) {
85       S.ReportError = std::move(ReportError);
86     }
87 
88   private:
Setup(SimpleRemoteEPCServer & S)89     Setup(SimpleRemoteEPCServer &S) : S(S) {}
90     SimpleRemoteEPCServer &S;
91     StringMap<std::vector<char>> BootstrapMap;
92     StringMap<ExecutorAddr> BootstrapSymbols;
93     std::vector<std::unique_ptr<ExecutorBootstrapService>> Services;
94   };
95 
96   static StringMap<ExecutorAddr> defaultBootstrapSymbols();
97 
98   template <typename TransportT, typename... TransportTCtorArgTs>
99   static Expected<std::unique_ptr<SimpleRemoteEPCServer>>
Create(unique_function<Error (Setup & S)> SetupFunction,TransportTCtorArgTs &&...TransportTCtorArgs)100   Create(unique_function<Error(Setup &S)> SetupFunction,
101          TransportTCtorArgTs &&...TransportTCtorArgs) {
102     auto Server = std::make_unique<SimpleRemoteEPCServer>();
103     Setup S(*Server);
104     if (auto Err = SetupFunction(S))
105       return std::move(Err);
106 
107     // Set ReportError up-front so that it can be used if construction
108     // process fails.
109     if (!Server->ReportError)
110       Server->ReportError = [](Error Err) {
111         logAllUnhandledErrors(std::move(Err), errs(), "SimpleRemoteEPCServer ");
112       };
113 
114     // Attempt to create transport.
115     auto T = TransportT::Create(
116         *Server, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...);
117     if (!T)
118       return T.takeError();
119     Server->T = std::move(*T);
120     if (auto Err = Server->T->start())
121       return std::move(Err);
122 
123     // If transport creation succeeds then start up services.
124     Server->Services = std::move(S.services());
125     Server->Services.push_back(
126         std::make_unique<rt_bootstrap::SimpleExecutorDylibManager>());
127     for (auto &Service : Server->Services)
128       Service->addBootstrapSymbols(S.bootstrapSymbols());
129 
130     if (auto Err = Server->sendSetupMessage(std::move(S.BootstrapMap),
131                                             std::move(S.BootstrapSymbols)))
132       return std::move(Err);
133     return std::move(Server);
134   }
135 
136   /// Set an error reporter for this server.
setErrorReporter(ReportErrorFunction ReportError)137   void setErrorReporter(ReportErrorFunction ReportError) {
138     this->ReportError = std::move(ReportError);
139   }
140 
141   /// Call to handle an incoming message.
142   ///
143   /// Returns 'Disconnect' if the message is a 'detach' message from the remote
144   /// otherwise returns 'Continue'. If the server has moved to an error state,
145   /// returns an error, which should be reported and treated as a 'Disconnect'.
146   Expected<HandleMessageAction>
147   handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
148                 SimpleRemoteEPCArgBytesVector ArgBytes) override;
149 
150   Error waitForDisconnect();
151 
152   void handleDisconnect(Error Err) override;
153 
154 private:
155   Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
156                     ExecutorAddr TagAddr, ArrayRef<char> ArgBytes);
157 
158   Error sendSetupMessage(StringMap<std::vector<char>> BootstrapMap,
159                          StringMap<ExecutorAddr> BootstrapSymbols);
160 
161   Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
162                      SimpleRemoteEPCArgBytesVector ArgBytes);
163   void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
164                          SimpleRemoteEPCArgBytesVector ArgBytes);
165 
166   shared::WrapperFunctionResult
167   doJITDispatch(const void *FnTag, const char *ArgData, size_t ArgSize);
168 
169   static shared::CWrapperFunctionResult jitDispatchEntry(void *DispatchCtx,
170                                                          const void *FnTag,
171                                                          const char *ArgData,
172                                                          size_t ArgSize);
173 
getNextSeqNo()174   uint64_t getNextSeqNo() { return NextSeqNo++; }
releaseSeqNo(uint64_t)175   void releaseSeqNo(uint64_t) {}
176 
177   using PendingJITDispatchResultsMap =
178       DenseMap<uint64_t, std::promise<shared::WrapperFunctionResult> *>;
179 
180   std::mutex ServerStateMutex;
181   std::condition_variable ShutdownCV;
182   enum { ServerRunning, ServerShuttingDown, ServerShutDown } RunState;
183   Error ShutdownErr = Error::success();
184   std::unique_ptr<SimpleRemoteEPCTransport> T;
185   std::unique_ptr<Dispatcher> D;
186   std::vector<std::unique_ptr<ExecutorBootstrapService>> Services;
187   ReportErrorFunction ReportError;
188 
189   uint64_t NextSeqNo = 0;
190   PendingJITDispatchResultsMap PendingJITDispatchResults;
191   std::vector<sys::DynamicLibrary> Dylibs;
192 };
193 
194 } // end namespace orc
195 } // end namespace llvm
196 
197 #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
198