LLVM: lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15#include "llvm/Config/llvm-config.h"

17

18#if !defined(_MSC_VER) && !defined(__MINGW32__)

19#include <unistd.h>

20#else

21#include <io.h>

22#endif

23

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}

35

36namespace llvm {

37namespace orc {

38namespace SimpleRemoteEPCDefaultBootstrapSymbolNames {

39

41 "__llvm_orc_SimpleRemoteEPC_dispatch_ctx";

42const char *DispatchFnName = "__llvm_orc_SimpleRemoteEPC_dispatch_fn";

43

44}

45

48

51 int OutFD) {

52#if LLVM_ENABLE_THREADS

53 if (InFD == -1)

54 return make_error("Invalid input file descriptor " +

57 if (OutFD == -1)

58 return make_error("Invalid output file descriptor " +

61 std::unique_ptr FDT(

63 return std::move(FDT);

64#else

65 return make_error("FD-based SimpleRemoteEPC transport requires "

66 "thread support, but llvm was built with "

67 "LLVM_ENABLE_THREADS=Off",

69#endif

70}

71

73#if LLVM_ENABLE_THREADS

74 ListenerThread.join();

75#endif

76}

77

79#if LLVM_ENABLE_THREADS

80 ListenerThread = std::thread([this]() { listenLoop(); });

82#endif

83 llvm_unreachable("Should not be called with LLVM_ENABLE_THREADS=Off");

84}

85

90 char HeaderBuffer[FDMsgHeader::Size];

91

93 FDMsgHeader::Size + ArgBytes.size();

99

100 std::lock_guardstd::mutex Lock(M);

101 if (Disconnected)

102 return make_error("FD-transport disconnected",

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()));

109}

110

112 if (Disconnected)

113 return;

114

115 Disconnected = true;

116 bool CloseOutFD = InFD != OutFD;

117

118

119 while (close(InFD) == -1) {

120 if (errno == EBADF)

121 break;

122 }

123

124

125 if (CloseOutFD) {

126 while (close(OutFD) == -1) {

127 if (errno == EBADF)

128 break;

129 }

130 }

131}

132

134 return make_error("Unexpected end-of-file",

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;

150 } else

152 } else if (ErrNo == EAGAIN || ErrNo == EINTR)

153 continue;

154 else {

155 std::lock_guardstd::mutex Lock(M);

156 if (Disconnected && IsEOF) {

157 *IsEOF = true;

159 }

161 std::error_code(ErrNo, std::generic_category()));

162 }

163 }

164 Completed += Read;

165 }

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 else

179 return ErrNo;

180 }

181 Completed += Written;

182 }

183 return 0;

184}

185

186void FDSimpleRemoteEPCTransport::listenLoop() {

188 do {

189

190 char HeaderBuffer[FDMsgHeader::Size];

191

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

206 ExecutorAddr TagAddr;

207

208 MsgSize =

212 SeqNo =

214 TagAddr.setValue(

216

217 if (MsgSize < FDMsgHeader::Size) {

219 make_error("Message size too small",

221 break;

222 }

223

224

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)) {

234 break;

235 } else {

236 Err = joinErrors(std::move(Err), Action.takeError());

237 break;

238 }

239 } while (true);

240

241

242

244

245

247}

248

249}

250}

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

Represents an address in the executor process.

uint64_t getValue() const

Uses read/write on FileDescriptors for transport.

void disconnect() override

Trigger disconnection from the transport.

static Expected< std::unique_ptr< FDSimpleRemoteEPCTransport > > Create(SimpleRemoteEPCTransportClient &C, int InFD, int OutFD)

Create a FDSimpleRemoteEPCTransport using the given FDs for reading (InFD) and writing (OutFD).

Error start() override

Called during setup of the client to indicate that the client is ready to receive messages.

Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, ArrayRef< char > ArgBytes) override

Send a SimpleRemoteEPC message.

~FDSimpleRemoteEPCTransport() override

virtual Expected< HandleMessageAction > handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, SimpleRemoteEPCArgBytesVector ArgBytes)=0

Handle receipt of a message.

virtual void handleDisconnect(Error Err)=0

Handle a disconnection from the underlying transport.

virtual ~SimpleRemoteEPCTransportClient()

virtual ~SimpleRemoteEPCTransport()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

const char * DispatchFnName

const char * ExecutorSessionObjectName

SmallVector< char, 128 > SimpleRemoteEPCArgBytesVector

static Error makeUnexpectedEOFError()

detail::packed_endian_specific_integral< uint64_t, llvm::endianness::little, unaligned > ulittle64_t

This is an optimization pass for GlobalISel generic memory operations.

std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

Error joinErrors(Error E1, Error E2)

Concatenate errors.

Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)

Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.