[libc-commits] [libc] b8be3da - [libc] Add Linux implementation of GNU extension function sendfile.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Fri Aug 26 12:14:00 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-08-26T19:13:40Z
New Revision: b8be3dabde8add876937400bf2ffda9854219c74

URL: https://github.com/llvm/llvm-project/commit/b8be3dabde8add876937400bf2ffda9854219c74
DIFF: https://github.com/llvm/llvm-project/commit/b8be3dabde8add876937400bf2ffda9854219c74.diff

LOG: [libc] Add Linux implementation of GNU extension function sendfile.

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D132721

Added: 
    libc/include/sys/sendfile.h.def
    libc/src/sys/sendfile/CMakeLists.txt
    libc/src/sys/sendfile/linux/CMakeLists.txt
    libc/src/sys/sendfile/linux/sendfile.cpp
    libc/src/sys/sendfile/sendfile.h
    libc/test/src/sys/sendfile/CMakeLists.txt
    libc/test/src/sys/sendfile/sendfile_test.cpp
    libc/test/src/sys/sendfile/testdata/CMakeLists.txt

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/api.td
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/CMakeLists.txt
    libc/spec/gnu_ext.td
    libc/spec/posix.td
    libc/spec/spec.td
    libc/src/sys/CMakeLists.txt
    libc/test/src/sys/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 13ca094e5cee0..dcb39ba7fc372 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -100,6 +100,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.mmap
     libc.src.sys.mman.munmap
 
+    # sys/sendfile entrypoints
+    libc.src.sys.sendfile.sendfile
+
     # sys/stat.h entrypoints
     libc.src.sys.stat.chmod
     libc.src.sys.stat.fchmod

diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 7aa23cc0c1bdd..92b42ffbed885 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -274,3 +274,7 @@ def UniStdAPI : PublicAPI<"unistd.h"> {
 def SysStatAPI : PublicAPI<"sys/stat.h"> {
   let Types = ["mode_t"];
 }
+
+def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> {
+  let Types = ["off_t", "size_t", "ssize_t"];
+}

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 15bf3b13dc66e..307bdd3efaa72 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -100,6 +100,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.mmap
     libc.src.sys.mman.munmap
 
+    # sys/sendfile entrypoints
+    libc.src.sys.sendfile.sendfile
+
     # sys/stat.h entrypoints
     libc.src.sys.stat.chmod
     libc.src.sys.stat.fchmod

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index cec90f5c9171b..248c164e7d667 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -212,6 +212,16 @@ add_gen_header(
     .llvm-libc-types.mode_t
 )
 
+add_gen_header(
+  sys_sendfile
+  DEF_FILE sys/sendfile.h.def
+  GEN_HDR sys/sendfile.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-types.off_t
+    .llvm-libc-types.ssize_t
+)
+
 add_gen_header(
   sys_syscall
   DEF_FILE sys/syscall.h.def

diff  --git a/libc/include/sys/sendfile.h.def b/libc/include/sys/sendfile.h.def
new file mode 100644
index 0000000000000..947edc28e1ecf
--- /dev/null
+++ b/libc/include/sys/sendfile.h.def
@@ -0,0 +1,16 @@
+//===-- Linux sys/sendfile.h ----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SYS_SENDFILE_H
+#define LLVM_LIBC_SYS_SENDFILE_H
+
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_SENDFILE_H

diff  --git a/libc/spec/gnu_ext.td b/libc/spec/gnu_ext.td
index ec22e8e0ee590..c1f08af138146 100644
--- a/libc/spec/gnu_ext.td
+++ b/libc/spec/gnu_ext.td
@@ -130,11 +130,26 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
       ]
   >;
 
+  HeaderSpec SendFile = HeaderSpec<
+      "sys/sendfile.h",
+      [], // Macros
+      [OffTType, SizeTType, SSizeTType,], // Types
+      [], // Enumerations
+      [
+          FunctionSpec<
+              "sendfile",
+              RetValSpec<SSizeTType>,
+              [ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<OffTPtr>, ArgSpec<SizeTType>]
+          >,
+      ]
+  >;
+
   let Headers = [
     CType,
     FEnv,
     Math,
     PThread,
+    SendFile,
     StdIO,
     String,
   ];

diff  --git a/libc/spec/posix.td b/libc/spec/posix.td
index 27fb7c23d45ce..a03b04ff25688 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -32,8 +32,6 @@ def POSIX : StandardSpec<"POSIX"> {
   ConstType ConstRestrictedCharPtr = ConstType<RestrictedCharPtr>;
 
   NamedType ModeTType = NamedType<"mode_t">;
-  NamedType OffTType = NamedType<"off_t">;
-  NamedType SSizeTType = NamedType<"ssize_t">;
 
   NamedType PThreadAttrTType = NamedType<"pthread_attr_t">;
   PtrType PThreadAttrTPtr = PtrType<PThreadAttrTType>;

diff  --git a/libc/spec/spec.td b/libc/spec/spec.td
index 3e5cbd2fedbff..7a2237f82957c 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -63,6 +63,10 @@ def LongDoublePtr : PtrType<LongDoubleType>;
 def IntMaxTType : NamedType<"intmax_t">;
 def UIntMaxTType : NamedType<"uintmax_t">;
 
+def OffTType : NamedType<"off_t">;
+def OffTPtr : PtrType<OffTType>;
+def SSizeTType : NamedType<"ssize_t">;
+
 // _Noreturn is really not a type, but it is convenient to treat it as a type.
 def NoReturn : NamedType<"_Noreturn void">;
 

diff  --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index 4c7e82097bf64..36d0cdf47cbb1 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_subdirectory(mman)
+add_subdirectory(sendfile)
 add_subdirectory(stat)

diff  --git a/libc/src/sys/sendfile/CMakeLists.txt b/libc/src/sys/sendfile/CMakeLists.txt
new file mode 100644
index 0000000000000..c4d298851c725
--- /dev/null
+++ b/libc/src/sys/sendfile/CMakeLists.txt
@@ -0,0 +1,11 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  sendfile
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.sendfile
+)
+

diff  --git a/libc/src/sys/sendfile/linux/CMakeLists.txt b/libc/src/sys/sendfile/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..f6d4fa30fb46c
--- /dev/null
+++ b/libc/src/sys/sendfile/linux/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_entrypoint_object(
+  sendfile
+  SRCS
+    sendfile.cpp
+  HDRS
+    ../sendfile.h
+  DEPENDS
+    libc.include.sys_sendfile
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)

diff  --git a/libc/src/sys/sendfile/linux/sendfile.cpp b/libc/src/sys/sendfile/linux/sendfile.cpp
new file mode 100644
index 0000000000000..8beaae2607bab
--- /dev/null
+++ b/libc/src/sys/sendfile/linux/sendfile.cpp
@@ -0,0 +1,30 @@
+//===-- Linux implementation of sendfile ----------------------------------===//
+//
+// 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/sys/sendfile/sendfile.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/sendfile.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(ssize_t, sendfile,
+                   (int out_fd, int in_fd, off_t *offset, size_t count)) {
+  long ret = __llvm_libc::syscall(SYS_sendfile, in_fd, out_fd, offset, count);
+  if (ret < 0) {
+    errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/sys/sendfile/sendfile.h b/libc/src/sys/sendfile/sendfile.h
new file mode 100644
index 0000000000000..f28840043d6be
--- /dev/null
+++ b/libc/src/sys/sendfile/sendfile.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sendfile ----------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_STAT_SENDFILE_H
+#define LLVM_LIBC_SRC_SYS_STAT_SENDFILE_H
+
+#include <sys/sendfile.h>
+
+namespace __llvm_libc {
+
+ssize_t sendfile(int, int, off_t *, size_t);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_STAT_SENDFILE_H

diff  --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index 4c7e82097bf64..36d0cdf47cbb1 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_subdirectory(mman)
+add_subdirectory(sendfile)
 add_subdirectory(stat)

diff  --git a/libc/test/src/sys/sendfile/CMakeLists.txt b/libc/test/src/sys/sendfile/CMakeLists.txt
new file mode 100644
index 0000000000000..d2aa830fb0529
--- /dev/null
+++ b/libc/test/src/sys/sendfile/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_libc_testsuite(libc_sys_sendfile_unittests)
+
+add_subdirectory(testdata)
+
+add_libc_unittest(
+  sendfile_test
+  SUITE
+    libc_sys_sendfile_unittests
+  SRCS
+    sendfile_test.cpp
+  DEPENDS
+    libc.include.errno
+    libc.include.fcntl
+    libc.include.sys_stat
+    libc.src.fcntl.open
+    libc.src.sys.sendfile.sendfile
+    libc.src.unistd.close
+    libc.src.unistd.read
+    libc.src.unistd.unlink
+    libc.src.unistd.write
+)

diff  --git a/libc/test/src/sys/sendfile/sendfile_test.cpp b/libc/test/src/sys/sendfile/sendfile_test.cpp
new file mode 100644
index 0000000000000..78f9dbfb11148
--- /dev/null
+++ b/libc/test/src/sys/sendfile/sendfile_test.cpp
@@ -0,0 +1,67 @@
+//===-- Unittests for sendfile --------------------------------------------===//
+//
+// 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/__support/CPP/string_view.h"
+#include "src/fcntl/open.h"
+#include "src/sys/sendfile/sendfile.h"
+#include "src/unistd/close.h"
+#include "src/unistd/read.h"
+#include "src/unistd/unlink.h"
+#include "src/unistd/write.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+namespace cpp = __llvm_libc::cpp;
+
+TEST(LlvmLibcSendfileTest, CreateAndTransfer) {
+  using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+  using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+
+  // The test strategy is to
+  //   1. Create a temporary file with known data.
+  //   2. Use sendfile to copy it to another file.
+  //   3. Make sure that the data was actually copied.
+  //   4. Clean up the temporary files.
+  constexpr const char *IN_FILE = "testdata/sendfile_in.test";
+  constexpr const char *OUT_FILE = "testdata/sendfile_out.test";
+  const char IN_DATA[] = "sendfile test";
+  constexpr ssize_t IN_SIZE = ssize_t(sizeof(IN_DATA));
+  errno = 0;
+
+  int in_fd = __llvm_libc::open(IN_FILE, O_CREAT | O_WRONLY, S_IRWXU);
+  ASSERT_GT(in_fd, 0);
+  ASSERT_EQ(errno, 0);
+  ASSERT_EQ(__llvm_libc::write(in_fd, IN_DATA, IN_SIZE), IN_SIZE);
+  ASSERT_THAT(__llvm_libc::close(in_fd), Succeeds(0));
+
+  in_fd = __llvm_libc::open(IN_FILE, O_RDONLY);
+  ASSERT_GT(in_fd, 0);
+  ASSERT_EQ(errno, 0);
+  int out_fd = __llvm_libc::open(OUT_FILE, O_CREAT | O_WRONLY, S_IRWXU);
+  ASSERT_GT(out_fd, 0);
+  ASSERT_EQ(errno, 0);
+  ssize_t size = __llvm_libc::sendfile(in_fd, out_fd, nullptr, IN_SIZE);
+  ASSERT_EQ(size, IN_SIZE);
+  ASSERT_THAT(__llvm_libc::close(in_fd), Succeeds(0));
+  ASSERT_THAT(__llvm_libc::close(out_fd), Succeeds(0));
+
+  out_fd = __llvm_libc::open(OUT_FILE, O_RDONLY);
+  ASSERT_GT(out_fd, 0);
+  ASSERT_EQ(errno, 0);
+  char buf[IN_SIZE];
+  ASSERT_EQ(IN_SIZE, __llvm_libc::read(out_fd, buf, IN_SIZE));
+  ASSERT_EQ(cpp::string_view(buf), cpp::string_view(IN_DATA));
+
+  ASSERT_THAT(__llvm_libc::unlink(IN_FILE), Succeeds(0));
+  ASSERT_THAT(__llvm_libc::unlink(OUT_FILE), Succeeds(0));
+}

diff  --git a/libc/test/src/sys/sendfile/testdata/CMakeLists.txt b/libc/test/src/sys/sendfile/testdata/CMakeLists.txt
new file mode 100644
index 0000000000000..62b9f997a06c5
--- /dev/null
+++ b/libc/test/src/sys/sendfile/testdata/CMakeLists.txt
@@ -0,0 +1 @@
+# Directory to hold temporary files created by tests.


        


More information about the libc-commits mailing list