[libc-commits] [libc] [libc] pipe(2) linux syscall wrapper and unittest (PR #85514)

via libc-commits libc-commits at lists.llvm.org
Sat Mar 16 03:40:07 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: None (muffpy)

<details>
<summary>Changes</summary>



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


8 Files Affected:

- (modified) libc/config/linux/x86_64/entrypoints.txt (+1) 
- (modified) libc/spec/linux.td (+17) 
- (modified) libc/src/unistd/CMakeLists.txt (+7) 
- (modified) libc/src/unistd/linux/CMakeLists.txt (+13) 
- (added) libc/src/unistd/linux/pipe2.cpp (+35) 
- (added) libc/src/unistd/pipe2.h (+20) 
- (modified) libc/test/src/unistd/CMakeLists.txt (+19) 
- (added) libc/test/src/unistd/pipe2_test.cpp (+64) 


``````````diff
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 4fb31c593b9dc7..702894b8a21d26 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -297,6 +297,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.link
     libc.src.unistd.linkat
     libc.src.unistd.lseek
+    libc.src.unistd.pipe2
     libc.src.unistd.pread
     libc.src.unistd.pwrite
     libc.src.unistd.read
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index f91f55ddac7846..80d3e860ed6c46 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -3,6 +3,8 @@ def StructEpollEventPtr : PtrType<StructEpollEvent>;
 
 def StructEpollData : NamedType<"struct epoll_data">;
 
+def Pipe2fdArrayT : NamedType<"__pipe2fd_array_t">;
+
 def Linux : StandardSpec<"Linux"> {
   HeaderSpec Errno = HeaderSpec<
       "errno.h",
@@ -264,6 +266,20 @@ def Linux : StandardSpec<"Linux"> {
       ]
   >;
 
+  HeaderSpec UniStd = HeaderSpec<
+    "unistd.h",
+    [], // Macros
+    [Pipe2fdArrayT], // Types
+    [], // Enumerations
+    [
+        FunctionSpec<
+          "pipe2",
+          RetValSpec<IntType>,
+          [ArgSpec<Pipe2fdArrayT>, ArgSpec<IntType>]
+        >,
+    ]
+  >;
+
   let Headers = [
     Errno,
     SysEpoll,
@@ -272,5 +288,6 @@ def Linux : StandardSpec<"Linux"> {
     SysRandom,
     SysTime,
     Signal,
+    UniStd
   ];
 }
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index e22b0e1872caa1..c63f170df29b96 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -149,6 +149,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.lseek
 )
 
+add_entrypoint_object(
+  pipe2
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.pipe2
+)
+
 add_entrypoint_object(
   pread
   ALIAS
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index df85d44e9e9edc..3496d32a18f2e4 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -273,6 +273,19 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  pipe2
+  SRCS
+    pipe2.cpp
+  HDRS
+    ../pipe2.h
+  DEPENDS
+    libc.include.unistd
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   pread
   SRCS
diff --git a/libc/src/unistd/linux/pipe2.cpp b/libc/src/unistd/linux/pipe2.cpp
new file mode 100644
index 00000000000000..9f2e5390104703
--- /dev/null
+++ b/libc/src/unistd/linux/pipe2.cpp
@@ -0,0 +1,35 @@
+//===-- Linux implementation of pipe2 ---------------------------------------===//
+//
+// 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/unistd/pipe2.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, pipe2, (int pipefd[2], int flags)) {
+    int ret;
+#ifdef SYS_pipe2
+  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pipe2, pipefd, flags);
+#elif defined (SYS_pipe)
+  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pipe, pipefd);
+#else 
+#error "pipe and pipe2 not available."
+#endif
+  if (ret == -1) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/unistd/pipe2.h b/libc/src/unistd/pipe2.h
new file mode 100644
index 00000000000000..3cf5d81f1f280e
--- /dev/null
+++ b/libc/src/unistd/pipe2.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pipe2 ---------------------------*- 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_UNISTD_PIPE2_H
+#define LLVM_LIBC_SRC_UNISTD_PIPE2_H
+
+#include <unistd.h>
+
+namespace LIBC_NAMESPACE {
+
+int pipe2(int pipefd[2], int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_UNISTD_PIPE2_H
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 3a7fe6f45c0911..76212a38467586 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -444,3 +444,22 @@ add_libc_test(
     libc.src.stdio.fopencookie
     libc.src.stdio.fflush
 )
+
+add_libc_unittest(
+  pipe2_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    pipe2_test.cpp
+  DEPENDS
+    libc.include.errno
+    libc.include.unistd
+    libc.src.errno.errno
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.unistd.pipe2
+    libc.src.unistd.read
+    libc.src.unistd.unlink
+    libc.src.unistd.write
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
\ No newline at end of file
diff --git a/libc/test/src/unistd/pipe2_test.cpp b/libc/test/src/unistd/pipe2_test.cpp
new file mode 100644
index 00000000000000..8c91078df466c3
--- /dev/null
+++ b/libc/test/src/unistd/pipe2_test.cpp
@@ -0,0 +1,64 @@
+//===-- Unittests for pipe2 -------------------------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/fcntl/open.h"
+#include "src/unistd/close.h"
+#include "src/unistd/pipe2.h"
+#include "src/unistd/read.h"
+#include "src/unistd/unlink.h"
+#include "src/unistd/write.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/stat.h>
+
+TEST(LlvmLibcPipe2Test, ReadAndWriteViaPipe2) {
+  int pipefd[2];
+  int flags;
+
+  LIBC_NAMESPACE::libc_errno = 0;
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+  // Create pipe(2) with flags set to 0
+  flags = 0;
+  ASSERT_NE(LIBC_NAMESPACE::pipe2(pipefd, flags), -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  // Write something via the pipe and read from other end
+  constexpr char MESSAGE[] = "Hello from the write end!";
+  constexpr size_t MESSAGE_SIZE = sizeof(MESSAGE);
+  char buf[MESSAGE_SIZE];
+  ASSERT_EQ(ssize_t(MESSAGE_SIZE),
+            LIBC_NAMESPACE::write(pipefd[1], MESSAGE, MESSAGE_SIZE));
+  ASSERT_EQ(ssize_t(MESSAGE_SIZE),
+            LIBC_NAMESPACE::read(pipefd[0], buf, MESSAGE_SIZE));
+  ASSERT_STREQ(buf, MESSAGE);
+
+  // Close the pipe file descriptors
+  ASSERT_NE(LIBC_NAMESPACE::close(pipefd[0]), -1);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_NE(LIBC_NAMESPACE::close(pipefd[1]), -1);
+  ASSERT_ERRNO_SUCCESS();
+}
+
+TEST(LlvmLibcPipe2Test, Pipe2BadFlags) {
+  int badflags = -1;
+  int pipefd[2];
+
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+  ASSERT_THAT(LIBC_NAMESPACE::pipe2(pipefd, badflag), Fails(EBADF));
+}
+
+TEST(LlvmLibcPipe2Test, Pipe2BadFD) {
+  int flags = 0;
+  int badpipefd[1];
+
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+  ASSERT_THAT(LIBC_NAMESPACE::pipe2(badpipefd, flags), Fails(EBADF));
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/85514


More information about the libc-commits mailing list