diff --git a/CMakeLists.txt b/CMakeLists.txt index c66fe9e62b..20bdc92e06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -518,6 +518,7 @@ else() select epoll_create epoll_create1 + epoll_pwait2 epoll_ctl eventfd poll diff --git a/configure.ac b/configure.ac index b0a37fe85e..cc961692b6 100644 --- a/configure.ac +++ b/configure.ac @@ -272,7 +272,7 @@ dnl Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE dnl Checks for library functions. -AC_CHECK_FUNCS([accept4 arc4random arc4random_buf arc4random_addrandom eventfd epoll_create1 fcntl getegid geteuid getifaddrs gettimeofday issetugid mach_absolute_time mmap nanosleep pipe pipe2 putenv sendfile setenv setrlimit sigaction signal strsignal strlcpy strsep strtok_r strtoll sysctl timerfd_create umask unsetenv usleep getrandom mmap64]) +AC_CHECK_FUNCS([accept4 arc4random arc4random_buf arc4random_addrandom eventfd epoll_create1 epoll_pwait2 fcntl getegid geteuid getifaddrs gettimeofday issetugid mach_absolute_time mmap nanosleep pipe pipe2 putenv sendfile setenv setrlimit sigaction signal strsignal strlcpy strsep strtok_r strtoll sysctl timerfd_create umask unsetenv usleep getrandom mmap64]) AS_IF([test "$bwin32" = "true"], AC_CHECK_FUNCS(_gmtime64_s, , [AC_CHECK_FUNCS(_gmtime64)]) diff --git a/epoll.c b/epoll.c index 24a63bb4da..9b4890772d 100644 --- a/epoll.c +++ b/epoll.c @@ -81,11 +81,13 @@ #if defined(EVENT__HAVE_SYS_TIMERFD_H) && \ defined(EVENT__HAVE_TIMERFD_CREATE) && \ defined(HAVE_POSIX_MONOTONIC) && defined(TFD_NONBLOCK) && \ - defined(TFD_CLOEXEC) + defined(TFD_CLOEXEC) && !defined(EVENT__HAVE_EPOLL_PWAIT2) /* Note that we only use timerfd if TFD_NONBLOCK and TFD_CLOEXEC are available and working. This means that we can't support it on 2.6.25 (where timerfd - was introduced) or 2.6.26, since 2.6.27 introduced those flags. - */ + was introduced) or 2.6.26, since 2.6.27 introduced those flags. On recent + enough systems (with 5.11 and never) and so epoll_pwait2() with nanosecond + precision for timeouts, timerfd is not needed at all. +*/ #define USING_TIMERFD #endif @@ -459,7 +461,11 @@ epoll_dispatch(struct event_base *base, struct timeval *tv) struct epollop *epollop = base->evbase; struct epoll_event *events = epollop->events; int i, res; +#if defined(EVENT__HAVE_EPOLL_PWAIT2) + struct timespec ts = { 0, 0 }; +#else /* no epoll_pwait2() */ long timeout = -1; +#endif /* EVENT__HAVE_EPOLL_PWAIT2 */ #ifdef USING_TIMERFD if (epollop->timerfd >= 0) { @@ -489,12 +495,16 @@ epoll_dispatch(struct event_base *base, struct timeval *tv) } else #endif if (tv != NULL) { +#if defined(EVENT__HAVE_EPOLL_PWAIT2) + TIMEVAL_TO_TIMESPEC(tv, &ts); +#else /* no epoll_pwait2() */ timeout = evutil_tv_to_msec_(tv); if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) { /* Linux kernels can wait forever if the timeout is * too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */ timeout = MAX_EPOLL_TIMEOUT_MSEC; } +#endif /* EVENT__HAVE_EPOLL_PWAIT2 */ } epoll_apply_changes(base); @@ -502,7 +512,11 @@ epoll_dispatch(struct event_base *base, struct timeval *tv) EVBASE_RELEASE_LOCK(base, th_base_lock); +#if defined(EVENT__HAVE_EPOLL_PWAIT2) + res = epoll_pwait2(epollop->epfd, events, epollop->nevents, tv ? &ts : NULL, NULL); +#else /* no epoll_pwait2() */ res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); +#endif /* EVENT__HAVE_EPOLL_PWAIT2 */ EVBASE_ACQUIRE_LOCK(base, th_base_lock); diff --git a/event-config.h.cmake b/event-config.h.cmake index a52e7136ea..a3cfafa164 100644 --- a/event-config.h.cmake +++ b/event-config.h.cmake @@ -99,6 +99,9 @@ /* Define to 1 if you have the `epoll_create1' function. */ #cmakedefine EVENT__HAVE_EPOLL_CREATE1 1 +/* Define to 1 if you have the `epoll_pwait2' function. */ +#cmakedefine EVENT__HAVE_EPOLL_PWAIT2 1 + /* Define to 1 if you have the `epoll_ctl' function. */ #cmakedefine EVENT__HAVE_EPOLL_CTL 1