Skip to content

Commit be51e51

Browse files
committed
[libc][NFC] Cleanup the GPU file I/O utility header
Summary: The GPU uses separate implementations to perform file IO. This is all done through the RPC interface and we kept it minimal such that we could treat a `stdin`, `stdout`, or `stderr` handle from the CPU correctly on the GPU. The RPC implementation uses different opcodes for whether or not we are using one of the standard streams. This is so we do not need to initialize anything to access the CPU's standard stream, because the server knows that it should print to `stdout` if it gets the `STDOUT` variant of the opcode. It also saves us an RPC call, which are expensive relatively speaking. This patch simply cleans up this interface to make them all use a common function. This is done in preparation to implement some more file IO functions like getc or putc.
1 parent 71168f6 commit be51e51

File tree

1 file changed

+21
-48
lines changed

1 file changed

+21
-48
lines changed

libc/src/stdio/gpu/file.h

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- GPU helper functions--------------------===//
1+
//===--- GPU helper functions for file I/O using RPC ----------------------===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -14,35 +14,17 @@
1414
namespace __llvm_libc {
1515
namespace file {
1616

17-
LIBC_INLINE uint64_t write_to_stdout(const void *data, size_t size) {
17+
template <uint16_t opcode>
18+
LIBC_INLINE uint64_t write_impl(::FILE *file, const void *data, size_t size) {
1819
uint64_t ret = 0;
19-
rpc::Client::Port port = rpc::client.open<RPC_WRITE_TO_STDOUT>();
20-
port.send_n(data, size);
21-
port.recv([&](rpc::Buffer *buffer) {
22-
ret = reinterpret_cast<uint64_t *>(buffer->data)[0];
23-
});
24-
port.close();
25-
return ret;
26-
}
20+
rpc::Client::Port port = rpc::client.open<opcode>();
2721

28-
LIBC_INLINE uint64_t write_to_stderr(const void *data, size_t size) {
29-
uint64_t ret = 0;
30-
rpc::Client::Port port = rpc::client.open<RPC_WRITE_TO_STDERR>();
31-
port.send_n(data, size);
32-
port.recv([&](rpc::Buffer *buffer) {
33-
ret = reinterpret_cast<uint64_t *>(buffer->data)[0];
34-
});
35-
port.close();
36-
return ret;
37-
}
22+
if constexpr (opcode == RPC_WRITE_TO_STREAM) {
23+
port.send([&](rpc::Buffer *buffer) {
24+
buffer->data[0] = reinterpret_cast<uintptr_t>(file);
25+
});
26+
}
3827

39-
LIBC_INLINE uint64_t write_to_stream(uintptr_t file, const void *data,
40-
size_t size) {
41-
uint64_t ret = 0;
42-
rpc::Client::Port port = rpc::client.open<RPC_WRITE_TO_STREAM>();
43-
port.send([&](rpc::Buffer *buffer) {
44-
reinterpret_cast<uintptr_t *>(buffer->data)[0] = file;
45-
});
4628
port.send_n(data, size);
4729
port.recv([&](rpc::Buffer *buffer) {
4830
ret = reinterpret_cast<uint64_t *>(buffer->data)[0];
@@ -51,45 +33,36 @@ LIBC_INLINE uint64_t write_to_stream(uintptr_t file, const void *data,
5133
return ret;
5234
}
5335

54-
LIBC_INLINE uint64_t write(FILE *f, const void *data, size_t size) {
36+
LIBC_INLINE uint64_t write(::FILE *f, const void *data, size_t size) {
5537
if (f == stdout)
56-
return write_to_stdout(data, size);
38+
return write_impl<RPC_WRITE_TO_STDOUT>(f, data, size);
5739
else if (f == stderr)
58-
return write_to_stderr(data, size);
40+
return write_impl<RPC_WRITE_TO_STDERR>(f, data, size);
5941
else
60-
return write_to_stream(reinterpret_cast<uintptr_t>(f), data, size);
61-
}
62-
63-
LIBC_INLINE uint64_t read_from_stdin(void *buf, size_t size) {
64-
uint64_t ret = 0;
65-
uint64_t recv_size;
66-
rpc::Client::Port port = rpc::client.open<RPC_READ_FROM_STDIN>();
67-
port.send([=](rpc::Buffer *buffer) { buffer->data[0] = size; });
68-
port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; });
69-
port.recv([&](rpc::Buffer *buffer) { ret = buffer->data[0]; });
70-
port.close();
71-
return ret;
42+
return write_impl<RPC_WRITE_TO_STREAM>(f, data, size);
7243
}
7344

74-
LIBC_INLINE uint64_t read_from_stream(uintptr_t file, void *buf, size_t size) {
45+
template <uint16_t opcode>
46+
LIBC_INLINE uint64_t read_from_stream(::FILE *file, void *buf, size_t size) {
7547
uint64_t ret = 0;
7648
uint64_t recv_size;
77-
rpc::Client::Port port = rpc::client.open<RPC_READ_FROM_STREAM>();
49+
rpc::Client::Port port = rpc::client.open<opcode>();
7850
port.send([=](rpc::Buffer *buffer) {
7951
buffer->data[0] = size;
80-
buffer->data[1] = file;
52+
if constexpr (opcode == RPC_READ_FROM_STREAM)
53+
buffer->data[1] = reinterpret_cast<uintptr_t>(file);
8154
});
8255
port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; });
8356
port.recv([&](rpc::Buffer *buffer) { ret = buffer->data[0]; });
8457
port.close();
8558
return ret;
8659
}
8760

88-
LIBC_INLINE uint64_t read(FILE *f, void *data, size_t size) {
61+
LIBC_INLINE uint64_t read(::FILE *f, void *data, size_t size) {
8962
if (f == stdin)
90-
return read_from_stdin(data, size);
63+
return read_from_stream<RPC_READ_FROM_STDIN>(f, data, size);
9164
else
92-
return read_from_stream(reinterpret_cast<uintptr_t>(f), data, size);
65+
return read_from_stream<RPC_READ_FROM_STREAM>(f, data, size);
9366
}
9467

9568
} // namespace file

0 commit comments

Comments
 (0)