diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp new file mode 100644 index 000000000000..64fc717b7b56 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp @@ -0,0 +1,250 @@ +//===------ SimpleRemoteEPCUtils.cpp - Utils for Simple Remote EPC --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Message definitions and other utilities for SimpleRemoteEPC and +// SimpleRemoteEPCServer. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/FormatVariadic.h" + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif + +namespace { + +struct FDMsgHeader { + static constexpr unsigned MsgSizeOffset = 0; + static constexpr unsigned OpCOffset = MsgSizeOffset + sizeof(uint64_t); + static constexpr unsigned SeqNoOffset = OpCOffset + sizeof(uint64_t); + static constexpr unsigned TagAddrOffset = SeqNoOffset + sizeof(uint64_t); + static constexpr unsigned Size = TagAddrOffset + sizeof(uint64_t); +}; + +} // namespace + +namespace llvm { +namespace orc { +namespace SimpleRemoteEPCDefaultBootstrapSymbolNames { + +const char *ExecutorSessionObjectName = + "__llvm_orc_SimpleRemoteEPC_dispatch_ctx"; +const char *DispatchFnName = "__llvm_orc_SimpleRemoteEPC_dispatch_fn"; + +} // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames + +SimpleRemoteEPCTransportClient::~SimpleRemoteEPCTransportClient() {} +SimpleRemoteEPCTransport::~SimpleRemoteEPCTransport() {} + +Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> +FDSimpleRemoteEPCTransport::Create(SimpleRemoteEPCTransportClient &C, int InFD, + int OutFD) { +#if LLVM_ENABLE_THREADS + if (InFD == -1) + return make_error<StringError>("Invalid input file descriptor " + + Twine(InFD), + inconvertibleErrorCode()); + if (OutFD == -1) + return make_error<StringError>("Invalid output file descriptor " + + Twine(OutFD), + inconvertibleErrorCode()); + std::unique_ptr<FDSimpleRemoteEPCTransport> FDT( + new FDSimpleRemoteEPCTransport(C, InFD, OutFD)); + return std::move(FDT); +#else + return make_error<StringError>("FD-based SimpleRemoteEPC transport requires " + "thread support, but llvm was built with " + "LLVM_ENABLE_THREADS=Off", + inconvertibleErrorCode()); +#endif +} + +FDSimpleRemoteEPCTransport::~FDSimpleRemoteEPCTransport() { +#if LLVM_ENABLE_THREADS + ListenerThread.join(); +#endif +} + +Error FDSimpleRemoteEPCTransport::start() { +#if LLVM_ENABLE_THREADS + ListenerThread = std::thread([this]() { listenLoop(); }); + return Error::success(); +#endif + llvm_unreachable("Should not be called with LLVM_ENABLE_THREADS=Off"); +} + +Error FDSimpleRemoteEPCTransport::sendMessage(SimpleRemoteEPCOpcode OpC, + uint64_t SeqNo, + ExecutorAddr TagAddr, + ArrayRef<char> ArgBytes) { + char HeaderBuffer[FDMsgHeader::Size]; + + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::MsgSizeOffset)) = + FDMsgHeader::Size + ArgBytes.size(); + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::OpCOffset)) = + static_cast<uint64_t>(OpC); + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::SeqNoOffset)) = SeqNo; + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::TagAddrOffset)) = + TagAddr.getValue(); + + std::lock_guard<std::mutex> Lock(M); + if (Disconnected) + return make_error<StringError>("FD-transport disconnected", + inconvertibleErrorCode()); + if (int ErrNo = writeBytes(HeaderBuffer, FDMsgHeader::Size)) + return errorCodeToError(std::error_code(ErrNo, std::generic_category())); + if (int ErrNo = writeBytes(ArgBytes.data(), ArgBytes.size())) + return errorCodeToError(std::error_code(ErrNo, std::generic_category())); + return Error::success(); +} + +void FDSimpleRemoteEPCTransport::disconnect() { + if (Disconnected) + return; // Return if already disconnected. + + Disconnected = true; + bool CloseOutFD = InFD != OutFD; + + // Close InFD. + while (close(InFD) == -1) { + if (errno == EBADF) + break; + } + + // Close OutFD. + if (CloseOutFD) { + while (close(OutFD) == -1) { + if (errno == EBADF) + break; + } + } +} + +static Error makeUnexpectedEOFError() { + return make_error<StringError>("Unexpected end-of-file", + inconvertibleErrorCode()); +} + +Error FDSimpleRemoteEPCTransport::readBytes(char *Dst, size_t Size, + bool *IsEOF) { + assert(Dst && "Attempt to read into null."); + ssize_t Completed = 0; + while (Completed < static_cast<ssize_t>(Size)) { + ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); + if (Read <= 0) { + auto ErrNo = errno; + if (Read == 0) { + if (Completed == 0 && IsEOF) { + *IsEOF = true; + return Error::success(); + } else + return makeUnexpectedEOFError(); + } else if (ErrNo == EAGAIN || ErrNo == EINTR) + continue; + else { + std::lock_guard<std::mutex> Lock(M); + if (Disconnected && IsEOF) { // disconnect called, pretend this is EOF. + *IsEOF = true; + return Error::success(); + } + return errorCodeToError( + std::error_code(ErrNo, std::generic_category())); + } + } + Completed += Read; + } + return Error::success(); +} + +int FDSimpleRemoteEPCTransport::writeBytes(const char *Src, size_t Size) { + assert(Src && "Attempt to append from null."); + ssize_t Completed = 0; + while (Completed < static_cast<ssize_t>(Size)) { + ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); + if (Written < 0) { + auto ErrNo = errno; + if (ErrNo == EAGAIN || ErrNo == EINTR) + continue; + else + return ErrNo; + } + Completed += Written; + } + return 0; +} + +void FDSimpleRemoteEPCTransport::listenLoop() { + Error Err = Error::success(); + do { + + char HeaderBuffer[FDMsgHeader::Size]; + // Read the header buffer. + { + bool IsEOF = false; + if (auto Err2 = readBytes(HeaderBuffer, FDMsgHeader::Size, &IsEOF)) { + Err = joinErrors(std::move(Err), std::move(Err2)); + break; + } + if (IsEOF) + break; + } + + // Decode header buffer. + uint64_t MsgSize; + SimpleRemoteEPCOpcode OpC; + uint64_t SeqNo; + ExecutorAddr TagAddr; + + MsgSize = + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::MsgSizeOffset)); + OpC = static_cast<SimpleRemoteEPCOpcode>(static_cast<uint64_t>( + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::OpCOffset)))); + SeqNo = + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::SeqNoOffset)); + TagAddr.setValue( + *((support::ulittle64_t *)(HeaderBuffer + FDMsgHeader::TagAddrOffset))); + + if (MsgSize < FDMsgHeader::Size) { + Err = joinErrors(std::move(Err), + make_error<StringError>("Message size too small", + inconvertibleErrorCode())); + break; + } + + // Read the argument bytes. + SimpleRemoteEPCArgBytesVector ArgBytes; + ArgBytes.resize(MsgSize - FDMsgHeader::Size); + if (auto Err2 = readBytes(ArgBytes.data(), ArgBytes.size())) { + Err = joinErrors(std::move(Err), std::move(Err2)); + break; + } + + if (auto Action = C.handleMessage(OpC, SeqNo, TagAddr, ArgBytes)) { + if (*Action == SimpleRemoteEPCTransportClient::EndSession) + break; + } else { + Err = joinErrors(std::move(Err), Action.takeError()); + break; + } + } while (true); + + // Attempt to close FDs, set Disconnected to true so that subsequent + // sendMessage calls fail. + disconnect(); + + // Call up to the client to handle the disconnection. + C.handleDisconnect(std::move(Err)); +} + +} // end namespace orc +} // end namespace llvm |