lib: Substitute poll APIs with epoll APIs in thread management routine

This commit substitutes poll APIs with epoll APIs for better performace. Note that epoll APIs are only available for Linux platforms. For BSD platforms which do not support epoll APIs, poll APIs are still used.

Signed-off-by: Kaifei Peng <2534164734@qq.com>
This commit is contained in:
ponedo 2024-03-16 04:40:05 +00:00 committed by Donald Sharp
parent 196b7f1c31
commit bb5743652d
4 changed files with 857 additions and 138 deletions

View file

@ -1599,6 +1599,26 @@ AC_CHECK_FUNCS([pollts], [
AC_DEFINE([HAVE_POLLTS], [1], [have NetBSD pollts()])
])
AC_ARG_ENABLE([epoll],
[AS_HELP_STRING([--enable-epoll], [Enable epoll support])],
[enable_epoll=yes],
[enable_epoll=no])
if test "x$enable_epoll" = "xyes"; then
AC_CHECK_FUNC([epoll_wait], [AC_DEFINE([HAVE_EPOLL_WAIT], [1], [Define if you have epoll_wait])])
AC_CHECK_FUNC([epoll_pwait], [AC_DEFINE([HAVE_EPOLL_PWAIT], [1], [Define if you have epoll_pwait])])
AC_CHECK_FUNC([epoll_pwait2], [AC_DEFINE([HAVE_EPOLL_PWAIT2], [1], [Define if you have epoll_pwait2])])
# Define USE_EPOLL if any of the above is found
AC_MSG_CHECKING([for any epoll API support])
if test "x$ac_cv_func_epoll_wait" = "xyes" || test "x$ac_cv_func_epoll_pwait" = "xyes" || test "x$ac_cv_func_epoll_pwait2" = "xyes"; then
AC_DEFINE([USE_EPOLL], [1], [Define if any epoll API is supported])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
AC_CHECK_HEADER([asm-generic/unistd.h],
[AC_CHECK_DECL(__NR_setns,
AC_DEFINE([HAVE_NETNS], [1], [Have netns]),,

File diff suppressed because it is too large Load diff

View file

@ -6,10 +6,21 @@
#ifndef _ZEBRA_THREAD_H
#define _ZEBRA_THREAD_H
#if defined(USE_EPOLL) && \
(defined(HAVE_EPOLL_WAIT) || defined(HAVE_EPOLL_PWAIT) || \
defined(HAVE_EPOLL_PWAIT2))
#define EPOLL_ENABLED 1
#else
#define EPOLL_ENABLED 0
#endif
#include <signal.h>
#include <zebra.h>
#include <pthread.h>
#include <poll.h>
#if EPOLL_ENABLED
#include <sys/epoll.h>
#endif
#include "monotime.h"
#include "frratomic.h"
#include "typesafe.h"
@ -43,6 +54,34 @@ struct rusage_t {
PREDECL_LIST(event_list);
PREDECL_HEAP(event_timer_list);
#if EPOLL_ENABLED
struct fd_handler {
/* The epoll set file descriptor */
int epoll_fd;
/* A hash table in which monitored I/O file descrpitors and events
* are registered
*/
struct hash *epoll_event_hash;
/* Maximum size of .revents and .regular_revents arrays */
int eventsize;
/* The buffer which stores the results of epoll_wait */
struct epoll_event *revents;
/* Vtysh might redirect stdin/stdout to regular files. However,
* regular files can't be added into epoll set and need special
* treatment. I/O events from/to regular file will be directly
* added to regular_revents, but not into epoll set, whereby
* sidesteping epoll_wait.
*/
struct epoll_event *regular_revents;
int regular_revent_count;
unsigned long *fd_poll_counter;
};
#else
struct fd_handler {
/* number of pfd that fit in the allocated space of pfds. This is a
* constant and is the same for both pfds and copy.
@ -59,6 +98,7 @@ struct fd_handler {
/* number of pollfds stored in copy */
nfds_t copycount;
};
#endif
struct xref_eventsched {
struct xref xref;
@ -91,7 +131,9 @@ struct event_loop {
pthread_mutex_t mtx;
pthread_t owner;
#if !EPOLL_ENABLED
nfds_t last_read;
#endif
bool ready_run_loop;
RUSAGE_T last_getrusage;

View file

@ -59,6 +59,18 @@ struct printfrr_eargs;
} while (0)
#endif
#ifndef msec_to_timespec
#define msec_to_timespec(ms, ts, tsp) \
do { \
if ((ms) >= 0) { \
(ts).tv_sec = (ms) / 1000; \
(ts).tv_nsec = ((ms) % 1000) * 1000000; \
(tsp) = &(ts); \
} else \
(tsp) = NULL; \
} while (0)
#endif
static inline time_t monotime(struct timeval *tvo)
{
struct timespec ts;