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