Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp
39606 views
//===------ SimpleRemoteEPCUtils.cpp - Utils for Simple Remote EPC --------===//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//===----------------------------------------------------------------------===//7//8// Message definitions and other utilities for SimpleRemoteEPC and9// SimpleRemoteEPCServer.10//11//===----------------------------------------------------------------------===//1213#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"14#include "llvm/Support/Endian.h"15#include "llvm/Support/FormatVariadic.h"1617#if !defined(_MSC_VER) && !defined(__MINGW32__)18#include <unistd.h>19#else20#include <io.h>21#endif2223namespace {2425struct FDMsgHeader {26static constexpr unsigned MsgSizeOffset = 0;27static constexpr unsigned OpCOffset = MsgSizeOffset + sizeof(uint64_t);28static constexpr unsigned SeqNoOffset = OpCOffset + sizeof(uint64_t);29static constexpr unsigned TagAddrOffset = SeqNoOffset + sizeof(uint64_t);30static constexpr unsigned Size = TagAddrOffset + sizeof(uint64_t);31};3233} // namespace3435namespace llvm {36namespace orc {37namespace SimpleRemoteEPCDefaultBootstrapSymbolNames {3839const char *ExecutorSessionObjectName =40"__llvm_orc_SimpleRemoteEPC_dispatch_ctx";41const char *DispatchFnName = "__llvm_orc_SimpleRemoteEPC_dispatch_fn";4243} // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames4445SimpleRemoteEPCTransportClient::~SimpleRemoteEPCTransportClient() = default;46SimpleRemoteEPCTransport::~SimpleRemoteEPCTransport() = default;4748Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>49FDSimpleRemoteEPCTransport::Create(SimpleRemoteEPCTransportClient &C, int InFD,50int OutFD) {51#if LLVM_ENABLE_THREADS52if (InFD == -1)53return make_error<StringError>("Invalid input file descriptor " +54Twine(InFD),55inconvertibleErrorCode());56if (OutFD == -1)57return make_error<StringError>("Invalid output file descriptor " +58Twine(OutFD),59inconvertibleErrorCode());60std::unique_ptr<FDSimpleRemoteEPCTransport> FDT(61new FDSimpleRemoteEPCTransport(C, InFD, OutFD));62return std::move(FDT);63#else64return make_error<StringError>("FD-based SimpleRemoteEPC transport requires "65"thread support, but llvm was built with "66"LLVM_ENABLE_THREADS=Off",67inconvertibleErrorCode());68#endif69}7071FDSimpleRemoteEPCTransport::~FDSimpleRemoteEPCTransport() {72#if LLVM_ENABLE_THREADS73ListenerThread.join();74#endif75}7677Error FDSimpleRemoteEPCTransport::start() {78#if LLVM_ENABLE_THREADS79ListenerThread = std::thread([this]() { listenLoop(); });80return Error::success();81#endif82llvm_unreachable("Should not be called with LLVM_ENABLE_THREADS=Off");83}8485Error FDSimpleRemoteEPCTransport::sendMessage(SimpleRemoteEPCOpcode OpC,86uint64_t SeqNo,87ExecutorAddr TagAddr,88ArrayRef<char> ArgBytes) {89char HeaderBuffer[FDMsgHeader::Size];9091*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::MsgSizeOffset)) =92FDMsgHeader::Size + ArgBytes.size();93*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::OpCOffset)) =94static_cast<uint64_t>(OpC);95*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::SeqNoOffset)) = SeqNo;96*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::TagAddrOffset)) =97TagAddr.getValue();9899std::lock_guard<std::mutex> Lock(M);100if (Disconnected)101return make_error<StringError>("FD-transport disconnected",102inconvertibleErrorCode());103if (int ErrNo = writeBytes(HeaderBuffer, FDMsgHeader::Size))104return errorCodeToError(std::error_code(ErrNo, std::generic_category()));105if (int ErrNo = writeBytes(ArgBytes.data(), ArgBytes.size()))106return errorCodeToError(std::error_code(ErrNo, std::generic_category()));107return Error::success();108}109110void FDSimpleRemoteEPCTransport::disconnect() {111if (Disconnected)112return; // Return if already disconnected.113114Disconnected = true;115bool CloseOutFD = InFD != OutFD;116117// Close InFD.118while (close(InFD) == -1) {119if (errno == EBADF)120break;121}122123// Close OutFD.124if (CloseOutFD) {125while (close(OutFD) == -1) {126if (errno == EBADF)127break;128}129}130}131132static Error makeUnexpectedEOFError() {133return make_error<StringError>("Unexpected end-of-file",134inconvertibleErrorCode());135}136137Error FDSimpleRemoteEPCTransport::readBytes(char *Dst, size_t Size,138bool *IsEOF) {139assert((Size == 0 || Dst) && "Attempt to read into null.");140ssize_t Completed = 0;141while (Completed < static_cast<ssize_t>(Size)) {142ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);143if (Read <= 0) {144auto ErrNo = errno;145if (Read == 0) {146if (Completed == 0 && IsEOF) {147*IsEOF = true;148return Error::success();149} else150return makeUnexpectedEOFError();151} else if (ErrNo == EAGAIN || ErrNo == EINTR)152continue;153else {154std::lock_guard<std::mutex> Lock(M);155if (Disconnected && IsEOF) { // disconnect called, pretend this is EOF.156*IsEOF = true;157return Error::success();158}159return errorCodeToError(160std::error_code(ErrNo, std::generic_category()));161}162}163Completed += Read;164}165return Error::success();166}167168int FDSimpleRemoteEPCTransport::writeBytes(const char *Src, size_t Size) {169assert((Size == 0 || Src) && "Attempt to append from null.");170ssize_t Completed = 0;171while (Completed < static_cast<ssize_t>(Size)) {172ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed);173if (Written < 0) {174auto ErrNo = errno;175if (ErrNo == EAGAIN || ErrNo == EINTR)176continue;177else178return ErrNo;179}180Completed += Written;181}182return 0;183}184185void FDSimpleRemoteEPCTransport::listenLoop() {186Error Err = Error::success();187do {188189char HeaderBuffer[FDMsgHeader::Size];190// Read the header buffer.191{192bool IsEOF = false;193if (auto Err2 = readBytes(HeaderBuffer, FDMsgHeader::Size, &IsEOF)) {194Err = joinErrors(std::move(Err), std::move(Err2));195break;196}197if (IsEOF)198break;199}200201// Decode header buffer.202uint64_t MsgSize;203SimpleRemoteEPCOpcode OpC;204uint64_t SeqNo;205ExecutorAddr TagAddr;206207MsgSize =208*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::MsgSizeOffset));209OpC = static_cast<SimpleRemoteEPCOpcode>(static_cast<uint64_t>(210*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::OpCOffset))));211SeqNo =212*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::SeqNoOffset));213TagAddr.setValue(214*((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::TagAddrOffset)));215216if (MsgSize < FDMsgHeader::Size) {217Err = joinErrors(std::move(Err),218make_error<StringError>("Message size too small",219inconvertibleErrorCode()));220break;221}222223// Read the argument bytes.224SimpleRemoteEPCArgBytesVector ArgBytes;225ArgBytes.resize(MsgSize - FDMsgHeader::Size);226if (auto Err2 = readBytes(ArgBytes.data(), ArgBytes.size())) {227Err = joinErrors(std::move(Err), std::move(Err2));228break;229}230231if (auto Action = C.handleMessage(OpC, SeqNo, TagAddr, ArgBytes)) {232if (*Action == SimpleRemoteEPCTransportClient::EndSession)233break;234} else {235Err = joinErrors(std::move(Err), Action.takeError());236break;237}238} while (true);239240// Attempt to close FDs, set Disconnected to true so that subsequent241// sendMessage calls fail.242disconnect();243244// Call up to the client to handle the disconnection.245C.handleDisconnect(std::move(Err));246}247248} // end namespace orc249} // end namespace llvm250251252