[libc-commits] [libc] [libc] Implement `fseek`, `fflush`, and `ftell` on the GPU (PR #67160)

Joseph Huber via libc-commits libc-commits at lists.llvm.org
Tue Sep 26 07:05:29 PDT 2023


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/67160

>From 500bb31017f6633b2a531bce53eb3a4cbbc2ff37 Mon Sep 17 00:00:00 2001
From: Joseph Huber <jhuber6 at vols.utk.edu>
Date: Wed, 20 Sep 2023 11:19:04 -0500
Subject: [PATCH] [libc] Implement `fseek`, `fflush`, and `ftell` on the GPU

Summary:
This patch adds the necessary entrypoints to handle the `fseek`,
`fflush`, and `ftell` functions. These are all very straightfoward, we
simply make RPC calls to the associated function on the other end.
Implementing it this way allows us to more or less borrow the state of
the stream from the server as we intentionally maintain no internal
state on the GPU device. However, this does not implement the `errno`
functinality so that must be ignored.
---
 libc/config/gpu/entrypoints.txt              |  3 ++
 libc/docs/gpu/support.rst                    |  3 ++
 libc/include/llvm-libc-types/rpc_opcodes_t.h |  3 ++
 libc/src/stdio/CMakeLists.txt                | 42 ++------------------
 libc/src/stdio/generic/CMakeLists.txt        | 39 ++++++++++++++++++
 libc/src/stdio/{ => generic}/fflush.cpp      |  0
 libc/src/stdio/{ => generic}/fseek.cpp       |  0
 libc/src/stdio/{ => generic}/ftell.cpp       |  0
 libc/src/stdio/gpu/CMakeLists.txt            | 33 +++++++++++++++
 libc/src/stdio/gpu/fflush.cpp                | 26 ++++++++++++
 libc/src/stdio/gpu/fseek.cpp                 | 30 ++++++++++++++
 libc/src/stdio/gpu/ftell.cpp                 | 26 ++++++++++++
 libc/utils/gpu/server/rpc_server.cpp         | 20 ++++++++++
 13 files changed, 186 insertions(+), 39 deletions(-)
 rename libc/src/stdio/{ => generic}/fflush.cpp (100%)
 rename libc/src/stdio/{ => generic}/fseek.cpp (100%)
 rename libc/src/stdio/{ => generic}/ftell.cpp (100%)
 create mode 100644 libc/src/stdio/gpu/fflush.cpp
 create mode 100644 libc/src/stdio/gpu/fseek.cpp
 create mode 100644 libc/src/stdio/gpu/ftell.cpp

diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index a50699c68f65bfa..4f24420d6d7c669 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -88,6 +88,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     # stdio.h entrypoints
     libc.src.stdio.feof
     libc.src.stdio.ferror
+    libc.src.stdio.fseek
+    libc.src.stdio.fflush
+    libc.src.stdio.ftell
     libc.src.stdio.clearerr
     libc.src.stdio.puts
     libc.src.stdio.fopen
diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst
index a19fca59270af05..81b17884a44023c 100644
--- a/libc/docs/gpu/support.rst
+++ b/libc/docs/gpu/support.rst
@@ -129,6 +129,9 @@ Function Name  Available  RPC Required
 feof           |check|    |check|
 ferror         |check|    |check|
 clearerr       |check|    |check|
+fseek          |check|    |check|
+ftell          |check|    |check|
+fflush         |check|    |check|
 fgetc          |check|    |check|
 fgets          |check|    |check|
 getc           |check|    |check|
diff --git a/libc/include/llvm-libc-types/rpc_opcodes_t.h b/libc/include/llvm-libc-types/rpc_opcodes_t.h
index fb0f19cf505e8dc..77fa709466974d7 100644
--- a/libc/include/llvm-libc-types/rpc_opcodes_t.h
+++ b/libc/include/llvm-libc-types/rpc_opcodes_t.h
@@ -26,6 +26,9 @@ typedef enum : unsigned short {
   RPC_FEOF = 13,
   RPC_FERROR = 14,
   RPC_CLEARERR = 15,
+  RPC_FSEEK = 16,
+  RPC_FTELL = 17,
+  RPC_FFLUSH = 18,
 } rpc_opcode_t;
 
 #endif // __LLVM_LIBC_TYPES_RPC_OPCODE_H__
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index 9c24c567b6c1d5b..9146271898ffaa5 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -26,19 +26,6 @@ if(NOT LIBC_TARGET_ARCHITECTURE_IS_GPU)
   add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/generic)
 endif()
 
-add_entrypoint_object(
-  fflush
-  SRCS
-    fflush.cpp
-  HDRS
-    fflush.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
 add_entrypoint_object(
   flockfile
   SRCS
@@ -63,19 +50,6 @@ add_entrypoint_object(
     libc.src.__support.File.platform_file
 )
 
-add_entrypoint_object(
-  fseek
-  SRCS
-    fseek.cpp
-  HDRS
-    fseek.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
 add_entrypoint_object(
   ungetc
   SRCS
@@ -302,19 +276,6 @@ add_entrypoint_object(
 add_subdirectory(printf_core)
 add_subdirectory(scanf_core)
 
-add_entrypoint_object(
-  ftell
-  SRCS
-    ftell.cpp
-  HDRS
-    ftell.h
-  DEPENDS
-    libc.src.errno.errno
-    libc.include.stdio
-    libc.src.__support.File.file
-    libc.src.__support.File.platform_file
-)
-
 add_entrypoint_object(
   remove
   ALIAS
@@ -327,6 +288,9 @@ add_stdio_entrypoint_object(feof)
 add_stdio_entrypoint_object(feof_unlocked)
 add_stdio_entrypoint_object(ferror)
 add_stdio_entrypoint_object(ferror_unlocked)
+add_stdio_entrypoint_object(fseek)
+add_stdio_entrypoint_object(ftell)
+add_stdio_entrypoint_object(fflush)
 add_stdio_entrypoint_object(clearerr)
 add_stdio_entrypoint_object(clearerr_unlocked)
 add_stdio_entrypoint_object(fopen)
diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt
index b7a9b9b5747e2b4..f5f0c082dd48fd4 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -70,6 +70,45 @@ add_entrypoint_object(
     libc.src.__support.File.platform_file
 )
 
+add_entrypoint_object(
+  fflush
+  SRCS
+    fflush.cpp
+  HDRS
+    ../fflush.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  fseek
+  SRCS
+    fseek.cpp
+  HDRS
+    ../fseek.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  ftell
+  SRCS
+    ftell.cpp
+  HDRS
+    ftell.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
 add_entrypoint_object(
   fopen
   SRCS
diff --git a/libc/src/stdio/fflush.cpp b/libc/src/stdio/generic/fflush.cpp
similarity index 100%
rename from libc/src/stdio/fflush.cpp
rename to libc/src/stdio/generic/fflush.cpp
diff --git a/libc/src/stdio/fseek.cpp b/libc/src/stdio/generic/fseek.cpp
similarity index 100%
rename from libc/src/stdio/fseek.cpp
rename to libc/src/stdio/generic/fseek.cpp
diff --git a/libc/src/stdio/ftell.cpp b/libc/src/stdio/generic/ftell.cpp
similarity index 100%
rename from libc/src/stdio/ftell.cpp
rename to libc/src/stdio/generic/ftell.cpp
diff --git a/libc/src/stdio/gpu/CMakeLists.txt b/libc/src/stdio/gpu/CMakeLists.txt
index c47176621144e39..047b68931bce5c3 100644
--- a/libc/src/stdio/gpu/CMakeLists.txt
+++ b/libc/src/stdio/gpu/CMakeLists.txt
@@ -32,6 +32,39 @@ add_entrypoint_object(
     libc.src.__support.RPC.rpc_client
 )
 
+add_entrypoint_object(
+  fseek
+  SRCS
+    fseek.cpp
+  HDRS
+    ../fseek.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
+add_entrypoint_object(
+  ftell
+  SRCS
+    ftell.cpp
+  HDRS
+    ../ftell.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
+add_entrypoint_object(
+  fflush
+  SRCS
+    fflush.cpp
+  HDRS
+    ../fflush.h
+  DEPENDS
+    libc.include.stdio
+    .gpu_file
+)
+
 add_entrypoint_object(
   clearerr
   SRCS
diff --git a/libc/src/stdio/gpu/fflush.cpp b/libc/src/stdio/gpu/fflush.cpp
new file mode 100644
index 000000000000000..68192174e58a8ec
--- /dev/null
+++ b/libc/src/stdio/gpu/fflush.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of fflush ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fflush.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
+  int ret;
+  rpc::Client::Port port = rpc::client.open<RPC_FFLUSH>();
+  port.send_and_recv(
+      [=](rpc::Buffer *buffer) { buffer->data[0] = file::from_stream(stream); },
+      [&](rpc::Buffer *buffer) { ret = static_cast<int>(buffer->data[0]); });
+  port.close();
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdio/gpu/fseek.cpp b/libc/src/stdio/gpu/fseek.cpp
new file mode 100644
index 000000000000000..3e93ddb46bf9757
--- /dev/null
+++ b/libc/src/stdio/gpu/fseek.cpp
@@ -0,0 +1,30 @@
+//===-- GPU implementation of fseek ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fseek.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, fseek, (::FILE * stream, long offset, int whence)) {
+  int ret;
+  rpc::Client::Port port = rpc::client.open<RPC_FSEEK>();
+  port.send_and_recv(
+      [=](rpc::Buffer *buffer) {
+        buffer->data[0] = file::from_stream(stream);
+        buffer->data[1] = static_cast<uint64_t>(offset);
+        buffer->data[2] = static_cast<uint64_t>(whence);
+      },
+      [&](rpc::Buffer *buffer) { ret = static_cast<int>(buffer->data[0]); });
+  port.close();
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdio/gpu/ftell.cpp b/libc/src/stdio/gpu/ftell.cpp
new file mode 100644
index 000000000000000..aea3e8b229fce65
--- /dev/null
+++ b/libc/src/stdio/gpu/ftell.cpp
@@ -0,0 +1,26 @@
+//===-- GPU implementation of ftell ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/ftell.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long, ftell, (::FILE * stream)) {
+  long ret;
+  rpc::Client::Port port = rpc::client.open<RPC_FSEEK>();
+  port.send_and_recv(
+      [=](rpc::Buffer *buffer) { buffer->data[0] = file::from_stream(stream); },
+      [&](rpc::Buffer *buffer) { ret = static_cast<long>(buffer->data[0]); });
+  port.close();
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp
index fa6a4e324c0c281..6395a808ca98b00 100644
--- a/libc/utils/gpu/server/rpc_server.cpp
+++ b/libc/utils/gpu/server/rpc_server.cpp
@@ -164,6 +164,26 @@ struct Server {
       });
       break;
     }
+    case RPC_FSEEK: {
+      port->recv_and_send([](rpc::Buffer *buffer) {
+        buffer->data[0] = fseek(file::to_stream(buffer->data[0]),
+                                static_cast<long>(buffer->data[1]),
+                                static_cast<int>(buffer->data[2]));
+      });
+      break;
+    }
+    case RPC_FTELL: {
+      port->recv_and_send([](rpc::Buffer *buffer) {
+        buffer->data[0] = ftell(file::to_stream(buffer->data[0]));
+      });
+      break;
+    }
+    case RPC_FFLUSH: {
+      port->recv_and_send([](rpc::Buffer *buffer) {
+        buffer->data[0] = fflush(file::to_stream(buffer->data[0]));
+      });
+      break;
+    }
     case RPC_NOOP: {
       port->recv([](rpc::Buffer *) {});
       break;



More information about the libc-commits mailing list