brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · e4ab2c0 Raw
251 lines · cpp
1//===------ SimpleRemoteEPCUtils.cpp - Utils for Simple Remote EPC --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Message definitions and other utilities for SimpleRemoteEPC and10// SimpleRemoteEPCServer.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"15#include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_THREADS16#include "llvm/Support/Endian.h"17 18#if !defined(_MSC_VER) && !defined(__MINGW32__)19#include <unistd.h>20#else21#include <io.h>22#endif23 24namespace {25 26struct FDMsgHeader {27  static constexpr unsigned MsgSizeOffset = 0;28  static constexpr unsigned OpCOffset = MsgSizeOffset + sizeof(uint64_t);29  static constexpr unsigned SeqNoOffset = OpCOffset + sizeof(uint64_t);30  static constexpr unsigned TagAddrOffset = SeqNoOffset + sizeof(uint64_t);31  static constexpr unsigned Size = TagAddrOffset + sizeof(uint64_t);32};33 34} // namespace35 36namespace llvm {37namespace orc {38namespace SimpleRemoteEPCDefaultBootstrapSymbolNames {39 40const char *ExecutorSessionObjectName =41    "__llvm_orc_SimpleRemoteEPC_dispatch_ctx";42const char *DispatchFnName = "__llvm_orc_SimpleRemoteEPC_dispatch_fn";43 44} // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames45 46SimpleRemoteEPCTransportClient::~SimpleRemoteEPCTransportClient() = default;47SimpleRemoteEPCTransport::~SimpleRemoteEPCTransport() = default;48 49Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>50FDSimpleRemoteEPCTransport::Create(SimpleRemoteEPCTransportClient &C, int InFD,51                                   int OutFD) {52#if LLVM_ENABLE_THREADS53  if (InFD == -1)54    return make_error<StringError>("Invalid input file descriptor " +55                                       Twine(InFD),56                                   inconvertibleErrorCode());57  if (OutFD == -1)58    return make_error<StringError>("Invalid output file descriptor " +59                                       Twine(OutFD),60                                   inconvertibleErrorCode());61  std::unique_ptr<FDSimpleRemoteEPCTransport> FDT(62      new FDSimpleRemoteEPCTransport(C, InFD, OutFD));63  return std::move(FDT);64#else65  return make_error<StringError>("FD-based SimpleRemoteEPC transport requires "66                                 "thread support, but llvm was built with "67                                 "LLVM_ENABLE_THREADS=Off",68                                 inconvertibleErrorCode());69#endif70}71 72FDSimpleRemoteEPCTransport::~FDSimpleRemoteEPCTransport() {73#if LLVM_ENABLE_THREADS74  ListenerThread.join();75#endif76}77 78Error FDSimpleRemoteEPCTransport::start() {79#if LLVM_ENABLE_THREADS80  ListenerThread = std::thread([this]() { listenLoop(); });81  return Error::success();82#endif83  llvm_unreachable("Should not be called with LLVM_ENABLE_THREADS=Off");84}85 86Error FDSimpleRemoteEPCTransport::sendMessage(SimpleRemoteEPCOpcode OpC,87                                              uint64_t SeqNo,88                                              ExecutorAddr TagAddr,89                                              ArrayRef<char> ArgBytes) {90  char HeaderBuffer[FDMsgHeader::Size];91 92  *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::MsgSizeOffset)) =93      FDMsgHeader::Size + ArgBytes.size();94  *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::OpCOffset)) =95      static_cast<uint64_t>(OpC);96  *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::SeqNoOffset)) = SeqNo;97  *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::TagAddrOffset)) =98      TagAddr.getValue();99 100  std::lock_guard<std::mutex> Lock(M);101  if (Disconnected)102    return make_error<StringError>("FD-transport disconnected",103                                   inconvertibleErrorCode());104  if (int ErrNo = writeBytes(HeaderBuffer, FDMsgHeader::Size))105    return errorCodeToError(std::error_code(ErrNo, std::generic_category()));106  if (int ErrNo = writeBytes(ArgBytes.data(), ArgBytes.size()))107    return errorCodeToError(std::error_code(ErrNo, std::generic_category()));108  return Error::success();109}110 111void FDSimpleRemoteEPCTransport::disconnect() {112  if (Disconnected)113    return; // Return if already disconnected.114 115  Disconnected = true;116  bool CloseOutFD = InFD != OutFD;117 118  // Close InFD.119  while (close(InFD) == -1) {120    if (errno == EBADF)121      break;122  }123 124  // Close OutFD.125  if (CloseOutFD) {126    while (close(OutFD) == -1) {127      if (errno == EBADF)128        break;129    }130  }131}132 133static Error makeUnexpectedEOFError() {134  return make_error<StringError>("Unexpected end-of-file",135                                 inconvertibleErrorCode());136}137 138Error FDSimpleRemoteEPCTransport::readBytes(char *Dst, size_t Size,139                                            bool *IsEOF) {140  assert((Size == 0 || Dst) && "Attempt to read into null.");141  ssize_t Completed = 0;142  while (Completed < static_cast<ssize_t>(Size)) {143    ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);144    if (Read <= 0) {145      auto ErrNo = errno;146      if (Read == 0) {147        if (Completed == 0 && IsEOF) {148          *IsEOF = true;149          return Error::success();150        } else151          return makeUnexpectedEOFError();152      } else if (ErrNo == EAGAIN || ErrNo == EINTR)153        continue;154      else {155        std::lock_guard<std::mutex> Lock(M);156        if (Disconnected && IsEOF) { // disconnect called,  pretend this is EOF.157          *IsEOF = true;158          return Error::success();159        }160        return errorCodeToError(161            std::error_code(ErrNo, std::generic_category()));162      }163    }164    Completed += Read;165  }166  return Error::success();167}168 169int FDSimpleRemoteEPCTransport::writeBytes(const char *Src, size_t Size) {170  assert((Size == 0 || Src) && "Attempt to append from null.");171  ssize_t Completed = 0;172  while (Completed < static_cast<ssize_t>(Size)) {173    ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed);174    if (Written < 0) {175      auto ErrNo = errno;176      if (ErrNo == EAGAIN || ErrNo == EINTR)177        continue;178      else179        return ErrNo;180    }181    Completed += Written;182  }183  return 0;184}185 186void FDSimpleRemoteEPCTransport::listenLoop() {187  Error Err = Error::success();188  do {189 190    char HeaderBuffer[FDMsgHeader::Size];191    // Read the header buffer.192    {193      bool IsEOF = false;194      if (auto Err2 = readBytes(HeaderBuffer, FDMsgHeader::Size, &IsEOF)) {195        Err = joinErrors(std::move(Err), std::move(Err2));196        break;197      }198      if (IsEOF)199        break;200    }201 202    // Decode header buffer.203    uint64_t MsgSize;204    SimpleRemoteEPCOpcode OpC;205    uint64_t SeqNo;206    ExecutorAddr TagAddr;207 208    MsgSize =209        *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::MsgSizeOffset));210    OpC = static_cast<SimpleRemoteEPCOpcode>(static_cast<uint64_t>(211        *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::OpCOffset))));212    SeqNo =213        *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::SeqNoOffset));214    TagAddr.setValue(215        *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::TagAddrOffset)));216 217    if (MsgSize < FDMsgHeader::Size) {218      Err = joinErrors(std::move(Err),219                       make_error<StringError>("Message size too small",220                                               inconvertibleErrorCode()));221      break;222    }223 224    // Read the argument bytes.225    SimpleRemoteEPCArgBytesVector ArgBytes;226    ArgBytes.resize(MsgSize - FDMsgHeader::Size);227    if (auto Err2 = readBytes(ArgBytes.data(), ArgBytes.size())) {228      Err = joinErrors(std::move(Err), std::move(Err2));229      break;230    }231 232    if (auto Action = C.handleMessage(OpC, SeqNo, TagAddr, ArgBytes)) {233      if (*Action == SimpleRemoteEPCTransportClient::EndSession)234        break;235    } else {236      Err = joinErrors(std::move(Err), Action.takeError());237      break;238    }239  } while (true);240 241  // Attempt to close FDs, set Disconnected to true so that subsequent242  // sendMessage calls fail.243  disconnect();244 245  // Call up to the client to handle the disconnection.246  C.handleDisconnect(std::move(Err));247}248 249} // end namespace orc250} // end namespace llvm251