Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,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
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
6 changes: 6 additions & 0 deletions libc/include/llvm-libc-macros/linux/fcntl-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
#define O_NOFOLLOW 00400000
#endif

#ifdef __aarch64__
#define O_DIRECT 0200000
#else
#define O_DIRECT 00040000
#endif

#define O_TRUNC 00001000
#define O_TMPFILE (020000000 | O_DIRECTORY)

Expand Down
20 changes: 20 additions & 0 deletions libc/include/llvm-libc-macros/linux/watch-queue-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Definition of macros from watch-queue.h ---------------------------------===//
Copy link
Author

Choose a reason for hiding this comment

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

git clang-format does not like this. Please ignore for now as this file may not even be required.

Copy link
Contributor

Choose a reason for hiding this comment

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

That header is way too long, shorten it to 80 characters and it will stop doing this.

//
// 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
//
//===----------------------------------------------------------------------===//

// References
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/watch_queue.h
// https://kernelnewbies.org/Linux_5.8#Core_.28various.29
// https://docs.kernel.org/core-api/watch_queue.html

#ifndef LLVM_LIBC_MACROS_LINUX_WATCH_QUEUE_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_WATCH_QUEUE_MACROS_H

#define O_NOTIFICATION_PIPE \
O_EXCL /* Parameter to pipe2() selecting notification pipe */
Copy link
Member

Choose a reason for hiding this comment

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

Ah, this is not something we should be providing; it's ok to #include <linux/watch_queue.h> for the definition of O_NOTIFICATION_PIPE.

I think that include should go in libc/include/llvm-libc-macros/unistd-macros.h.

libc/include/llvm-libc-macros/unistd-macros.h should then be included in libc/test/src/unistd/pipe2_test.cpp.

Copy link
Author

Choose a reason for hiding this comment

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

There are weird conflict errors coming from including libc/include/llvm-libc-macros/unistd-macros.h in the pipe2_test.cpp file because I have included src/unistd/read.h too which contains #include <unistd.h>. And <unistd.h> has some beef with libc/.../unistd-macros.h.

[27/29] Building CXX object projects/libc/test/src/unistd/CMa...ibc.test.src.unistd.pipe2_test.__build__.dir/pipe2_test.cpp.o
FAILED: projects/libc/test/src/unistd/CMakeFiles/libc.test.src.unistd.pipe2_test.__build__.dir/pipe2_test.cpp.o 
/usr/bin/clang++ -DLIBC_NAMESPACE=__llvm_libc_19_0_0_git -I/home/llvm-project/build/projects/libc/test/src/unistd -I/home/llvm-project/libc/test/src/unistd -I/home/llvm-project/libc -isystem /home/llvm-project/build/projects/libc/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -fpie -mcpu=native -fno-exceptions -fno-rtti -std=c++17 -MD -MT projects/libc/test/src/unistd/CMakeFiles/libc.test.src.unistd.pipe2_test.__build__.dir/pipe2_test.cpp.o -MF projects/libc/test/src/unistd/CMakeFiles/libc.test.src.unistd.pipe2_test.__build__.dir/pipe2_test.cpp.o.d -o projects/libc/test/src/unistd/CMakeFiles/libc.test.src.unistd.pipe2_test.__build__.dir/pipe2_test.cpp.o -c /home/llvm-project/libc/test/src/unistd/pipe2_test.cpp
In file included from /home/llvm-project/libc/test/src/unistd/pipe2_test.cpp:15:
In file included from /home/llvm-project/libc/src/unistd/read.h:12:
In file included from /usr/include/unistd.h:630:
/usr/include/aarch64-linux-gnu/bits/confname.h:133:5: error: expected identifier
    _SC_PAGESIZE,
    ^
/home/llvm-project/libc/include/llvm-libc-macros/linux/unistd-macros.h:21:22: note: expanded from macro '_SC_PAGESIZE'
#define _SC_PAGESIZE 1
                     ^
In file included from /home/llvm-project/libc/test/src/unistd/pipe2_test.cpp:15:
In file included from /home/llvm-project/libc/src/unistd/read.h:12:
/usr/include/unistd.h:1091:35: error: expected ')'
extern long int syscall (long int __sysno, ...) __THROW;
                                  ^
/usr/include/unistd.h:1091:17: note: to match this '('
extern long int syscall (long int __sysno, ...) __THROW;
                ^
/home/llvm-project/libc/include/llvm-libc-macros/linux/unistd-macros.h:31:22: note: expanded from macro 'syscall'
#define syscall(...) __syscall_helper(__VA_ARGS__, 0, 1, 2, 3, 4, 5, 6)
                     ^
/home/llvm-project/libc/include/llvm-libc-macros/linux/unistd-macros.h:29:29: note: expanded from macro '__syscall_helper'
  __llvm_libc_syscall((long)(sysno), (long)(arg1), (long)(arg2), (long)(arg3), \
                            ^
In file included from /home/llvm-project/libc/test/src/unistd/pipe2_test.cpp:15:
In file included from /home/llvm-project/libc/src/unistd/read.h:12:
/usr/include/unistd.h:1091:17: error: expected expression
extern long int syscall (long int __sysno, ...) __THROW;
                ^
/home/llvm-project/libc/include/llvm-libc-macros/linux/unistd-macros.h:31:22: note: expanded from macro 'syscall'
#define syscall(...) __syscall_helper(__VA_ARGS__, 0, 1, 2, 3, 4, 5, 6)
                     ^
/home/llvm-project/libc/include/llvm-libc-macros/linux/unistd-macros.h:29:36: note: expanded from macro '__syscall_helper'
  __llvm_libc_syscall((long)(sysno), (long)(arg1), (long)(arg2), (long)(arg3), \
                                   ^
In file included from /home/llvm-project/libc/test/src/unistd/pipe2_test.cpp:15:
In file included from /home/llvm-project/libc/src/unistd/read.h:12:
/usr/include/unistd.h:1091:44: error: expected expression
extern long int syscall (long int __sysno, ...) __THROW;
                                           ^
/usr/include/unistd.h:1091:48: error: expected ';' after top level declarator
extern long int syscall (long int __sysno, ...) __THROW;
                                               ^
5 errors generated.
ninja: build stopped: subcommand failed.

PS: Btw, this error happens even without #include <linux/watch_queue.h> in libc/include/llvm-libc-macros/unistd-macros.h but that should be clear from the error.

Copy link
Member

Choose a reason for hiding this comment

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

And <unistd.h>

Yeah, that's a pretty endemic issue throughout our libc; most of the includes of <unistd.h> currently look incorrect to me.

Let me see if I can clean that up real quick, then you can rebase on my change. I'll try to get that posted real quick, let's see.

Copy link
Member

Choose a reason for hiding this comment

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

Mind waiting for #85971 to land, then are you comfortable rebasing your changes on top of that? I'd wait until it lands; it's possible to rebase your branch on my branch BEFORE my branch lands, but IME if my branch gets updated before landing, it causes merge conflicts getting yours landed that are a waste of your time to resolve.


#endif // LLVM_LIBC_MACROS_LINUX_WATCH_QUEUE_MACROS_H
15 changes: 15 additions & 0 deletions libc/spec/linux.td
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,20 @@ def Linux : StandardSpec<"Linux"> {
]
>;

HeaderSpec UniStd = HeaderSpec<
"unistd.h",
[], // Macros
[], // Types
[], // Enumerations
[
FunctionSpec<
"pipe2",
RetValSpec<IntType>,
[ArgSpec<IntPtr>, ArgSpec<IntType>] // TODO: use int[2] array for the first ArgSpec when possible
>,
]
>;

let Headers = [
Errno,
SysEpoll,
Expand All @@ -272,5 +286,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
33 changes: 33 additions & 0 deletions libc/src/unistd/linux/pipe2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- 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);
#else
#error "pipe2 not available."
#endif
if (ret < 0) {
libc_errno = -ret;
return -1;
}
return ret;
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/unistd/pipe2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- 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

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
)
93 changes: 93 additions & 0 deletions libc/test/src/unistd/pipe2_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//===-- 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 "include/llvm-libc-macros/linux/fcntl-macros.h"
#include "include/llvm-libc-macros/linux/watch-queue-macros.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

The way we interact with public headers changed since this patch was written. The short version is we're now using proxy headers in /hdr/ instead of including the types from include directly. You can see an example of this in the patch that adds pipe: https://github.com/llvm/llvm-project/pull/84587/files#diff-0d107f2b3067e045736b456ccc6d3523aedade072afc031562b9103cb1972805

Sorry about the delay and the changing design, but this should be the final change needed before landing.

#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, Pipe2CreationTest) {
int pipefd[2];
int flags;

LIBC_NAMESPACE::libc_errno = 0;
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;

// Create pipe(2) with all valid flags set
#ifdef CONFIG_WATCH_QUEUE
flags = O_CLOEXEC | O_NONBLOCK | O_DIRECT | O_NOTIFICATION_PIPE;
#else
flags = O_CLOEXEC | O_NONBLOCK | O_DIRECT;
#endif
ASSERT_NE(LIBC_NAMESPACE::pipe2(pipefd, flags), -1);
ASSERT_ERRNO_SUCCESS();

// Check if file descriptors are distinct and valid
ASSERT_GE(pipefd[0], 0);
ASSERT_GE(pipefd[1], 0);
ASSERT_NE(pipefd[0], pipefd[1]);

// Check file status flags associated with pipe file descriptors
ASSERT_TRUE((fcntl(pipefd[0], F_GETFL) & flags) != 0);
ASSERT_TRUE((fcntl(pipefd[1], F_GETFL) & flags) != 0);

// 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, 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 = 0xDEADBEEF;
int pipefd[2];

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

TEST(LlvmLibcPipe2Test, Pipe2InvalidPipeFD) {
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
ASSERT_THAT(LIBC_NAMESPACE::pipe2(NULL, 0), Fails(EFAULT));
}