Skip to content

[libc] implement sys/uio/readv #124718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 6, 2025
Merged

[libc] implement sys/uio/readv #124718

merged 5 commits into from
Feb 6, 2025

Conversation

c8ef
Copy link
Contributor

@c8ef c8ef commented Jan 28, 2025

Closes #124694.

This patch adds the sys/uio/readv function.
ref: https://pubs.opengroup.org/onlinepubs/009696699/functions/readv.html

@c8ef c8ef marked this pull request as ready for review January 28, 2025 08:15
@llvmbot llvmbot added the libc label Jan 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 28, 2025

@llvm/pr-subscribers-libc

Author: None (c8ef)

Changes

Closes #124694.


Full diff: https://github.com/llvm/llvm-project/pull/124718.diff

9 Files Affected:

  • (modified) libc/config/linux/aarch64/entrypoints.txt (+1)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+1)
  • (modified) libc/include/sys/uio.yaml (+8)
  • (modified) libc/src/sys/uio/CMakeLists.txt (+7)
  • (modified) libc/src/sys/uio/linux/CMakeLists.txt (+15)
  • (added) libc/src/sys/uio/linux/readv.cpp (+27)
  • (added) libc/src/sys/uio/readv.h (+22)
  • (modified) libc/test/src/sys/uio/CMakeLists.txt (+17-1)
  • (added) libc/test/src/sys/uio/readv_test.cpp (+30)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 09eb51a3f8fc62..99b1187b43e11b 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -355,6 +355,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # sys/uio.h entrypoints
     libc.src.sys.uio.writev
+    libc.src.sys.uio.readv
 )
 
 if(LLVM_LIBC_INCLUDE_SCUDO)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 366e4d34294d15..df85f87140b88b 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -355,6 +355,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # sys/uio.h entrypoints
     libc.src.sys.uio.writev
+    libc.src.sys.uio.readv
 )
 
 if(LLVM_LIBC_INCLUDE_SCUDO)
diff --git a/libc/include/sys/uio.yaml b/libc/include/sys/uio.yaml
index 87c5bdff48245c..6d3f336b2b5204 100644
--- a/libc/include/sys/uio.yaml
+++ b/libc/include/sys/uio.yaml
@@ -15,3 +15,11 @@ functions:
       - type: int
       - type: const struct iovec *
       - type: int
+  - name: readv
+    standards:
+      - POSIX
+    return_type: ssize_t
+    arguments:
+      - type: int
+      - type: const struct iovec *
+      - type: int
diff --git a/libc/src/sys/uio/CMakeLists.txt b/libc/src/sys/uio/CMakeLists.txt
index 6298f86cd937da..c6a64297904103 100644
--- a/libc/src/sys/uio/CMakeLists.txt
+++ b/libc/src/sys/uio/CMakeLists.txt
@@ -8,3 +8,10 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.writev
 )
+
+add_entrypoint_object(
+  readv
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.readv
+)
diff --git a/libc/src/sys/uio/linux/CMakeLists.txt b/libc/src/sys/uio/linux/CMakeLists.txt
index 85a7a3ae4d5c21..7901c741f69a5a 100644
--- a/libc/src/sys/uio/linux/CMakeLists.txt
+++ b/libc/src/sys/uio/linux/CMakeLists.txt
@@ -12,3 +12,18 @@ add_entrypoint_object(
     libc.hdr.types.ssize_t
     libc.hdr.types.struct_iovec
 )
+
+add_entrypoint_object(
+  readv
+  SRCS
+    readv.cpp
+  HDRS
+    ../readv.h
+  DEPENDS
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.errno.errno
+    libc.hdr.types.ssize_t
+    libc.hdr.types.struct_iovec
+)
diff --git a/libc/src/sys/uio/linux/readv.cpp b/libc/src/sys/uio/linux/readv.cpp
new file mode 100644
index 00000000000000..3812f4dec150b8
--- /dev/null
+++ b/libc/src/sys/uio/linux/readv.cpp
@@ -0,0 +1,27 @@
+//===-- Implementation file for readv -------------------------------------===//
+//
+// 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/uio/readv.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(ssize_t, readv, (int fd, const iovec *iov, int iovcnt)) {
+  long ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_readv, fd, iov, iovcnt);
+  // On failure, return -1 and set errno.
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    return -1;
+  }
+  // On success, return number of bytes read.
+  return static_cast<ssize_t>(ret);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/uio/readv.h b/libc/src/sys/uio/readv.h
new file mode 100644
index 00000000000000..135b1e6fd1b5ac
--- /dev/null
+++ b/libc/src/sys/uio/readv.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for readv -----------------------------------===//
+//
+// 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_UIO_READV_H
+#define LLVM_LIBC_SRC_SYS_UIO_READV_H
+
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_iovec.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t readv(int fd, const iovec *iov, int iovcnt);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_UIO_READV_H
diff --git a/libc/test/src/sys/uio/CMakeLists.txt b/libc/test/src/sys/uio/CMakeLists.txt
index 45f8d14c161792..a58337ec5f01a5 100644
--- a/libc/test/src/sys/uio/CMakeLists.txt
+++ b/libc/test/src/sys/uio/CMakeLists.txt
@@ -1,8 +1,9 @@
 add_custom_target(libc_sys_uio_unittests)
+
 add_libc_unittest(
   writev_test
   SUITE
-  libc_sys_uio_unittests
+    libc_sys_uio_unittests
   SRCS
     writev_test.cpp
   DEPENDS
@@ -13,3 +14,18 @@ add_libc_unittest(
     libc.src.fcntl.open
     libc.test.UnitTest.ErrnoSetterMatcher
 )
+
+add_libc_unittest(
+  readv_test
+  SUITE
+    libc_sys_uio_unittests
+  SRCS
+    readv_test.cpp
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.__support.common
+    libc.src.sys.uio.readv
+    libc.src.unistd.close
+    libc.src.fcntl.open
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/uio/readv_test.cpp b/libc/test/src/sys/uio/readv_test.cpp
new file mode 100644
index 00000000000000..cf551d364653bc
--- /dev/null
+++ b/libc/test/src/sys/uio/readv_test.cpp
@@ -0,0 +1,30 @@
+//===-- Unittests for readv -----------------------------------------------===//
+//
+// 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/fcntl/open.h"
+#include "src/sys/uio/readv.h"
+#include "src/unistd/close.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+TEST(LlvmLibcSysUioReadvTest, SmokeTest) {
+  int fd = LIBC_NAMESPACE::open("/dev/urandom", O_RDONLY);
+  ASSERT_THAT(fd, returns(GT(0)).with_errno(EQ(0)));
+  char buf0[2];
+  char buf1[3];
+  struct iovec iov[2];
+  iov[0].iov_base = buf0;
+  iov[0].iov_len = 1;
+  iov[1].iov_base = buf1;
+  iov[1].iov_len = 2;
+  ASSERT_THAT(LIBC_NAMESPACE::readv(fd, iov, 2),
+              returns(EQ(3)).with_errno(EQ(0)));
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
+}

@c8ef c8ef changed the title [libc] implement sys/uio/writev [libc] implement sys/uio/readv Jan 28, 2025
Copy link
Member

@nickdesaulniers nickdesaulniers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch. Some additional includes should polish this up. We should probably define IOV_MAX in libc/include/llvm-libc-macros/limits-macros.h, too in order to make these functions more useful.

Comment on lines 23 to 28
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.errno.errno
libc.hdr.types.ssize_t
libc.hdr.types.struct_iovec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sort alphabetically, please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcSysUioReadvTest, SmokeTest) {
int fd = LIBC_NAMESPACE::open("/dev/urandom", O_RDONLY);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now that the existing libc/test/src/sys/uio/writev_test.cpp also opens /dev/random...but doesn't that mean these posix mandated functions won't run on windows? cc @SchrodingerZhu

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be more convenient to use an API like tmpfile? Or should we write to a file first and then read from it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think writing a sequence and reading it back is a better test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, let's get this fixed up first before landing then, please. Or at least file a bug saying this is an issue for the writev_test and readv_test, then add a link to that issue in a comment in both test files in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Switch to using local files.

@c8ef
Copy link
Contributor Author

c8ef commented Jan 29, 2025

We should probably define IOV_MAX in libc/include/llvm-libc-macros/limits-macros.h, too in order to make these functions more useful.

Done. I set it to 1024 here since the default value for glibc and musl is 1024.

@c8ef c8ef requested a review from nickdesaulniers January 29, 2025 02:51
@c8ef
Copy link
Contributor Author

c8ef commented Jan 31, 2025

Gentle ping~ @nickdesaulniers

@c8ef
Copy link
Contributor Author

c8ef commented Feb 4, 2025

Friendly ping!

Copy link
Member

@nickdesaulniers nickdesaulniers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing up the pre-existing test, too! That's above and beyond the call of duty.

We might want to use EXPECT_THAT, such that we always call unlink even if prior assertions fail, but open with O_CREAT may make that less of an issue. It might be more helpful for us one day to register an at exit helper to clean up any temp files, for use from unit tests.

@c8ef
Copy link
Contributor Author

c8ef commented Feb 6, 2025

We might want to use EXPECT_THAT, such that we always call unlink even if prior assertions fail, but open with O_CREAT may make that less of an issue. It might be more helpful for us one day to register an at exit helper to clean up any temp files, for use from unit tests.

Using an exit helper is a great idea. I will remember to use this approach in the future!

@c8ef c8ef merged commit e1c63bb into llvm:main Feb 6, 2025
14 checks passed
@c8ef c8ef deleted the readv branch February 6, 2025 01:28
@llvm-ci
Copy link
Collaborator

llvm-ci commented Feb 6, 2025

LLVM Buildbot has detected a new failure on builder premerge-monolithic-linux running on premerge-linux-1 while building libc at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/153/builds/22071

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
...
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/suppressions.cpp (94130 of 98156)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Misc/Posix/ubsan_options.cpp (94131 of 98156)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/uadd-overflow.cpp (94132 of 98156)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/incdec-overflow.cpp (94133 of 98156)
PASS: UBSan-MemorySanitizer-x86_64 :: TestCases/Misc/local_bounds.cpp (94134 of 98156)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Misc/Posix/static-link.cpp (94135 of 98156)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Misc/bool.cpp (94136 of 98156)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Misc/bool.m (94137 of 98156)
UNSUPPORTED: UBSan-Standalone-lld-x86_64 :: TestCases/Misc/no-interception.cpp (94138 of 98156)
TIMEOUT: MLIR :: Examples/standalone/test.toy (94139 of 98156)
******************** TEST 'MLIR :: Examples/standalone/test.toy' FAILED ********************
Exit Code: 1
Timeout: Reached timeout of 60 seconds

Command Output (stdout):
--
# RUN: at line 1
"/etc/cmake/bin/cmake" "/build/buildbot/premerge-monolithic-linux/llvm-project/mlir/examples/standalone" -G "Ninja"  -DCMAKE_CXX_COMPILER=/usr/bin/clang++  -DCMAKE_C_COMPILER=/usr/bin/clang   -DLLVM_ENABLE_LIBCXX=OFF -DMLIR_DIR=/build/buildbot/premerge-monolithic-linux/build/lib/cmake/mlir  -DLLVM_USE_LINKER=lld  -DPython3_EXECUTABLE="/usr/bin/python3.10"
# executed command: /etc/cmake/bin/cmake /build/buildbot/premerge-monolithic-linux/llvm-project/mlir/examples/standalone -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_C_COMPILER=/usr/bin/clang -DLLVM_ENABLE_LIBCXX=OFF -DMLIR_DIR=/build/buildbot/premerge-monolithic-linux/build/lib/cmake/mlir -DLLVM_USE_LINKER=lld -DPython3_EXECUTABLE=/usr/bin/python3.10
# .---command stdout------------
# | -- The CXX compiler identification is Clang 16.0.6
# | -- The C compiler identification is Clang 16.0.6
# | -- Detecting CXX compiler ABI info
# | -- Detecting CXX compiler ABI info - done
# | -- Check for working CXX compiler: /usr/bin/clang++ - skipped
# | -- Detecting CXX compile features
# | -- Detecting CXX compile features - done
# | -- Detecting C compiler ABI info
# | -- Detecting C compiler ABI info - done
# | -- Check for working C compiler: /usr/bin/clang - skipped
# | -- Detecting C compile features
# | -- Detecting C compile features - done
# | -- Looking for histedit.h
# | -- Looking for histedit.h - found
# | -- Found LibEdit: /usr/include (found version "2.11") 
# | -- Found ZLIB: /usr/lib/x86_64-linux-gnu/libz.so (found version "1.2.11") 
# | -- Found LibXml2: /usr/lib/x86_64-linux-gnu/libxml2.so (found version "2.9.13") 
# | -- Using MLIRConfig.cmake in: /build/buildbot/premerge-monolithic-linux/build/lib/cmake/mlir
# | -- Using LLVMConfig.cmake in: /build/buildbot/premerge-monolithic-linux/build/lib/cmake/llvm
# | -- Linker detection: unknown
# | -- Performing Test LLVM_LIBSTDCXX_MIN
# | -- Performing Test LLVM_LIBSTDCXX_MIN - Success
# | -- Performing Test LLVM_LIBSTDCXX_SOFT_ERROR
# | -- Performing Test LLVM_LIBSTDCXX_SOFT_ERROR - Success
# | -- Performing Test CXX_SUPPORTS_CUSTOM_LINKER
# | -- Performing Test CXX_SUPPORTS_CUSTOM_LINKER - Success
# | -- Performing Test C_SUPPORTS_FPIC
# | -- Performing Test C_SUPPORTS_FPIC - Success
# | -- Performing Test CXX_SUPPORTS_FPIC

Icohedron pushed a commit to Icohedron/llvm-project that referenced this pull request Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc] implement sys/uio/readv
5 participants