1 //===---- SimpleRemoteEPCServer.h - EPC over abstract channel ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // EPC over simple abstract channel.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
14 #define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
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/DynamicLibrary.h"
25 #include "llvm/Support/Error.h"
27 #include <condition_variable>
35 /// A simple EPC server implementation.
36 class SimpleRemoteEPCServer : public SimpleRemoteEPCTransportClient {
38 using ReportErrorFunction = unique_function<void(Error)>;
40 /// Dispatches calls to runWrapper.
43 virtual ~Dispatcher();
44 virtual void dispatch(unique_function<void()> Work) = 0;
45 virtual void shutdown() = 0;
48 #if LLVM_ENABLE_THREADS
49 class ThreadDispatcher : public Dispatcher {
51 void dispatch(unique_function<void()> Work) override;
52 void shutdown() override;
55 std::mutex DispatchMutex;
57 size_t Outstanding = 0;
58 std::condition_variable OutstandingCV;
63 friend class SimpleRemoteEPCServer;
66 SimpleRemoteEPCServer &server() { return S; }
67 StringMap<ExecutorAddr> &bootstrapSymbols() { return BootstrapSymbols; }
68 std::vector<std::unique_ptr<ExecutorBootstrapService>> &services() {
71 void setDispatcher(std::unique_ptr<Dispatcher> D) { S.D = std::move(D); }
72 void setErrorReporter(unique_function<void(Error)> ReportError) {
73 S.ReportError = std::move(ReportError);
77 Setup(SimpleRemoteEPCServer &S) : S(S) {}
78 SimpleRemoteEPCServer &S;
79 StringMap<ExecutorAddr> BootstrapSymbols;
80 std::vector<std::unique_ptr<ExecutorBootstrapService>> Services;
83 static StringMap<ExecutorAddr> defaultBootstrapSymbols();
85 template <typename TransportT, typename... TransportTCtorArgTs>
86 static Expected<std::unique_ptr<SimpleRemoteEPCServer>>
87 Create(unique_function<Error(Setup &S)> SetupFunction,
88 TransportTCtorArgTs &&...TransportTCtorArgs) {
89 auto Server = std::make_unique<SimpleRemoteEPCServer>();
91 if (auto Err = SetupFunction(S))
92 return std::move(Err);
94 // Set ReportError up-front so that it can be used if construction
96 if (!Server->ReportError)
97 Server->ReportError = [](Error Err) {
98 logAllUnhandledErrors(std::move(Err), errs(), "SimpleRemoteEPCServer ");
101 // Attempt to create transport.
102 auto T = TransportT::Create(
103 *Server, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...);
105 return T.takeError();
106 Server->T = std::move(*T);
107 if (auto Err = Server->T->start())
108 return std::move(Err);
110 // If transport creation succeeds then start up services.
111 Server->Services = std::move(S.services());
112 Server->Services.push_back(
113 std::make_unique<rt_bootstrap::SimpleExecutorDylibManager>());
114 for (auto &Service : Server->Services)
115 Service->addBootstrapSymbols(S.bootstrapSymbols());
117 if (auto Err = Server->sendSetupMessage(std::move(S.BootstrapSymbols)))
118 return std::move(Err);
119 return std::move(Server);
122 /// Set an error reporter for this server.
123 void setErrorReporter(ReportErrorFunction ReportError) {
124 this->ReportError = std::move(ReportError);
127 /// Call to handle an incoming message.
129 /// Returns 'Disconnect' if the message is a 'detach' message from the remote
130 /// otherwise returns 'Continue'. If the server has moved to an error state,
131 /// returns an error, which should be reported and treated as a 'Disconnect'.
132 Expected<HandleMessageAction>
133 handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
134 SimpleRemoteEPCArgBytesVector ArgBytes) override;
136 Error waitForDisconnect();
138 void handleDisconnect(Error Err) override;
141 Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
142 ExecutorAddr TagAddr, ArrayRef<char> ArgBytes);
144 Error sendSetupMessage(StringMap<ExecutorAddr> BootstrapSymbols);
146 Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
147 SimpleRemoteEPCArgBytesVector ArgBytes);
148 void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
149 SimpleRemoteEPCArgBytesVector ArgBytes);
151 shared::WrapperFunctionResult
152 doJITDispatch(const void *FnTag, const char *ArgData, size_t ArgSize);
154 static shared::CWrapperFunctionResult jitDispatchEntry(void *DispatchCtx,
159 uint64_t getNextSeqNo() { return NextSeqNo++; }
160 void releaseSeqNo(uint64_t) {}
162 using PendingJITDispatchResultsMap =
163 DenseMap<uint64_t, std::promise<shared::WrapperFunctionResult> *>;
165 std::mutex ServerStateMutex;
166 std::condition_variable ShutdownCV;
167 enum { ServerRunning, ServerShuttingDown, ServerShutDown } RunState;
168 Error ShutdownErr = Error::success();
169 std::unique_ptr<SimpleRemoteEPCTransport> T;
170 std::unique_ptr<Dispatcher> D;
171 std::vector<std::unique_ptr<ExecutorBootstrapService>> Services;
172 ReportErrorFunction ReportError;
174 uint64_t NextSeqNo = 0;
175 PendingJITDispatchResultsMap PendingJITDispatchResults;
176 std::vector<sys::DynamicLibrary> Dylibs;
179 } // end namespace orc
180 } // end namespace llvm
182 #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H