Skip to content

Commit

Permalink
add support for FreeBSD's native eventfd descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
jiixyj committed Dec 28, 2020
1 parent 2404ae9 commit 95a356b
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 27 deletions.
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ if(NOT HAVE_ERRNO_T)
add_definitions(-Derrno_t=int)
endif()

# FreeBSD 13 supports native eventfd descriptors. Prefer them if available.
include(CheckSymbolExists)
check_symbol_exists(eventfd "sys/eventfd.h" HAVE_EVENTFD)

add_subdirectory(src)

if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
Expand Down Expand Up @@ -62,8 +66,12 @@ if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
TARGETS epoll-shim
EXPORT ${PROJECT_NAME}-targets
LIBRARY
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" TYPE INCLUDE)
INCLUDES
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sys" TYPE INCLUDE)
if(NOT HAVE_EVENTFD)
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/eventfd/" TYPE INCLUDE)
endif()

install(
EXPORT ${PROJECT_NAME}-targets
Expand Down
File renamed without changes.
29 changes: 17 additions & 12 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

add_library(epoll-shim
epoll_shim_ctx.c
epoll.c
epollfd_ctx.c
timerfd.c
timerfd_ctx.c
signalfd.c
signalfd_ctx.c
eventfd.c
eventfd_ctx.c)
add_library(
epoll-shim
epoll_shim_ctx.c
epoll.c
epollfd_ctx.c
timerfd.c
timerfd_ctx.c
signalfd.c
signalfd_ctx.c)
if(NOT HAVE_EVENTFD)
target_sources(epoll-shim PRIVATE eventfd.c eventfd_ctx.c)
endif()
target_link_libraries(epoll-shim PRIVATE Threads::Threads)
target_include_directories(
epoll-shim
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
epoll-shim PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
if(NOT HAVE_EVENTFD)
target_include_directories(
epoll-shim PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/eventfd>)
endif()

target_link_options(epoll-shim PRIVATE
"LINKER:--version-script=${PROJECT_SOURCE_DIR}/Version.map")
Expand Down
15 changes: 12 additions & 3 deletions test/epoll-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@ poll_only_fd_thread_fun(void *arg)
ATF_TC_WITHOUT_HEAD(epoll__poll_only_fd);
ATF_TC_BODY_FD_LEAKCHECK(epoll__poll_only_fd, tc)
{
#ifdef __linux__
atf_tc_skip("Test hangs on Linux");
#endif

int ep = epoll_create1(EPOLL_CLOEXEC);
ATF_REQUIRE(ep >= 0);

Expand Down Expand Up @@ -1633,14 +1637,18 @@ ATF_TC_BODY_FD_LEAKCHECK(epoll__invalid_writes, tcptr)
{
fd = signalfd(-1, &mask, 0);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE_ERRNO(EINVAL, write(fd, &dummy, 1) < 0);
ATF_REQUIRE(write(fd, &dummy, 1) < 0);
/* FreeBSD's native write returns EOPNOTSUPP. write is not
* shimmed when using native eventfds. */
ATF_REQUIRE(errno == EINVAL || errno == EOPNOTSUPP);
ATF_REQUIRE(close(fd) == 0);
}

{
fd = timerfd_create(CLOCK_MONOTONIC, 0);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE_ERRNO(EINVAL, write(fd, &dummy, 1) < 0);
ATF_REQUIRE(write(fd, &dummy, 1) < 0);
ATF_REQUIRE(errno == EINVAL || errno == EOPNOTSUPP);
ATF_REQUIRE_ERRNO(EINVAL,
write(fd, &dummy, (size_t)SSIZE_MAX + 1) < 0);
ATF_REQUIRE(close(fd) == 0);
Expand All @@ -1649,7 +1657,8 @@ ATF_TC_BODY_FD_LEAKCHECK(epoll__invalid_writes, tcptr)
{
fd = epoll_create1(EPOLL_CLOEXEC);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE_ERRNO(EINVAL, write(fd, &dummy, 1) < 0);
ATF_REQUIRE(write(fd, &dummy, 1) < 0);
ATF_REQUIRE(errno == EINVAL || errno == EOPNOTSUPP);
ATF_REQUIRE_ERRNO(EINVAL, read(fd, &dummy, 1) < 0);
ATF_REQUIRE_ERRNO(EINVAL,
read(fd, &dummy, (size_t)SSIZE_MAX + 1) < 0);
Expand Down
4 changes: 2 additions & 2 deletions test/eventfd-ctx-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ ATF_TC_BODY_FD_LEAKCHECK(eventfd__fork, tc)
ATF_REQUIRE((efd = eventfd(0,
EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE)) >= 0);

if (close(5) == 0) {
if (close(efd + 2) == 0) {
atf_tc_skip("shimmed eventfd's implemented by self-pipe "
"cannot be shared between processes");
}
Expand All @@ -384,7 +384,7 @@ ATF_TC_BODY_FD_LEAKCHECK(eventfd__fork, tc)
ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
ATF_REQUIRE(WIFEXITED(status));
if (WEXITSTATUS(status) == EBADF) {
atf_tc_skip("shimmed eventfd's cannot be shared "
atf_tc_skip("only native eventfds can be shared "
"between processes");
}
ATF_REQUIRE(WEXITSTATUS(status) == 0);
Expand Down
6 changes: 5 additions & 1 deletion test/pipe-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,9 +938,13 @@ ATF_TC_BODY_FD_LEAKCHECK(pipe__fifo_connecting_reader, tc)
&(struct timespec){0, 0}) == 0);
}
ATF_REQUIRE(close(kq) == 0);
#endif
#if defined(__linux__)
/* Linux 5.10 doesn't notify on new readers. */
will_notice_new_readers = false;
#endif
if (!will_notice_new_readers) {
atf_tc_skip("FreeBSD FIFOs don't notify on new readers");
atf_tc_skip("FreeBSD/Linux FIFOs don't notify on new readers");
} else {
ATF_REQUIRE(epoll_wait(ep, eps, 32, 0) == 1);
ATF_REQUIRE(eps[0].events == EPOLLOUT);
Expand Down
12 changes: 9 additions & 3 deletions test/signalfd-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,17 @@ ATF_TC_BODY_FD_LEAKCHECK(signalfd__argument_checks, tcptr)
ATF_REQUIRE(pipe2(fds, O_CLOEXEC) == 0);

ATF_REQUIRE_ERRNO(EBADF, signalfd(invalid_fd, &mask, 0));
ATF_REQUIRE_ERRNO(EINVAL, signalfd(invalid_fd, NULL, 0));
ATF_REQUIRE_ERRNO(EINVAL, signalfd(-1, NULL, 0));
ATF_REQUIRE(signalfd(invalid_fd, NULL, 0));
/* Linux 5.10 returns EFAULT. */
ATF_REQUIRE(errno == EINVAL || errno == EFAULT);
ATF_REQUIRE(signalfd(-1, NULL, 0));
/* Linux 5.10 returns EFAULT. */
ATF_REQUIRE(errno == EINVAL || errno == EFAULT);

ATF_REQUIRE_ERRNO(EINVAL, signalfd(fds[0], &mask, 0));
ATF_REQUIRE_ERRNO(EINVAL, signalfd(fds[0], NULL, 0));
ATF_REQUIRE(signalfd(fds[0], NULL, 0));
/* Linux 5.10 returns EFAULT. */
ATF_REQUIRE(errno == EINVAL || errno == EFAULT);

ATF_REQUIRE_ERRNO(EINVAL, signalfd(invalid_fd, &mask, 42));

Expand Down
5 changes: 3 additions & 2 deletions test/timerfd-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,9 @@ ATF_TC_BODY_FD_LEAKCHECK(timerfd__argument_checks, tc)
struct itimerspec itimerspec;
ATF_REQUIRE_ERRNO(EBADF, timerfd_gettime(timerfd, &itimerspec) < 0);

ATF_REQUIRE_ERRNO(EBADF,
timerfd_settime(timerfd, 0, &itimerspec, NULL) < 0);
ATF_REQUIRE(timerfd_settime(timerfd, 0, &itimerspec, NULL) < 0);
/* Linux 5.10 returns EINVAL instead of EBADF. */
ATF_REQUIRE(errno == EBADF || errno == EINVAL);
}

ATF_TC_WITHOUT_HEAD(timerfd__upgrade_simple_to_complex);
Expand Down
4 changes: 2 additions & 2 deletions test/tst-epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ ATF_TC_BODY_FD_LEAKCHECK(epollfd_osv__some_tests, tc)
r = (int)write(s[1], &c, 1);
ATF_REQUIRE_MSG(r == 1, "write single character");
r = epoll_wait(ep, events, MAXEVENTS, 0);
ATF_REQUIRE_MSG(r == 1 && (events[0].events & EPOLLIN) &&
(events[0].data.u32 == 456),
ATF_REQUIRE_MSG(r == 0 || (r == 1 && (events[0].events & EPOLLIN) &&
(events[0].data.u32 == 456)),
"epoll_wait false positive (fine)");
r = (int)read(s[0], &c, 1);
ATF_REQUIRE_MSG(r == 1, "read one byte out of 2 on the pipe");
Expand Down

0 comments on commit 95a356b

Please sign in to comment.