Skip to content

Commit

Permalink
epoll: use epoll_pwait2() if available
Browse files Browse the repository at this point in the history
On GNU/Linux with epoll backend, prefer epoll_pwait2() if available,
which is useful to support the timeout with microsecond precision.
  • Loading branch information
dmantipov authored and azat committed Sep 27, 2022
1 parent f8bb9d8 commit 117ee9a
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 4 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ else()
select
epoll_create
epoll_create1
epoll_pwait2
epoll_ctl
eventfd
poll
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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)])
Expand Down
20 changes: 17 additions & 3 deletions epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -489,20 +495,28 @@ 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);
event_changelist_remove_all_(&base->changelist, base);

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);

Expand Down
3 changes: 3 additions & 0 deletions event-config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 117ee9a

Please sign in to comment.