Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp
35323 views
//===------- SimpleEPCServer.cpp - EPC over simple abstract channel -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h"910#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"11#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"12#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"13#include "llvm/Support/FormatVariadic.h"14#include "llvm/Support/Process.h"15#include "llvm/TargetParser/Host.h"1617#include "OrcRTBootstrap.h"1819#define DEBUG_TYPE "orc"2021using namespace llvm::orc::shared;2223namespace llvm {24namespace orc {2526ExecutorBootstrapService::~ExecutorBootstrapService() = default;2728SimpleRemoteEPCServer::Dispatcher::~Dispatcher() = default;2930#if LLVM_ENABLE_THREADS31void SimpleRemoteEPCServer::ThreadDispatcher::dispatch(32unique_function<void()> Work) {33{34std::lock_guard<std::mutex> Lock(DispatchMutex);35if (!Running)36return;37++Outstanding;38}3940std::thread([this, Work = std::move(Work)]() mutable {41Work();42std::lock_guard<std::mutex> Lock(DispatchMutex);43--Outstanding;44OutstandingCV.notify_all();45}).detach();46}4748void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() {49std::unique_lock<std::mutex> Lock(DispatchMutex);50Running = false;51OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; });52}53#endif5455StringMap<ExecutorAddr> SimpleRemoteEPCServer::defaultBootstrapSymbols() {56StringMap<ExecutorAddr> DBS;57rt_bootstrap::addTo(DBS);58return DBS;59}6061Expected<SimpleRemoteEPCTransportClient::HandleMessageAction>62SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,63ExecutorAddr TagAddr,64SimpleRemoteEPCArgBytesVector ArgBytes) {6566LLVM_DEBUG({67dbgs() << "SimpleRemoteEPCServer::handleMessage: opc = ";68switch (OpC) {69case SimpleRemoteEPCOpcode::Setup:70dbgs() << "Setup";71assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");72assert(!TagAddr && "Non-zero TagAddr for Setup?");73break;74case SimpleRemoteEPCOpcode::Hangup:75dbgs() << "Hangup";76assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");77assert(!TagAddr && "Non-zero TagAddr for Hangup?");78break;79case SimpleRemoteEPCOpcode::Result:80dbgs() << "Result";81assert(!TagAddr && "Non-zero TagAddr for Result?");82break;83case SimpleRemoteEPCOpcode::CallWrapper:84dbgs() << "CallWrapper";85break;86}87dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr88<< ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())89<< " bytes\n";90});9192using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;93if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))94return make_error<StringError>("Unexpected opcode",95inconvertibleErrorCode());9697// TODO: Clean detach message?98switch (OpC) {99case SimpleRemoteEPCOpcode::Setup:100return make_error<StringError>("Unexpected Setup opcode",101inconvertibleErrorCode());102case SimpleRemoteEPCOpcode::Hangup:103return SimpleRemoteEPCTransportClient::EndSession;104case SimpleRemoteEPCOpcode::Result:105if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))106return std::move(Err);107break;108case SimpleRemoteEPCOpcode::CallWrapper:109handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));110break;111}112return ContinueSession;113}114115Error SimpleRemoteEPCServer::waitForDisconnect() {116std::unique_lock<std::mutex> Lock(ServerStateMutex);117ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; });118return std::move(ShutdownErr);119}120121void SimpleRemoteEPCServer::handleDisconnect(Error Err) {122PendingJITDispatchResultsMap TmpPending;123124{125std::lock_guard<std::mutex> Lock(ServerStateMutex);126std::swap(TmpPending, PendingJITDispatchResults);127RunState = ServerShuttingDown;128}129130// Send out-of-band errors to any waiting threads.131for (auto &KV : TmpPending)132KV.second->set_value(133shared::WrapperFunctionResult::createOutOfBandError("disconnecting"));134135// Wait for dispatcher to clear.136D->shutdown();137138// Shut down services.139while (!Services.empty()) {140ShutdownErr =141joinErrors(std::move(ShutdownErr), Services.back()->shutdown());142Services.pop_back();143}144145std::lock_guard<std::mutex> Lock(ServerStateMutex);146ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err));147RunState = ServerShutDown;148ShutdownCV.notify_all();149}150151Error SimpleRemoteEPCServer::sendMessage(SimpleRemoteEPCOpcode OpC,152uint64_t SeqNo, ExecutorAddr TagAddr,153ArrayRef<char> ArgBytes) {154155LLVM_DEBUG({156dbgs() << "SimpleRemoteEPCServer::sendMessage: opc = ";157switch (OpC) {158case SimpleRemoteEPCOpcode::Setup:159dbgs() << "Setup";160assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");161assert(!TagAddr && "Non-zero TagAddr for Setup?");162break;163case SimpleRemoteEPCOpcode::Hangup:164dbgs() << "Hangup";165assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");166assert(!TagAddr && "Non-zero TagAddr for Hangup?");167break;168case SimpleRemoteEPCOpcode::Result:169dbgs() << "Result";170assert(!TagAddr && "Non-zero TagAddr for Result?");171break;172case SimpleRemoteEPCOpcode::CallWrapper:173dbgs() << "CallWrapper";174break;175}176dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr177<< ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())178<< " bytes\n";179});180auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);181LLVM_DEBUG({182if (Err)183dbgs() << " \\--> SimpleRemoteEPC::sendMessage failed\n";184});185return Err;186}187188Error SimpleRemoteEPCServer::sendSetupMessage(189StringMap<std::vector<char>> BootstrapMap,190StringMap<ExecutorAddr> BootstrapSymbols) {191192using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;193194std::vector<char> SetupPacket;195SimpleRemoteEPCExecutorInfo EI;196EI.TargetTriple = sys::getProcessTriple();197if (auto PageSize = sys::Process::getPageSize())198EI.PageSize = *PageSize;199else200return PageSize.takeError();201EI.BootstrapMap = std::move(BootstrapMap);202EI.BootstrapSymbols = std::move(BootstrapSymbols);203204assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) &&205"Dispatch context name should not be set");206assert(!EI.BootstrapSymbols.count(DispatchFnName) &&207"Dispatch function name should not be set");208EI.BootstrapSymbols[ExecutorSessionObjectName] = ExecutorAddr::fromPtr(this);209EI.BootstrapSymbols[DispatchFnName] = ExecutorAddr::fromPtr(jitDispatchEntry);210EI.BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] =211ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper);212EI.BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] =213ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);214215using SPSSerialize =216shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;217auto SetupPacketBytes =218shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI));219shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size());220if (!SPSSerialize::serialize(OB, EI))221return make_error<StringError>("Could not send setup packet",222inconvertibleErrorCode());223224return sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddr(),225{SetupPacketBytes.data(), SetupPacketBytes.size()});226}227228Error SimpleRemoteEPCServer::handleResult(229uint64_t SeqNo, ExecutorAddr TagAddr,230SimpleRemoteEPCArgBytesVector ArgBytes) {231std::promise<shared::WrapperFunctionResult> *P = nullptr;232{233std::lock_guard<std::mutex> Lock(ServerStateMutex);234auto I = PendingJITDispatchResults.find(SeqNo);235if (I == PendingJITDispatchResults.end())236return make_error<StringError>("No call for sequence number " +237Twine(SeqNo),238inconvertibleErrorCode());239P = I->second;240PendingJITDispatchResults.erase(I);241releaseSeqNo(SeqNo);242}243auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size());244memcpy(R.data(), ArgBytes.data(), ArgBytes.size());245P->set_value(std::move(R));246return Error::success();247}248249void SimpleRemoteEPCServer::handleCallWrapper(250uint64_t RemoteSeqNo, ExecutorAddr TagAddr,251SimpleRemoteEPCArgBytesVector ArgBytes) {252D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {253using WrapperFnTy =254shared::CWrapperFunctionResult (*)(const char *, size_t);255auto *Fn = TagAddr.toPtr<WrapperFnTy>();256shared::WrapperFunctionResult ResultBytes(257Fn(ArgBytes.data(), ArgBytes.size()));258if (auto Err = sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,259ExecutorAddr(),260{ResultBytes.data(), ResultBytes.size()}))261ReportError(std::move(Err));262});263}264265shared::WrapperFunctionResult266SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData,267size_t ArgSize) {268uint64_t SeqNo;269std::promise<shared::WrapperFunctionResult> ResultP;270auto ResultF = ResultP.get_future();271{272std::lock_guard<std::mutex> Lock(ServerStateMutex);273if (RunState != ServerRunning)274return shared::WrapperFunctionResult::createOutOfBandError(275"jit_dispatch not available (EPC server shut down)");276277SeqNo = getNextSeqNo();278assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use");279PendingJITDispatchResults[SeqNo] = &ResultP;280}281282if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,283ExecutorAddr::fromPtr(FnTag), {ArgData, ArgSize}))284ReportError(std::move(Err));285286return ResultF.get();287}288289shared::CWrapperFunctionResult290SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag,291const char *ArgData, size_t ArgSize) {292return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx)293->doJITDispatch(FnTag, ArgData, ArgSize)294.release();295}296297} // end namespace orc298} // end namespace llvm299300301