38 changes: 38 additions & 0 deletions libc/src/sys/epoll/linux/epoll_create.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//===---------- Linux implementation of the epoll_create function ---------===//
//
// 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/epoll/epoll_create.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.
michaelrj-google marked this conversation as resolved.
Show resolved Hide resolved

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, epoll_create, ([[maybe_unused]] int size)) {
#ifdef SYS_epoll_create
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_epoll_create, size);
#elif defined(SYS_epoll_create1)
nickdesaulniers marked this conversation as resolved.
Show resolved Hide resolved
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_epoll_create1, 0);
#else
#error \
"epoll_create and epoll_create1 are unavailable. Unable to build epoll_create."
#endif

// A negative return value indicates an error with the magnitude of the
// value being the error code.
if (ret < 0) {
libc_errno = -ret;
return -1;
}

return ret;
}

} // namespace LIBC_NAMESPACE
31 changes: 31 additions & 0 deletions libc/src/sys/epoll/linux/epoll_create1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===---------- Linux implementation of the epoll_create1 function --------===//
//
// 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/epoll/epoll_create1.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, epoll_create1, (int flags)) {
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_epoll_create1, flags);

// A negative return value indicates an error with the magnitude of the
// value being the error code.
if (ret < 0) {
libc_errno = -ret;
return -1;
}

return ret;
}

} // namespace LIBC_NAMESPACE
34 changes: 34 additions & 0 deletions libc/src/sys/epoll/linux/epoll_ctl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===---------- Linux implementation of the epoll_ctl function ----------===//
//
// 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/epoll/epoll_ctl.h"

#include "hdr/types/struct_epoll_event.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, epoll_ctl,
(int epfd, int op, int fd, epoll_event *event)) {
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_epoll_ctl, epfd, op, fd,
reinterpret_cast<long>(event));

// A negative return value indicates an error with the magnitude of the
// value being the error code.
if (ret < 0) {
libc_errno = -ret;
return -1;
}

return ret;
}

} // namespace LIBC_NAMESPACE
5 changes: 3 additions & 2 deletions libc/src/sys/epoll/linux/epoll_pwait.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "src/sys/epoll/epoll_pwait.h"

#include "hdr/signal_macros.h" // for NSIG
#include "hdr/types/sigset_t.h"
#include "hdr/types/struct_epoll_event.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
Expand All @@ -23,7 +24,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait,
int timeout, const sigset_t *sigmask)) {
int ret = LIBC_NAMESPACE::syscall_impl<int>(
SYS_epoll_pwait, epfd, reinterpret_cast<long>(events), maxevents, timeout,
reinterpret_cast<long>(sigmask), sizeof(sigset_t));
reinterpret_cast<long>(sigmask), NSIG / 8);

// A negative return value indicates an error with the magnitude of the
// value being the error code.
Expand All @@ -32,7 +33,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait,
return -1;
}

return 0;
return ret;
}

} // namespace LIBC_NAMESPACE
5 changes: 3 additions & 2 deletions libc/src/sys/epoll/linux/epoll_pwait2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "src/sys/epoll/epoll_pwait2.h"

#include "hdr/signal_macros.h" // for NSIG
#include "hdr/types/sigset_t.h"
#include "hdr/types/struct_epoll_event.h"
#include "hdr/types/struct_timespec.h"
Expand All @@ -25,7 +26,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait2,
int ret = LIBC_NAMESPACE::syscall_impl<int>(
SYS_epoll_pwait2, epfd, reinterpret_cast<long>(events), maxevents,
reinterpret_cast<long>(timeout), reinterpret_cast<long>(sigmask),
sizeof(sigset_t));
NSIG / 8);

// A negative return value indicates an error with the magnitude of the
// value being the error code.
Expand All @@ -34,7 +35,7 @@ LLVM_LIBC_FUNCTION(int, epoll_pwait2,
return -1;
}

return 0;
return ret;
}

} // namespace LIBC_NAMESPACE
5 changes: 3 additions & 2 deletions libc/src/sys/epoll/linux/epoll_wait.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "src/sys/epoll/epoll_wait.h"

#include "hdr/signal_macros.h" // for NSIG
#include "hdr/types/sigset_t.h"
#include "hdr/types/struct_epoll_event.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
Expand All @@ -27,7 +28,7 @@ LLVM_LIBC_FUNCTION(int, epoll_wait,
#elif defined(SYS_epoll_pwait)
int ret = LIBC_NAMESPACE::syscall_impl<int>(
SYS_epoll_pwait, epfd, reinterpret_cast<long>(events), maxevents, timeout,
reinterpret_cast<long>(nullptr), sizeof(sigset_t));
reinterpret_cast<long>(nullptr), NSIG / 8);
#else
#error "epoll_wait and epoll_pwait are unavailable. Unable to build epoll_wait."
#endif
Expand All @@ -38,7 +39,7 @@ LLVM_LIBC_FUNCTION(int, epoll_wait,
return -1;
}

return 0;
return ret;
}

} // namespace LIBC_NAMESPACE
7 changes: 7 additions & 0 deletions libc/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.lseek
)

add_entrypoint_object(
pipe
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.pipe
)

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(
pipe
SRCS
pipe.cpp
HDRS
../pipe.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/pipe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Linux implementation of pipe --------------------------------------===//
//
// 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/pipe.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, pipe, (int pipefd[2])) {
#ifdef SYS_pipe
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_pipe,
reinterpret_cast<long>(pipefd));
#elif defined(SYS_pipe2)
nickdesaulniers marked this conversation as resolved.
Show resolved Hide resolved
int ret = LIBC_NAMESPACE::syscall_impl<int>(
SYS_pipe2, reinterpret_cast<long>(pipefd), 0);
#endif
if (ret < 0) {
libc_errno = -ret;
return -1;
}
return ret;
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/unistd/pipe.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for pipe --------------------------*- 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_PIPE_H
#define LLVM_LIBC_SRC_UNISTD_PIPE_H

namespace LIBC_NAMESPACE {

int pipe(int pipefd[2]);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_UNISTD_PIPE_H
68 changes: 65 additions & 3 deletions libc/test/src/sys/epoll/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,65 @@
add_custom_target(libc_sys_epoll_unittests)

add_libc_unittest(
epoll_create_test
SUITE
libc_sys_epoll_unittests
SRCS
epoll_create_test.cpp
DEPENDS
libc.include.sys_epoll
libc.src.errno.errno
libc.src.sys.epoll.epoll_create
libc.src.unistd.close
libc.test.UnitTest.ErrnoSetterMatcher
)

add_libc_unittest(
epoll_create1_test
SUITE
libc_sys_epoll_unittests
SRCS
epoll_create1_test.cpp
DEPENDS
libc.hdr.sys_epoll_macros
libc.src.errno.errno
libc.src.sys.epoll.epoll_create1
libc.src.unistd.close
libc.test.UnitTest.ErrnoSetterMatcher
)

add_libc_unittest(
epoll_ctl_test
SUITE
libc_sys_epoll_unittests
SRCS
epoll_ctl_test.cpp
DEPENDS
libc.hdr.sys_epoll_macros
libc.hdr.types.struct_epoll_event
libc.src.errno.errno
libc.src.sys.epoll.epoll_create1
libc.src.sys.epoll.epoll_ctl
libc.src.unistd.pipe
libc.src.unistd.close
libc.test.UnitTest.ErrnoSetterMatcher
)

add_libc_unittest(
epoll_wait_test
SUITE
libc_sys_epoll_unittests
SRCS
epoll_wait_test.cpp
DEPENDS
libc.include.sys_epoll
libc.hdr.sys_epoll_macros
libc.hdr.types.struct_epoll_event
libc.src.errno.errno
libc.src.sys.epoll.epoll_create1
libc.src.sys.epoll.epoll_ctl
libc.src.sys.epoll.epoll_wait
libc.src.unistd.pipe
libc.src.unistd.close
libc.test.UnitTest.ErrnoSetterMatcher
)

Expand All @@ -19,9 +70,14 @@ add_libc_unittest(
SRCS
epoll_pwait_test.cpp
DEPENDS
libc.include.sys_epoll
libc.hdr.sys_epoll_macros
libc.hdr.types.struct_epoll_event
libc.src.errno.errno
libc.src.sys.epoll.epoll_create1
libc.src.sys.epoll.epoll_ctl
libc.src.sys.epoll.epoll_pwait
libc.src.unistd.pipe
libc.src.unistd.close
libc.test.UnitTest.ErrnoSetterMatcher
)

Expand All @@ -32,8 +88,14 @@ add_libc_unittest(
SRCS
epoll_pwait2_test.cpp
DEPENDS
libc.include.sys_epoll
libc.hdr.sys_epoll_macros
libc.hdr.types.struct_epoll_event
libc.hdr.types.struct_timespec
libc.src.errno.errno
libc.src.sys.epoll.epoll_create1
libc.src.sys.epoll.epoll_ctl
libc.src.sys.epoll.epoll_pwait2
libc.src.unistd.pipe
libc.src.unistd.close
libc.test.UnitTest.ErrnoSetterMatcher
)
31 changes: 31 additions & 0 deletions libc/test/src/sys/epoll/linux/epoll_create1_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- Unittests for epoll_create1 ---------------------------------------===//
//
// 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 "hdr/sys_epoll_macros.h"
#include "src/errno/libc_errno.h"
#include "src/sys/epoll/epoll_create1.h"
#include "src/unistd/close.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcEpollCreate1Test, Basic) {
int fd = LIBC_NAMESPACE::epoll_create1(0);
ASSERT_GT(fd, 0);
nickdesaulniers marked this conversation as resolved.
Show resolved Hide resolved
ASSERT_ERRNO_SUCCESS();

ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
}

TEST(LlvmLibcEpollCreate1Test, CloseOnExecute) {
int fd = LIBC_NAMESPACE::epoll_create1(EPOLL_CLOEXEC);
ASSERT_GT(fd, 0);
ASSERT_ERRNO_SUCCESS();

ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
}
26 changes: 26 additions & 0 deletions libc/test/src/sys/epoll/linux/epoll_create_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Unittests for epoll_create ----------------------------------------===//
//
// 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/sys/epoll/epoll_create.h"
#include "src/unistd/close.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcEpollCreateTest, Basic) {
int fd = LIBC_NAMESPACE::epoll_create(1);
michaelrj-google marked this conversation as resolved.
Show resolved Hide resolved
ASSERT_GT(fd, 0);
ASSERT_ERRNO_SUCCESS();

ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
}

TEST(LlvmLibcEpollCreateTest, Fails) {
ASSERT_THAT(LIBC_NAMESPACE::epoll_create(0), Fails(EINVAL));
}
47 changes: 47 additions & 0 deletions libc/test/src/sys/epoll/linux/epoll_ctl_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===-- Unittests for epoll_ctl -------------------------------------------===//
//
// 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 "hdr/sys_epoll_macros.h"
#include "hdr/types/struct_epoll_event.h"
#include "src/errno/libc_errno.h"
#include "src/sys/epoll/epoll_create1.h"
#include "src/sys/epoll/epoll_ctl.h"
#include "src/unistd/close.h"
#include "src/unistd/pipe.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcEpollCtlTest, Basic) {
int epfd = LIBC_NAMESPACE::epoll_create1(0);
ASSERT_GT(epfd, 0);
ASSERT_ERRNO_SUCCESS();

int pipefd[2];

ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds());

epoll_event event;
event.events = EPOLLOUT;
event.data.fd = pipefd[0];

ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event),
Succeeds());

// adding the same file fail.
ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event),
Fails(EEXIST));

ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event),
Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds());
}
47 changes: 42 additions & 5 deletions libc/test/src/sys/epoll/linux/epoll_pwait2_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,53 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "hdr/sys_epoll_macros.h"
#include "hdr/types/struct_epoll_event.h"
#include "hdr/types/struct_timespec.h"
#include "src/errno/libc_errno.h"
#include "src/sys/epoll/epoll_create1.h"
#include "src/sys/epoll/epoll_ctl.h"
#include "src/sys/epoll/epoll_pwait2.h"
#include "src/unistd/close.h"
#include "src/unistd/pipe.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcEpollWaitTest, Basic) {
EXPECT_THAT(LIBC_NAMESPACE::epoll_pwait2(-1, nullptr, 0, nullptr, nullptr),
returns(EQ(-1ul)).with_errno(EQ(EINVAL)));
}
TEST(LlvmLibcEpollPwaitTest, Basic) {
int epfd = LIBC_NAMESPACE::epoll_create1(0);
ASSERT_GT(epfd, 0);
ASSERT_ERRNO_SUCCESS();

int pipefd[2];

ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds());

epoll_event event;
event.events = EPOLLOUT;
event.data.fd = pipefd[0];

timespec time_spec;
time_spec.tv_sec = 0;
time_spec.tv_nsec = 0;

// TODO: Complete these tests when epoll_create is implemented.
ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event),
Succeeds());

// Timeout of 0 causes immediate return. We just need to check that the
// interface works, we're not testing the kernel behavior here.
ASSERT_THAT(
LIBC_NAMESPACE::epoll_pwait2(epfd, &event, 1, &time_spec, nullptr),
Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::epoll_pwait2(-1, &event, 1, &time_spec, nullptr),
Fails(EBADF));

ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event),
Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds());
}
42 changes: 37 additions & 5 deletions libc/test/src/sys/epoll/linux/epoll_pwait_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,48 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "hdr/sys_epoll_macros.h"
#include "hdr/types/struct_epoll_event.h"
#include "src/errno/libc_errno.h"
#include "src/sys/epoll/epoll_create1.h"
#include "src/sys/epoll/epoll_ctl.h"
#include "src/sys/epoll/epoll_pwait.h"
#include "src/unistd/close.h"
#include "src/unistd/pipe.h"

#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcEpollWaitTest, Basic) {
EXPECT_THAT(LIBC_NAMESPACE::epoll_pwait(-1, nullptr, 0, 0, nullptr),
returns(EQ(-1ul)).with_errno(EQ(EINVAL)));
}
TEST(LlvmLibcEpollPwaitTest, Basic) {
int epfd = LIBC_NAMESPACE::epoll_create1(0);
ASSERT_GT(epfd, 0);
ASSERT_ERRNO_SUCCESS();

int pipefd[2];

ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds());

epoll_event event;
event.events = EPOLLOUT;
event.data.fd = pipefd[0];

// TODO: Complete these tests when epoll_create is implemented.
ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event),
Succeeds());

// Timeout of 0 causes immediate return. We just need to check that the
// interface works, we're not testing the kernel behavior here.
ASSERT_THAT(LIBC_NAMESPACE::epoll_pwait(epfd, &event, 1, 0, nullptr),
Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::epoll_pwait(-1, &event, 1, 0, nullptr),
Fails(EBADF));

ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event),
Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds());
}
37 changes: 33 additions & 4 deletions libc/test/src/sys/epoll/linux/epoll_wait_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,45 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "hdr/sys_epoll_macros.h"
#include "hdr/types/struct_epoll_event.h"
#include "src/errno/libc_errno.h"
#include "src/sys/epoll/epoll_create1.h"
#include "src/sys/epoll/epoll_ctl.h"
#include "src/sys/epoll/epoll_wait.h"
#include "src/unistd/close.h"
#include "src/unistd/pipe.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcEpollWaitTest, Basic) {
EXPECT_THAT(LIBC_NAMESPACE::epoll_wait(-1, nullptr, 0, 0),
returns(EQ(-1ul)).with_errno(EQ(EINVAL)));
}
int epfd = LIBC_NAMESPACE::epoll_create1(0);
ASSERT_GT(epfd, 0);
ASSERT_ERRNO_SUCCESS();

int pipefd[2];

ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds());

epoll_event event;
event.events = EPOLLOUT;
event.data.fd = pipefd[0];

ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_ADD, pipefd[0], &event),
Succeeds());

// TODO: Complete these tests when epoll_create is implemented.
// Timeout of 0 causes immediate return. We just need to check that the
// interface works, we're not testing the kernel behavior here.
ASSERT_THAT(LIBC_NAMESPACE::epoll_wait(epfd, &event, 1, 0), Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::epoll_wait(-1, &event, 1, 0), Fails(EBADF));

ASSERT_THAT(LIBC_NAMESPACE::epoll_ctl(epfd, EPOLL_CTL_DEL, pipefd[0], &event),
Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(epfd), Succeeds());
}
15 changes: 15 additions & 0 deletions libc/test/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,21 @@ add_libc_unittest(
libc.test.UnitTest.ErrnoSetterMatcher
)

add_libc_unittest(
pipe_test
SUITE
libc_unistd_unittests
SRCS
pipe_test.cpp
DEPENDS
libc.include.errno
libc.include.unistd
libc.src.errno.errno
libc.src.unistd.close
libc.src.unistd.pipe
libc.test.UnitTest.ErrnoSetterMatcher
)

add_libc_unittest(
rmdir_test
SUITE
Expand Down
26 changes: 26 additions & 0 deletions libc/test/src/unistd/pipe_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Unittests for pipe ------------------------------------------------===//
//
// 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/close.h"
#include "src/unistd/pipe.h"

#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcPipeTest, SmokeTest) {

int pipefd[2];

ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds());

ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds());
ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds());
}

// TODO: Functionality tests
103 changes: 96 additions & 7 deletions utils/bazel/llvm-project-overlay/libc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ libc_support_library(
hdrs = ["include/llvm-libc-macros/linux/fcntl-macros.h"],
)

############################ Proxy Header Files ################################
########################### Macro Proxy Header Files ###########################

libc_support_library(
name = "hdr_math_macros",
Expand All @@ -118,6 +118,33 @@ libc_support_library(
hdrs = ["hdr/fenv_macros.h"],
)

libc_support_library(
name = "hdr_signal_macros",
hdrs = ["hdr/signal_macros.h"],
)

libc_support_library(
name = "hdr_sys_epoll_macros",
hdrs = ["hdr/sys_epoll_macros.h"],
)

############################ Type Proxy Header Files ###########################

libc_support_library(
name = "types_sigset_t",
hdrs = ["hdr/types/sigset_t.h"],
)

libc_support_library(
name = "types_struct_epoll_event",
hdrs = ["hdr/types/struct_epoll_event.h"],
)

libc_support_library(
name = "types_struct_timespec",
hdrs = ["hdr/types/struct_timespec.h"],
)

############################### Support libraries ##############################

libc_support_library(
Expand Down Expand Up @@ -2941,6 +2968,17 @@ libc_function(
],
)

libc_function(
name = "pipe",
srcs = ["src/unistd/linux/pipe.cpp"],
hdrs = ["src/unistd/pipe.h"],
deps = [
":__support_common",
":__support_osutil_syscall",
":errno",
],
)

libc_function(
name = "lseek",
srcs = ["src/unistd/linux/lseek.cpp"],
Expand Down Expand Up @@ -3417,13 +3455,51 @@ libc_function(

############################## sys/epoll targets ###############################

libc_support_library(
name = "types_sigset_t",
hdrs = ["hdr/types/sigset_t.h"],
libc_function(
name = "epoll_create",
srcs = ["src/sys/epoll/linux/epoll_create.cpp"],
hdrs = ["src/sys/epoll/epoll_create.h"],
target_compatible_with = select({
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
weak = True,
deps = [
":__support_osutil_syscall",
":errno",
],
)
libc_support_library(
name = "types_struct_epoll_event",
hdrs = ["hdr/types/struct_epoll_event.h"],

libc_function(
name = "epoll_create1",
srcs = ["src/sys/epoll/linux/epoll_create1.cpp"],
hdrs = ["src/sys/epoll/epoll_create1.h"],
target_compatible_with = select({
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
weak = True,
deps = [
":__support_osutil_syscall",
":errno",
],
)

libc_function(
name = "epoll_ctl",
srcs = ["src/sys/epoll/linux/epoll_ctl.cpp"],
hdrs = ["src/sys/epoll/epoll_ctl.h"],
target_compatible_with = select({
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
weak = True,
deps = [
":__support_osutil_syscall",
":errno",
":hdr_sys_epoll_macros",
":types_struct_epoll_event",
],
)

libc_function(
Expand All @@ -3438,6 +3514,8 @@ libc_function(
deps = [
":__support_osutil_syscall",
":errno",
":hdr_signal_macros",
":hdr_sys_epoll_macros",
":types_sigset_t",
":types_struct_epoll_event",
],
Expand All @@ -3455,6 +3533,8 @@ libc_function(
deps = [
":__support_osutil_syscall",
":errno",
":hdr_signal_macros",
":hdr_sys_epoll_macros",
":types_sigset_t",
":types_struct_epoll_event",
],
Expand All @@ -3466,9 +3546,18 @@ libc_function(
# name = "epoll_pwait2",
# srcs = ["src/sys/epoll/linux/epoll_pwait2.cpp"],
# hdrs = ["src/sys/epoll/epoll_pwait2.h"],
# target_compatible_with = select({
# "@platforms//os:linux": [],
# "//conditions:default": ["@platforms//:incompatible"],
# }),
# weak = True,
# deps = [
# ":__support_osutil_syscall",
# ":errno",
# ":hdr_signal_macros",
# ":hdr_sys_epoll_macros",
# ":types_sigset_t",
# ":types_struct_epoll_event",
# ":types_struct_timespec",
# ],
# )
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,55 @@ package(default_visibility = ["//visibility:public"])

licenses(["notice"])

libc_test(
name = "epoll_create_test",
srcs = ["linux/epoll_create_test.cpp"],
libc_function_deps = [
"//libc:epoll_create",
"//libc:close",
],
)

libc_test(
name = "epoll_create1_test",
srcs = ["linux/epoll_create1_test.cpp"],
libc_function_deps = [
"//libc:epoll_create1",
"//libc:close",
],
deps = [
"//libc:hdr_sys_epoll_macros",
],
)

libc_test(
name = "epoll_ctl_test",
srcs = ["linux/epoll_ctl_test.cpp"],
libc_function_deps = [
"//libc:epoll_create1",
"//libc:epoll_ctl",
"//libc:pipe",
"//libc:close",
],
deps = [
"//libc:hdr_sys_epoll_macros",
"//libc:types_struct_epoll_event",
],
)

libc_test(
name = "epoll_wait_test",
srcs = ["linux/epoll_wait_test.cpp"],
libc_function_deps = [
"//libc:epoll_wait",
"//libc:epoll_create1",
"//libc:epoll_ctl",
"//libc:pipe",
"//libc:close",
],
deps = [
"//libc:hdr_sys_epoll_macros",
"//libc:types_struct_epoll_event",
],
)

Expand All @@ -23,6 +67,14 @@ libc_test(
srcs = ["linux/epoll_pwait_test.cpp"],
libc_function_deps = [
"//libc:epoll_pwait",
"//libc:epoll_create1",
"//libc:epoll_ctl",
"//libc:pipe",
"//libc:close",
],
deps = [
"//libc:hdr_sys_epoll_macros",
"//libc:types_struct_epoll_event",
],
)

Expand All @@ -33,5 +85,14 @@ libc_test(
# srcs = ["linux/epoll_pwait2_test.cpp"],
# libc_function_deps = [
# "//libc:epoll_pwait2",
# "//libc:epoll_create1",
# "//libc:epoll_ctl",
# "//libc:pipe",
# "//libc:close",
# ],
# deps = [
# "//libc:hdr_sys_epoll_macros",
# "//libc:types_struct_epoll_event",
# "//libc:types_struct_timespec",
# ],
# )