diff --git a/libc/include/llvm-libc-types/rpc_opcodes_t.h b/libc/include/llvm-libc-types/rpc_opcodes_t.h index 2fd318f06a7db..7b85428dd3445 100644 --- a/libc/include/llvm-libc-types/rpc_opcodes_t.h +++ b/libc/include/llvm-libc-types/rpc_opcodes_t.h @@ -17,6 +17,7 @@ typedef enum { RPC_WRITE_TO_STREAM, RPC_WRITE_TO_STDOUT_NEWLINE, RPC_READ_FROM_STREAM, + RPC_READ_FGETS, RPC_OPEN_FILE, RPC_CLOSE_FILE, RPC_MALLOC, diff --git a/libc/src/stdio/gpu/fgets.cpp b/libc/src/stdio/gpu/fgets.cpp index 4cabd15001a7f..5ea4bdcdc9e0f 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(); + 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(str); }); + port.close(); + + if (recv_size == 0) return nullptr; - str[i] = '\0'; return str; } diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 0550115f7cd1a..05e900edc6993 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -101,6 +101,22 @@ struct Server { }); break; } + case RPC_READ_FGETS: { + uint64_t sizes[lane_size] = {0}; + void *data[lane_size] = {nullptr}; + port->recv([&](rpc::Buffer *buffer, uint32_t id) { + data[id] = new char[buffer->data[0]]; + const char *str = + fgets(reinterpret_cast(data[id]), buffer->data[0], + file::to_stream(buffer->data[1])); + sizes[id] = !str ? 0 : std::strlen(str) + 1; + }); + port->send_n(data, sizes); + for (uint32_t id = 0; id < lane_size; ++id) + if (data[id]) + delete[] reinterpret_cast(data[id]); + break; + } case RPC_OPEN_FILE: { uint64_t sizes[lane_size] = {0}; void *paths[lane_size] = {nullptr};