summaryrefslogtreecommitdiff
path: root/libc/src/stdio/gpu
diff options
context:
space:
mode:
authorJoseph Huber <35342157+jhuber6@users.noreply.github.com>2023-10-19 17:00:01 -0400
committerGitHub <noreply@github.com>2023-10-19 17:00:01 -0400
commita39215768b58bb39716820959cedf82c76648770 (patch)
treee29c443194ccda2529a317150dd0355ee25000cd /libc/src/stdio/gpu
parent049993eae6bef539ac4bca7ddeede78282e496d9 (diff)
[libc] Rework the 'fgets' implementation on the GPU (#69635)
Summary: The `fgets` function as implemented is not functional currently when called with multiple threads. This is because we rely on reapeatedly polling the character to detect EOF. This doesn't work when there are multiple threads that may with to poll the characters. this patch pulls out the logic into a standalone RPC call to handle this in a single operation such that calling it from multiple threads functions as expected. It also makes it less slow because we no longer make N RPC calls for N characters.
Diffstat (limited to 'libc/src/stdio/gpu')
-rw-r--r--libc/src/stdio/gpu/fgets.cpp28
1 files changed, 12 insertions, 16 deletions
diff --git a/libc/src/stdio/gpu/fgets.cpp b/libc/src/stdio/gpu/fgets.cpp
index 4cabd15001a7..5ea4bdcdc9e0 100644
--- a/libc/src/stdio/gpu/fgets.cpp
+++ b/libc/src/stdio/gpu/fgets.cpp
@@ -22,24 +22,20 @@ LLVM_LIBC_FUNCTION(char *, fgets,
if (count < 1)
return nullptr;
- // This implementation is very slow as it makes multiple RPC calls.
- unsigned char c = '\0';
- int i = 0;
- for (; i < count - 1 && c != '\n'; ++i) {
- auto r = file::read(stream, &c, 1);
- if (r != 1)
- break;
-
- str[i] = c;
- }
-
- bool has_error = LIBC_NAMESPACE::ferror(stream);
- bool has_eof = LIBC_NAMESPACE::feof(stream);
-
- if (has_error || (i == 0 && has_eof))
+ uint64_t recv_size;
+ void *buf = nullptr;
+ rpc::Client::Port port = rpc::client.open<RPC_READ_FGETS>();
+ port.send([=](rpc::Buffer *buffer) {
+ buffer->data[0] = count;
+ buffer->data[1] = file::from_stream(stream);
+ });
+ port.recv_n(&buf, &recv_size,
+ [&](uint64_t) { return reinterpret_cast<void *>(str); });
+ port.close();
+
+ if (recv_size == 0)
return nullptr;
- str[i] = '\0';
return str;
}