17#define DEBUG_TYPE "orc"
28#if LLVM_ENABLE_THREADS
29void SimpleRemoteEPCServer::ThreadDispatcher::dispatch(
32 std::lock_guard<std::mutex> Lock(DispatchMutex);
38 std::thread([
this, Work = std::move(Work)]()
mutable {
40 std::lock_guard<std::mutex> Lock(DispatchMutex);
42 OutstandingCV.notify_all();
46void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() {
47 std::unique_lock<std::mutex> Lock(DispatchMutex);
49 OutstandingCV.wait(Lock, [
this]() {
return Outstanding == 0; });
65 dbgs() <<
"SimpleRemoteEPCServer::handleMessage: opc = ";
69 assert(SeqNo == 0 &&
"Non-zero SeqNo for Setup?");
70 assert(!TagAddr &&
"Non-zero TagAddr for Setup?");
74 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
75 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
81 dbgs() <<
"CallWrapper";
84 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
85 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.
size())
89 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
101 std::lock_guard<std::mutex> Lock(ServerStateMutex);
105 return std::move(Err);
109 if (
auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
110 return std::move(Err);
113 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
120 std::unique_lock<std::mutex> Lock(ServerStateMutex);
121 ShutdownCV.wait(Lock, [
this]() {
return RunState == ServerShutDown; });
122 return std::move(ShutdownErr);
126 PendingJITDispatchResultsMap TmpPending;
129 std::lock_guard<std::mutex> Lock(ServerStateMutex);
130 std::swap(TmpPending, PendingJITDispatchResults);
131 RunState = ServerShuttingDown;
135 for (
auto &KV : TmpPending)
136 KV.second->set_value(
143 while (!Services.empty()) {
145 joinErrors(std::move(ShutdownErr), Services.back()->shutdown());
149 std::lock_guard<std::mutex> Lock(ServerStateMutex);
163 Error DisconnectReason =
164 (!Err && !RemoteHangup)
169 ShutdownErr =
joinErrors(std::move(ShutdownErr), std::move(DisconnectReason));
170 RunState = ServerShutDown;
171 ShutdownCV.notify_all();
179 dbgs() <<
"SimpleRemoteEPCServer::sendMessage: opc = ";
183 assert(SeqNo == 0 &&
"Non-zero SeqNo for Setup?");
184 assert(!TagAddr &&
"Non-zero TagAddr for Setup?");
188 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
189 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
195 dbgs() <<
"CallWrapper";
198 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
199 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.
size())
202 auto Err =
T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
205 dbgs() <<
" \\--> SimpleRemoteEPC::sendMessage failed\n";
210Error SimpleRemoteEPCServer::sendSetupMessage(
211 StringMap<std::vector<char>> BootstrapMap,
212 StringMap<ExecutorAddr> BootstrapSymbols) {
214 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
216 SimpleRemoteEPCExecutorInfo EI;
226 "Dispatch context name should not be set");
228 "Dispatch function name should not be set");
234 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
235 auto SetupPacketBytes =
237 shared::SPSOutputBuffer
OB(SetupPacketBytes.data(), SetupPacketBytes.size());
238 if (!SPSSerialize::serialize(OB, EI))
243 {SetupPacketBytes.data(), SetupPacketBytes.size()});
246Error SimpleRemoteEPCServer::handleResult(
249 std::promise<shared::WrapperFunctionBuffer> *
P =
nullptr;
253 return R.takeError();
256 std::lock_guard<std::mutex> Lock(ServerStateMutex);
257 auto I = PendingJITDispatchResults.find(SeqNo);
258 if (
I == PendingJITDispatchResults.end())
263 PendingJITDispatchResults.erase(
I);
266 P->set_value(std::move(*R));
270void SimpleRemoteEPCServer::handleCallWrapper(
273 D->dispatch([
this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
275 shared::CWrapperFunctionBuffer (*)(
const char *, size_t);
276 auto *Fn = TagAddr.
toPtr<WrapperFnTy>();
277 shared::WrapperFunctionBuffer ResultBytes(
278 Fn(ArgBytes.
data(), ArgBytes.
size()));
281 ResultTag, {Payload.data(), Payload.size()}))
282 ReportError(std::move(Err));
287SimpleRemoteEPCServer::doJITDispatch(
const void *FnTag,
const char *ArgData,
290 std::promise<shared::WrapperFunctionBuffer> ResultP;
291 auto ResultF = ResultP.get_future();
293 std::lock_guard<std::mutex> Lock(ServerStateMutex);
294 if (RunState != ServerRunning)
296 "jit_dispatch not available (EPC server shut down)");
298 SeqNo = getNextSeqNo();
299 assert(!PendingJITDispatchResults.count(SeqNo) &&
"SeqNo already in use");
300 PendingJITDispatchResults[SeqNo] = &ResultP;
305 ReportError(std::move(Err));
307 return ResultF.get();
311SimpleRemoteEPCServer::jitDispatchEntry(
void *DispatchCtx,
const void *FnTag,
312 const char *ArgData,
size_t ArgSize) {
313 return reinterpret_cast<SimpleRemoteEPCServer *
>(DispatchCtx)
314 ->doJITDispatch(FnTag, ArgData, ArgSize)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
Provides a library for accessing information about this process and other processes on the operating ...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Represents an address in the executor process.
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
virtual ~ExecutorBootstrapService()
static StringMap< ExecutorAddr > defaultBootstrapSymbols()
void handleDisconnect(Error Err) override
Handle a disconnection from the underlying transport.
Expected< HandleMessageAction > handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, shared::WrapperFunctionBuffer ArgBytes) override
Call to handle an incoming message.
Error waitForDisconnect()
C++ wrapper function buffer: Same as CWrapperFunctionBuffer but auto-releases memory.
size_t size() const
Returns the size of the data contained in this instance.
static WrapperFunctionBuffer createOutOfBandError(const char *Msg)
Create an out-of-band error by copying the given string.
char * data()
Get a pointer to the data contained in this instance.
static WrapperFunctionBuffer allocate(size_t Size)
Create a WrapperFunctionBuffer with the given size and return a pointer to the underlying memory.
static LLVM_ABI Expected< unsigned > getPageSize()
Get the process's page size.
unique_function is a type-erasing functor similar to std::function.
@ OB
OB - OneByte - Set if this instruction has a one byte opcode.
LLVM_ABI const char * DispatchFnName
LLVM_ABI const char * ExecutorSessionObjectName
LLVM_ABI void addTo(StringMap< ExecutorAddr > &M)
Adds all default target-process bootstrap wrappers.
LLVM_ABI void addDefaultBootstrapValuesForHostProcess(StringMap< std::vector< char > > &BootstrapMap, StringMap< ExecutorAddr > &BootstrapSymbols)
LLVM_ABI std::pair< ExecutorAddr, shared::WrapperFunctionBuffer > encodeResultMessage(shared::WrapperFunctionBuffer ResultBytes)
Encode a wrapper function result as the TagAddr and payload of a Result message.
LLVM_ABI Error decodeHangupPayload(shared::WrapperFunctionBuffer Payload)
Decode a Hangup payload produced by encodeHangupPayload.
LLVM_ABI Expected< shared::WrapperFunctionBuffer > decodeResultMessage(ExecutorAddr TagAddr, shared::WrapperFunctionBuffer Payload)
Decode a Result message produced by encodeResultMessage, returning the result to complete the pending...
LLVM_ABI std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
StringMap< ExecutorAddr > BootstrapSymbols
StringMap< std::vector< char > > BootstrapMap