Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions libc/spec/linux.td
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand All @@ -272,5 +288,6 @@ def Linux : StandardSpec<"Linux"> {
SysRandom,
SysTime,
Signal,
UniStd
];
}
7 changes: 7 additions & 0 deletions libc/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions libc/src/unistd/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions libc/src/unistd/linux/pipe2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- 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
21 changes: 21 additions & 0 deletions libc/src/unistd/pipe2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- 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
17 changes: 17 additions & 0 deletions libc/test/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,20 @@ 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.unistd.close
libc.src.unistd.pipe2
libc.src.unistd.read
libc.src.unistd.write
libc.test.UnitTest.ErrnoSetterMatcher
)
63 changes: 63 additions & 0 deletions libc/test/src/unistd/pipe2_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===-- 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/unistd/close.h"
#include "src/unistd/pipe2.h"
#include "src/unistd/read.h"
#include "src/unistd/write.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

#include <fcntl.h>
Copy link
Member

Choose a reason for hiding this comment

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

Please include include/llvm-libc-macros/linux/fcntl-macros.h instead.

Copy link
Member

Choose a reason for hiding this comment

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

and make sure to remove <fcntl.h>. If you get a compile time failure as a result, let me know what it is.

Copy link
Author

Choose a reason for hiding this comment

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

I need <fcntl.h> for this subtest in Pipe2CreationTest.


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;
Copy link
Member

Choose a reason for hiding this comment

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

In terms of flags we define, it looks like we only define O_CLOEXEC and O_NONBLOCK. You should add definitions of O_DIRECT and O_NOTIFICATION_PIPE to include/llvm-libc-macros/linux/fcntl-macros.h.

Copy link
Author

Choose a reason for hiding this comment

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

Done. And created a new uapi header for O_NOTIFICATION_PIPE. May I ask if we are currently not categorizing headers into things like asm-generic and uapi?

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, Pipe2InvalidFlags) {
int invalidflags = O_CREAT | O_PATH | O_SYNC;
int pipefd[2];

using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
ASSERT_THAT(LIBC_NAMESPACE::pipe2(pipefd, invalidflags), Fails(EINVAL));
}

TEST(LlvmLibcPipe2Test, Pipe2InvalidPipeFD) {
int flags = 0;
int invalidpipefd[1];

using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
ASSERT_THAT(LIBC_NAMESPACE::pipe2(invalidpipefd, flags), Fails(EFAULT));
}