From: William Horvath william@horvath.blog
This brings the improved timeout resolution to Wine builds which didn't have epoll_pwait2 at compile time, if the run-time kernel supports it (i.e. build 5.10->run 6.14). --- configure.ac | 1 - server/fd.c | 31 ++++++++++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/configure.ac b/configure.ac index 9e32070f610..05157e80d55 100644 --- a/configure.ac +++ b/configure.ac @@ -2072,7 +2072,6 @@ AC_CHECK_FUNCS(\ dladdr1 \ dlinfo \ epoll_create \ - epoll_pwait2 \ fstatfs \ futimens \ futimes \ diff --git a/server/fd.c b/server/fd.c index bb0e90d99d0..640f9e2a79d 100644 --- a/server/fd.c +++ b/server/fd.c @@ -100,6 +100,7 @@ #include "ddk/wdm.h"
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE) +# include <dlfcn.h> # include <sys/epoll.h> # define USE_EPOLL #endif /* HAVE_SYS_EPOLL_H && HAVE_EPOLL_CREATE */ @@ -561,14 +562,25 @@ static inline void remove_epoll_user( struct fd *fd, int user ) } }
+static int (*pepoll_pwait2)( int, struct epoll_event *, int, const struct timespec *, const sigset_t * ); + +/* dispatch to the highest resolution epoll available */ +static inline int do_epoll_wait( struct epoll_event *events, int maxevents, const struct timespec *timeout_ts, int timeout_ms ) +{ + if (pepoll_pwait2) + { + int ret = pepoll_pwait2( epoll_fd, events, maxevents, timeout_ts, NULL ); + if (ret == -1 && errno == ENOSYS) pepoll_pwait2 = NULL; /* broken, fall back to epoll_wait */ + else return ret; + } + return epoll_wait( epoll_fd, events, maxevents, timeout_ms ); +} + static inline void main_loop_epoll(void) { int i, ret, timeout; struct timespec ts; struct epoll_event events[128]; -#ifdef HAVE_EPOLL_PWAIT2 - static int failed_epoll_pwait2 = 0; -#endif
assert( POLLIN == EPOLLIN ); assert( POLLOUT == EPOLLOUT ); @@ -577,6 +589,8 @@ static inline void main_loop_epoll(void)
if (epoll_fd == -1) return;
+ pepoll_pwait2 = dlsym( RTLD_DEFAULT, "epoll_pwait2" ); + while (active_users) { timeout = get_next_timeout( &ts ); @@ -584,16 +598,7 @@ static inline void main_loop_epoll(void) if (!active_users) break; /* last user removed by a timeout */ if (epoll_fd == -1) break; /* an error occurred with epoll */
-#ifdef HAVE_EPOLL_PWAIT2 - if (!failed_epoll_pwait2) - { - ret = epoll_pwait2( epoll_fd, events, ARRAY_SIZE( events ), timeout == -1 ? NULL : &ts, NULL ); - if (ret == -1 && errno == ENOSYS) - failed_epoll_pwait2 = 1; - } - if (failed_epoll_pwait2) -#endif - ret = epoll_wait( epoll_fd, events, ARRAY_SIZE( events ), timeout ); + ret = do_epoll_wait( events, ARRAY_SIZE( events ), timeout == -1 ? NULL : &ts, timeout );
set_current_time();