SimpleRemoteEPCServer.h 6.5 KB

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