Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.cpp
39606 views
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Message definitions and other utilities for SimpleRemoteEPC and
10
// SimpleRemoteEPCServer.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
15
#include "llvm/Support/Endian.h"
16
#include "llvm/Support/FormatVariadic.h"
17
18
#if !defined(_MSC_VER) && !defined(__MINGW32__)
19
#include <unistd.h>
20
#else
21
#include <io.h>
22
#endif
23
24
namespace {
25
26
struct 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
} // namespace
35
36
namespace llvm {
37
namespace orc {
38
namespace SimpleRemoteEPCDefaultBootstrapSymbolNames {
39
40
const char *ExecutorSessionObjectName =
41
"__llvm_orc_SimpleRemoteEPC_dispatch_ctx";
42
const char *DispatchFnName = "__llvm_orc_SimpleRemoteEPC_dispatch_fn";
43
44
} // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames
45
46
SimpleRemoteEPCTransportClient::~SimpleRemoteEPCTransportClient() = default;
47
SimpleRemoteEPCTransport::~SimpleRemoteEPCTransport() = default;
48
49
Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>>
50
FDSimpleRemoteEPCTransport::Create(SimpleRemoteEPCTransportClient &C, int InFD,
51
int OutFD) {
52
#if LLVM_ENABLE_THREADS
53
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
#else
65
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
#endif
70
}
71
72
FDSimpleRemoteEPCTransport::~FDSimpleRemoteEPCTransport() {
73
#if LLVM_ENABLE_THREADS
74
ListenerThread.join();
75
#endif
76
}
77
78
Error FDSimpleRemoteEPCTransport::start() {
79
#if LLVM_ENABLE_THREADS
80
ListenerThread = std::thread([this]() { listenLoop(); });
81
return Error::success();
82
#endif
83
llvm_unreachable("Should not be called with LLVM_ENABLE_THREADS=Off");
84
}
85
86
Error 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
111
void 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
133
static Error makeUnexpectedEOFError() {
134
return make_error<StringError>("Unexpected end-of-file",
135
inconvertibleErrorCode());
136
}
137
138
Error 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
} else
151
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
169
int 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
186
void 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 subsequent
242
// 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 orc
250
} // end namespace llvm
251
252