1349cc55cSDimitry Andric //===------- SimpleEPCServer.cpp - EPC over simple abstract channel -------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric 9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h" 10349cc55cSDimitry Andric 11*5f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 12349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" 13*5f757f3fSDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 14349cc55cSDimitry Andric #include "llvm/Support/FormatVariadic.h" 15349cc55cSDimitry Andric #include "llvm/Support/Process.h" 1606c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 17349cc55cSDimitry Andric 18349cc55cSDimitry Andric #include "OrcRTBootstrap.h" 19349cc55cSDimitry Andric 20349cc55cSDimitry Andric #define DEBUG_TYPE "orc" 21349cc55cSDimitry Andric 22349cc55cSDimitry Andric using namespace llvm::orc::shared; 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric namespace llvm { 25349cc55cSDimitry Andric namespace orc { 26349cc55cSDimitry Andric 2781ad6265SDimitry Andric ExecutorBootstrapService::~ExecutorBootstrapService() = default; 28349cc55cSDimitry Andric 2981ad6265SDimitry Andric SimpleRemoteEPCServer::Dispatcher::~Dispatcher() = default; 30349cc55cSDimitry Andric 31349cc55cSDimitry Andric #if LLVM_ENABLE_THREADS 32349cc55cSDimitry Andric void SimpleRemoteEPCServer::ThreadDispatcher::dispatch( 33349cc55cSDimitry Andric unique_function<void()> Work) { 34349cc55cSDimitry Andric { 35349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex); 36349cc55cSDimitry Andric if (!Running) 37349cc55cSDimitry Andric return; 38349cc55cSDimitry Andric ++Outstanding; 39349cc55cSDimitry Andric } 40349cc55cSDimitry Andric 41349cc55cSDimitry Andric std::thread([this, Work = std::move(Work)]() mutable { 42349cc55cSDimitry Andric Work(); 43349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(DispatchMutex); 44349cc55cSDimitry Andric --Outstanding; 45349cc55cSDimitry Andric OutstandingCV.notify_all(); 46349cc55cSDimitry Andric }).detach(); 47349cc55cSDimitry Andric } 48349cc55cSDimitry Andric 49349cc55cSDimitry Andric void SimpleRemoteEPCServer::ThreadDispatcher::shutdown() { 50349cc55cSDimitry Andric std::unique_lock<std::mutex> Lock(DispatchMutex); 51349cc55cSDimitry Andric Running = false; 52349cc55cSDimitry Andric OutstandingCV.wait(Lock, [this]() { return Outstanding == 0; }); 53349cc55cSDimitry Andric } 54349cc55cSDimitry Andric #endif 55349cc55cSDimitry Andric 56349cc55cSDimitry Andric StringMap<ExecutorAddr> SimpleRemoteEPCServer::defaultBootstrapSymbols() { 57349cc55cSDimitry Andric StringMap<ExecutorAddr> DBS; 58349cc55cSDimitry Andric rt_bootstrap::addTo(DBS); 59349cc55cSDimitry Andric return DBS; 60349cc55cSDimitry Andric } 61349cc55cSDimitry Andric 62349cc55cSDimitry Andric Expected<SimpleRemoteEPCTransportClient::HandleMessageAction> 63349cc55cSDimitry Andric SimpleRemoteEPCServer::handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 64349cc55cSDimitry Andric ExecutorAddr TagAddr, 65349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) { 66349cc55cSDimitry Andric 67349cc55cSDimitry Andric LLVM_DEBUG({ 68349cc55cSDimitry Andric dbgs() << "SimpleRemoteEPCServer::handleMessage: opc = "; 69349cc55cSDimitry Andric switch (OpC) { 70349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Setup: 71349cc55cSDimitry Andric dbgs() << "Setup"; 72349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Setup?"); 7306c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Setup?"); 74349cc55cSDimitry Andric break; 75349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Hangup: 76349cc55cSDimitry Andric dbgs() << "Hangup"; 77349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?"); 7806c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Hangup?"); 79349cc55cSDimitry Andric break; 80349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Result: 81349cc55cSDimitry Andric dbgs() << "Result"; 8206c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Result?"); 83349cc55cSDimitry Andric break; 84349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::CallWrapper: 85349cc55cSDimitry Andric dbgs() << "CallWrapper"; 86349cc55cSDimitry Andric break; 87349cc55cSDimitry Andric } 8806c3fb27SDimitry Andric dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr 89349cc55cSDimitry Andric << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size()) 90349cc55cSDimitry Andric << " bytes\n"; 91349cc55cSDimitry Andric }); 92349cc55cSDimitry Andric 93349cc55cSDimitry Andric using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>; 94349cc55cSDimitry Andric if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC)) 95349cc55cSDimitry Andric return make_error<StringError>("Unexpected opcode", 96349cc55cSDimitry Andric inconvertibleErrorCode()); 97349cc55cSDimitry Andric 98349cc55cSDimitry Andric // TODO: Clean detach message? 99349cc55cSDimitry Andric switch (OpC) { 100349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Setup: 101349cc55cSDimitry Andric return make_error<StringError>("Unexpected Setup opcode", 102349cc55cSDimitry Andric inconvertibleErrorCode()); 103349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Hangup: 104349cc55cSDimitry Andric return SimpleRemoteEPCTransportClient::EndSession; 105349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Result: 106349cc55cSDimitry Andric if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes))) 107349cc55cSDimitry Andric return std::move(Err); 108349cc55cSDimitry Andric break; 109349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::CallWrapper: 110349cc55cSDimitry Andric handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes)); 111349cc55cSDimitry Andric break; 112349cc55cSDimitry Andric } 113349cc55cSDimitry Andric return ContinueSession; 114349cc55cSDimitry Andric } 115349cc55cSDimitry Andric 116349cc55cSDimitry Andric Error SimpleRemoteEPCServer::waitForDisconnect() { 117349cc55cSDimitry Andric std::unique_lock<std::mutex> Lock(ServerStateMutex); 118349cc55cSDimitry Andric ShutdownCV.wait(Lock, [this]() { return RunState == ServerShutDown; }); 119349cc55cSDimitry Andric return std::move(ShutdownErr); 120349cc55cSDimitry Andric } 121349cc55cSDimitry Andric 122349cc55cSDimitry Andric void SimpleRemoteEPCServer::handleDisconnect(Error Err) { 123349cc55cSDimitry Andric PendingJITDispatchResultsMap TmpPending; 124349cc55cSDimitry Andric 125349cc55cSDimitry Andric { 126349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex); 127349cc55cSDimitry Andric std::swap(TmpPending, PendingJITDispatchResults); 128349cc55cSDimitry Andric RunState = ServerShuttingDown; 129349cc55cSDimitry Andric } 130349cc55cSDimitry Andric 131349cc55cSDimitry Andric // Send out-of-band errors to any waiting threads. 132349cc55cSDimitry Andric for (auto &KV : TmpPending) 133349cc55cSDimitry Andric KV.second->set_value( 134349cc55cSDimitry Andric shared::WrapperFunctionResult::createOutOfBandError("disconnecting")); 135349cc55cSDimitry Andric 136349cc55cSDimitry Andric // Wait for dispatcher to clear. 137349cc55cSDimitry Andric D->shutdown(); 138349cc55cSDimitry Andric 139349cc55cSDimitry Andric // Shut down services. 140349cc55cSDimitry Andric while (!Services.empty()) { 141349cc55cSDimitry Andric ShutdownErr = 142349cc55cSDimitry Andric joinErrors(std::move(ShutdownErr), Services.back()->shutdown()); 143349cc55cSDimitry Andric Services.pop_back(); 144349cc55cSDimitry Andric } 145349cc55cSDimitry Andric 146349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex); 147349cc55cSDimitry Andric ShutdownErr = joinErrors(std::move(ShutdownErr), std::move(Err)); 148349cc55cSDimitry Andric RunState = ServerShutDown; 149349cc55cSDimitry Andric ShutdownCV.notify_all(); 150349cc55cSDimitry Andric } 151349cc55cSDimitry Andric 152349cc55cSDimitry Andric Error SimpleRemoteEPCServer::sendMessage(SimpleRemoteEPCOpcode OpC, 153349cc55cSDimitry Andric uint64_t SeqNo, ExecutorAddr TagAddr, 154349cc55cSDimitry Andric ArrayRef<char> ArgBytes) { 155349cc55cSDimitry Andric 156349cc55cSDimitry Andric LLVM_DEBUG({ 157349cc55cSDimitry Andric dbgs() << "SimpleRemoteEPCServer::sendMessage: opc = "; 158349cc55cSDimitry Andric switch (OpC) { 159349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Setup: 160349cc55cSDimitry Andric dbgs() << "Setup"; 161349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Setup?"); 16206c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Setup?"); 163349cc55cSDimitry Andric break; 164349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Hangup: 165349cc55cSDimitry Andric dbgs() << "Hangup"; 166349cc55cSDimitry Andric assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?"); 16706c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Hangup?"); 168349cc55cSDimitry Andric break; 169349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::Result: 170349cc55cSDimitry Andric dbgs() << "Result"; 17106c3fb27SDimitry Andric assert(!TagAddr && "Non-zero TagAddr for Result?"); 172349cc55cSDimitry Andric break; 173349cc55cSDimitry Andric case SimpleRemoteEPCOpcode::CallWrapper: 174349cc55cSDimitry Andric dbgs() << "CallWrapper"; 175349cc55cSDimitry Andric break; 176349cc55cSDimitry Andric } 17706c3fb27SDimitry Andric dbgs() << ", seqno = " << SeqNo << ", tag-addr = " << TagAddr 178349cc55cSDimitry Andric << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size()) 179349cc55cSDimitry Andric << " bytes\n"; 180349cc55cSDimitry Andric }); 181349cc55cSDimitry Andric auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes); 182349cc55cSDimitry Andric LLVM_DEBUG({ 183349cc55cSDimitry Andric if (Err) 184349cc55cSDimitry Andric dbgs() << " \\--> SimpleRemoteEPC::sendMessage failed\n"; 185349cc55cSDimitry Andric }); 186349cc55cSDimitry Andric return Err; 187349cc55cSDimitry Andric } 188349cc55cSDimitry Andric 189349cc55cSDimitry Andric Error SimpleRemoteEPCServer::sendSetupMessage( 19006c3fb27SDimitry Andric StringMap<std::vector<char>> BootstrapMap, 191349cc55cSDimitry Andric StringMap<ExecutorAddr> BootstrapSymbols) { 192349cc55cSDimitry Andric 193349cc55cSDimitry Andric using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames; 194349cc55cSDimitry Andric 195349cc55cSDimitry Andric std::vector<char> SetupPacket; 196349cc55cSDimitry Andric SimpleRemoteEPCExecutorInfo EI; 197349cc55cSDimitry Andric EI.TargetTriple = sys::getProcessTriple(); 198349cc55cSDimitry Andric if (auto PageSize = sys::Process::getPageSize()) 199349cc55cSDimitry Andric EI.PageSize = *PageSize; 200349cc55cSDimitry Andric else 201349cc55cSDimitry Andric return PageSize.takeError(); 20206c3fb27SDimitry Andric EI.BootstrapMap = std::move(BootstrapMap); 203349cc55cSDimitry Andric EI.BootstrapSymbols = std::move(BootstrapSymbols); 204349cc55cSDimitry Andric 205349cc55cSDimitry Andric assert(!EI.BootstrapSymbols.count(ExecutorSessionObjectName) && 206349cc55cSDimitry Andric "Dispatch context name should not be set"); 207349cc55cSDimitry Andric assert(!EI.BootstrapSymbols.count(DispatchFnName) && 208349cc55cSDimitry Andric "Dispatch function name should not be set"); 209349cc55cSDimitry Andric EI.BootstrapSymbols[ExecutorSessionObjectName] = ExecutorAddr::fromPtr(this); 210349cc55cSDimitry Andric EI.BootstrapSymbols[DispatchFnName] = ExecutorAddr::fromPtr(jitDispatchEntry); 211*5f757f3fSDimitry Andric EI.BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] = 212*5f757f3fSDimitry Andric ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper); 213*5f757f3fSDimitry Andric EI.BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] = 214*5f757f3fSDimitry Andric ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper); 215349cc55cSDimitry Andric 216349cc55cSDimitry Andric using SPSSerialize = 217349cc55cSDimitry Andric shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>; 218349cc55cSDimitry Andric auto SetupPacketBytes = 219349cc55cSDimitry Andric shared::WrapperFunctionResult::allocate(SPSSerialize::size(EI)); 220349cc55cSDimitry Andric shared::SPSOutputBuffer OB(SetupPacketBytes.data(), SetupPacketBytes.size()); 221349cc55cSDimitry Andric if (!SPSSerialize::serialize(OB, EI)) 222349cc55cSDimitry Andric return make_error<StringError>("Could not send setup packet", 223349cc55cSDimitry Andric inconvertibleErrorCode()); 224349cc55cSDimitry Andric 225349cc55cSDimitry Andric return sendMessage(SimpleRemoteEPCOpcode::Setup, 0, ExecutorAddr(), 226349cc55cSDimitry Andric {SetupPacketBytes.data(), SetupPacketBytes.size()}); 227349cc55cSDimitry Andric } 228349cc55cSDimitry Andric 229349cc55cSDimitry Andric Error SimpleRemoteEPCServer::handleResult( 230349cc55cSDimitry Andric uint64_t SeqNo, ExecutorAddr TagAddr, 231349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) { 232349cc55cSDimitry Andric std::promise<shared::WrapperFunctionResult> *P = nullptr; 233349cc55cSDimitry Andric { 234349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex); 235349cc55cSDimitry Andric auto I = PendingJITDispatchResults.find(SeqNo); 236349cc55cSDimitry Andric if (I == PendingJITDispatchResults.end()) 237349cc55cSDimitry Andric return make_error<StringError>("No call for sequence number " + 238349cc55cSDimitry Andric Twine(SeqNo), 239349cc55cSDimitry Andric inconvertibleErrorCode()); 240349cc55cSDimitry Andric P = I->second; 241349cc55cSDimitry Andric PendingJITDispatchResults.erase(I); 242349cc55cSDimitry Andric releaseSeqNo(SeqNo); 243349cc55cSDimitry Andric } 244349cc55cSDimitry Andric auto R = shared::WrapperFunctionResult::allocate(ArgBytes.size()); 245349cc55cSDimitry Andric memcpy(R.data(), ArgBytes.data(), ArgBytes.size()); 246349cc55cSDimitry Andric P->set_value(std::move(R)); 247349cc55cSDimitry Andric return Error::success(); 248349cc55cSDimitry Andric } 249349cc55cSDimitry Andric 250349cc55cSDimitry Andric void SimpleRemoteEPCServer::handleCallWrapper( 251349cc55cSDimitry Andric uint64_t RemoteSeqNo, ExecutorAddr TagAddr, 252349cc55cSDimitry Andric SimpleRemoteEPCArgBytesVector ArgBytes) { 253349cc55cSDimitry Andric D->dispatch([this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() { 254349cc55cSDimitry Andric using WrapperFnTy = 255349cc55cSDimitry Andric shared::CWrapperFunctionResult (*)(const char *, size_t); 256349cc55cSDimitry Andric auto *Fn = TagAddr.toPtr<WrapperFnTy>(); 257349cc55cSDimitry Andric shared::WrapperFunctionResult ResultBytes( 258349cc55cSDimitry Andric Fn(ArgBytes.data(), ArgBytes.size())); 259349cc55cSDimitry Andric if (auto Err = sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo, 260349cc55cSDimitry Andric ExecutorAddr(), 261349cc55cSDimitry Andric {ResultBytes.data(), ResultBytes.size()})) 262349cc55cSDimitry Andric ReportError(std::move(Err)); 263349cc55cSDimitry Andric }); 264349cc55cSDimitry Andric } 265349cc55cSDimitry Andric 266349cc55cSDimitry Andric shared::WrapperFunctionResult 267349cc55cSDimitry Andric SimpleRemoteEPCServer::doJITDispatch(const void *FnTag, const char *ArgData, 268349cc55cSDimitry Andric size_t ArgSize) { 269349cc55cSDimitry Andric uint64_t SeqNo; 270349cc55cSDimitry Andric std::promise<shared::WrapperFunctionResult> ResultP; 271349cc55cSDimitry Andric auto ResultF = ResultP.get_future(); 272349cc55cSDimitry Andric { 273349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(ServerStateMutex); 274349cc55cSDimitry Andric if (RunState != ServerRunning) 275349cc55cSDimitry Andric return shared::WrapperFunctionResult::createOutOfBandError( 276349cc55cSDimitry Andric "jit_dispatch not available (EPC server shut down)"); 277349cc55cSDimitry Andric 278349cc55cSDimitry Andric SeqNo = getNextSeqNo(); 279349cc55cSDimitry Andric assert(!PendingJITDispatchResults.count(SeqNo) && "SeqNo already in use"); 280349cc55cSDimitry Andric PendingJITDispatchResults[SeqNo] = &ResultP; 281349cc55cSDimitry Andric } 282349cc55cSDimitry Andric 283349cc55cSDimitry Andric if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo, 284349cc55cSDimitry Andric ExecutorAddr::fromPtr(FnTag), {ArgData, ArgSize})) 285349cc55cSDimitry Andric ReportError(std::move(Err)); 286349cc55cSDimitry Andric 287349cc55cSDimitry Andric return ResultF.get(); 288349cc55cSDimitry Andric } 289349cc55cSDimitry Andric 290349cc55cSDimitry Andric shared::CWrapperFunctionResult 291349cc55cSDimitry Andric SimpleRemoteEPCServer::jitDispatchEntry(void *DispatchCtx, const void *FnTag, 292349cc55cSDimitry Andric const char *ArgData, size_t ArgSize) { 293349cc55cSDimitry Andric return reinterpret_cast<SimpleRemoteEPCServer *>(DispatchCtx) 294349cc55cSDimitry Andric ->doJITDispatch(FnTag, ArgData, ArgSize) 295349cc55cSDimitry Andric .release(); 296349cc55cSDimitry Andric } 297349cc55cSDimitry Andric 298349cc55cSDimitry Andric } // end namespace orc 299349cc55cSDimitry Andric } // end namespace llvm 300