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 {
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)
57 if (OutFD == -1)
61 std::unique_ptr FDT(
62 new FDSimpleRemoteEPCTransport(C, InFD, OutFD));
63 return std::move(FDT);
64#else
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)
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
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
203 uint64_t MsgSize;
205 uint64_t SeqNo;
206 ExecutorAddr TagAddr;
207
208 MsgSize =
212 SeqNo =
214 TagAddr.setValue(
216
217 if (MsgSize < FDMsgHeader::Size) {
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
246 C.handleDisconnect(std::move(Err));
247}
248
249}
250}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
void disconnect() override
Trigger disconnection from the transport.
Definition SimpleRemoteEPCUtils.cpp:111
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).
Definition SimpleRemoteEPCUtils.cpp:50
Error start() override
Called during setup of the client to indicate that the client is ready to receive messages.
Definition SimpleRemoteEPCUtils.cpp:78
Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, ArrayRef< char > ArgBytes) override
Send a SimpleRemoteEPC message.
Definition SimpleRemoteEPCUtils.cpp:86
~FDSimpleRemoteEPCTransport() override
Definition SimpleRemoteEPCUtils.cpp:72
virtual ~SimpleRemoteEPCTransportClient()
virtual ~SimpleRemoteEPCTransport()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI const char * DispatchFnName
Definition SimpleRemoteEPCUtils.cpp:42
LLVM_ABI const char * ExecutorSessionObjectName
Definition SimpleRemoteEPCUtils.cpp:40
SmallVector< char, 128 > SimpleRemoteEPCArgBytesVector
static Error makeUnexpectedEOFError()
Definition SimpleRemoteEPCUtils.cpp:133
detail::packed_endian_specific_integral< uint64_t, llvm::endianness::little, unaligned > ulittle64_t
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI 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 make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.