Skip to content

[libc] implement sys/uio/writev #122233

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

Conversation

SchrodingerZhu
Copy link
Contributor

implement sys/uio/writev according to POSIX standard. This vectorized IO API is needed by many logging libraries to achieve atomic logging multiple strings.

@llvmbot
Copy link
Member

llvmbot commented Jan 9, 2025

@llvm/pr-subscribers-libc

Author: Schrodinger ZHU Yifan (SchrodingerZhu)

Changes

implement sys/uio/writev according to POSIX standard. This vectorized IO API is needed by many logging libraries to achieve atomic logging multiple strings.


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

15 Files Affected:

  • (modified) libc/config/linux/aarch64/entrypoints.txt (+3)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+3)
  • (modified) libc/hdr/types/CMakeLists.txt (+9)
  • (added) libc/hdr/types/struct_iovec.h (+21)
  • (modified) libc/include/CMakeLists.txt (+10)
  • (added) libc/include/sys/uio.h.def (+16)
  • (added) libc/include/sys/uio.yaml (+17)
  • (modified) libc/src/sys/CMakeLists.txt (+1)
  • (added) libc/src/sys/uio/CMakeLists.txt (+10)
  • (added) libc/src/sys/uio/linux/CMakeLists.txt (+14)
  • (added) libc/src/sys/uio/linux/writev.cpp (+27)
  • (added) libc/src/sys/uio/writev.h (+22)
  • (modified) libc/test/src/sys/CMakeLists.txt (+1)
  • (added) libc/test/src/sys/uio/CMakeLists.txt (+15)
  • (added) libc/test/src/sys/uio/writev_test.cpp (+29)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 00f0c6a8bfb8e4..fc2b0e91c1286d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -350,6 +350,9 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # wchar.h entrypoints
     libc.src.wchar.wctob
+
+    # sys/uio.h entrypoints
+    libc.src.sys.uio.writev
 )
 
 if(LLVM_LIBC_INCLUDE_SCUDO)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 7e549607716c02..e7b049c0a66388 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -350,6 +350,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     # wchar.h entrypoints
     libc.src.wchar.wctob
     libc.src.wchar.btowc
+
+    # sys/uio.h entrypoints
+    libc.src.sys.uio.writev
 )
 
 if(LLVM_LIBC_INCLUDE_SCUDO)
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 1674de14201524..3dfa38a020fad0 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -333,3 +333,12 @@ add_proxy_header_library(
   FULL_BUILD_DEPENDS
     libc.include.llvm-libc-types.uid_t
 )
+
+add_proxy_header_library(
+  struct_iovec
+  HDRS
+    struct_iovec.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.struct_iovec
+    libc.include.sys_uio
+)
diff --git a/libc/hdr/types/struct_iovec.h b/libc/hdr/types/struct_iovec.h
new file mode 100644
index 00000000000000..e34efdb8ddfe4b
--- /dev/null
+++ b/libc/hdr/types/struct_iovec.h
@@ -0,0 +1,21 @@
+//===-- Proxy for struct iovec  -------------------------------------------===//
+//
+// 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_HDR_TYPES_STRUCT_FLOCK64_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_FLOCK64_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_iovec.h"
+
+#else
+
+#include <sys/uio.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_FLOCK64_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 568bb05d923023..e5ceea360d3965 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -632,6 +632,16 @@ add_header_macro(
     .llvm-libc-types.struct_utsname
 )
 
+add_header_macro(
+  sys_uio
+  ../libc/include/sys/uio.yaml
+  sys/uio.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-types.struct_iovec
+    .llvm-libc-types.ssize_t
+)
+
 add_header_macro(
   sys_wait
   ../libc/include/sys/wait.yaml
diff --git a/libc/include/sys/uio.h.def b/libc/include/sys/uio.h.def
new file mode 100644
index 00000000000000..c48aaf91d52f19
--- /dev/null
+++ b/libc/include/sys/uio.h.def
@@ -0,0 +1,16 @@
+//===-- POSIX header auxv.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_UIO_H
+#define LLVM_LIBC_SYS_UIO_H
+
+#include "__llvm-libc-common.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_UIO_H
diff --git a/libc/include/sys/uio.yaml b/libc/include/sys/uio.yaml
new file mode 100644
index 00000000000000..808d8ec790198e
--- /dev/null
+++ b/libc/include/sys/uio.yaml
@@ -0,0 +1,17 @@
+header: sys/uio.h
+header_template: uio.h.def
+macros: []
+types: 
+  - type_name: struct_iovec
+  - type_name: ssize_t
+enums: []
+objects: []
+functions:
+  - name: writev
+    standards:
+      - POSIX
+    return_type: ssize_t
+    arguments:
+      - type: int
+      - type: const struct iovec *
+      - type: int
diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index adc666b94202f7..bb177f11c6d628 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -11,3 +11,4 @@ add_subdirectory(statvfs)
 add_subdirectory(utsname)
 add_subdirectory(wait)
 add_subdirectory(prctl)
+add_subdirectory(uio)
diff --git a/libc/src/sys/uio/CMakeLists.txt b/libc/src/sys/uio/CMakeLists.txt
new file mode 100644
index 00000000000000..6298f86cd937da
--- /dev/null
+++ b/libc/src/sys/uio/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  writev
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.writev
+)
diff --git a/libc/src/sys/uio/linux/CMakeLists.txt b/libc/src/sys/uio/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..85a7a3ae4d5c21
--- /dev/null
+++ b/libc/src/sys/uio/linux/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_entrypoint_object(
+  writev
+  SRCS
+    writev.cpp
+  HDRS
+    ../writev.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/writev.cpp b/libc/src/sys/uio/linux/writev.cpp
new file mode 100644
index 00000000000000..a3bb8986d522ec
--- /dev/null
+++ b/libc/src/sys/uio/linux/writev.cpp
@@ -0,0 +1,27 @@
+//===-- Implementation file for writev ------------------------------------===//
+//
+// 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/writev.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, writev, (int fd, const iovec *iov, int iovcnt)) {
+  long ret = LIBC_NAMESPACE::syscall_impl<long>(SYS_writev, 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 written.
+  return static_cast<ssize_t>(ret);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/uio/writev.h b/libc/src/sys/uio/writev.h
new file mode 100644
index 00000000000000..787bc4b3044b0f
--- /dev/null
+++ b/libc/src/sys/uio/writev.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for writev ----------------------------------===//
+//
+// 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_WRITEV_H
+#define LLVM_LIBC_SRC_SYS_UIO_WRITEV_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 writev(int fd, const iovec *iov, int iovcnt);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_UIO_WRITEV_H
diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index dc0aa8bf7b75dc..9e9293aab628f4 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -11,3 +11,4 @@ add_subdirectory(wait)
 add_subdirectory(prctl)
 add_subdirectory(auxv)
 add_subdirectory(epoll)
+add_subdirectory(uio)
diff --git a/libc/test/src/sys/uio/CMakeLists.txt b/libc/test/src/sys/uio/CMakeLists.txt
new file mode 100644
index 00000000000000..45f8d14c161792
--- /dev/null
+++ b/libc/test/src/sys/uio/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_custom_target(libc_sys_uio_unittests)
+add_libc_unittest(
+  writev_test
+  SUITE
+  libc_sys_uio_unittests
+  SRCS
+    writev_test.cpp
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.__support.common
+    libc.src.sys.uio.writev
+    libc.src.unistd.close
+    libc.src.fcntl.open
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/uio/writev_test.cpp b/libc/test/src/sys/uio/writev_test.cpp
new file mode 100644
index 00000000000000..a9a314813182d2
--- /dev/null
+++ b/libc/test/src/sys/uio/writev_test.cpp
@@ -0,0 +1,29 @@
+//===-- Unittests for writev ----------------------------------------------===//
+//
+// 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/writev.h"
+#include "src/unistd/close.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+TEST(LlvmLibcSysUioWritevTest, SmokeTest) {
+  int fd = LIBC_NAMESPACE::open("/dev/null", O_WRONLY);
+  ASSERT_THAT(fd, returns(GT(0)).with_errno(EQ(0)));
+  const char *data = "Hello, World!\n";
+  struct iovec iov[2];
+  iov[0].iov_base = const_cast<char *>(data);
+  iov[0].iov_len = 7;
+  iov[1].iov_base = const_cast<char *>(data + 7);
+  iov[1].iov_len = 8;
+  ASSERT_THAT(LIBC_NAMESPACE::writev(fd, iov, 2),
+              returns(EQ(15)).with_errno(EQ(0)));
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
+}

@SchrodingerZhu SchrodingerZhu requested a review from jhuber6 January 9, 2025 08:33
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.

please fix the two copy pasta's first

@SchrodingerZhu SchrodingerZhu merged commit 73dd730 into llvm:main Jan 10, 2025
9 of 10 checks passed
@SchrodingerZhu SchrodingerZhu deleted the libc/src/sys/uio/linux/writev branch January 10, 2025 04:49
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 11, 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/19318

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/ImplicitConversion/signed-integer-truncation-or-sign-change-summary.cpp (93346 of 97378)
PASS: UBSan-MemorySanitizer-lld-x86_64 :: TestCases/ImplicitConversion/signed-integer-truncation-ignorelist.c (93347 of 97378)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/ImplicitConversion/signed-integer-truncation-summary.cpp (93348 of 97378)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/div-overflow.cpp (93349 of 97378)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/bit-int-pass.c (93350 of 97378)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/ImplicitConversion/unsigned-integer-truncation-summary.cpp (93351 of 97378)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/bit-int.c (93352 of 97378)
UNSUPPORTED: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/summary.cpp (93353 of 97378)
PASS: UBSan-Standalone-lld-x86_64 :: TestCases/Integer/mul-overflow.cpp (93354 of 97378)
TIMEOUT: MLIR :: Examples/standalone/test.toy (93355 of 97378)
******************** 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

BaiXilin pushed a commit to BaiXilin/llvm-fix-vnni-instr-types that referenced this pull request Jan 12, 2025
implement sys/uio/writev according to POSIX standard. This vectorized IO
API is needed by many logging libraries to achieve atomic logging
multiple strings.
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.

4 participants