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