123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- //===------ 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
|