Commit 404cdb77 authored by Dag Erling Smørgrav's avatar Dag Erling Smørgrav

Add an epoll()-based acceptor for Linux 2.6. Simple empirical tests indicate

that epoll() performs significantly better than poll() (less CPU usage).

git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@780 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 1679fe52
......@@ -7,10 +7,13 @@
*/
#undef ACCEPTOR_USE_KQUEUE
#undef ACCEPTOR_USE_EPOLL
#undef ACCEPTOR_USE_POLL
#if defined(HAVE_KQUEUE)
#define ACCEPTOR_USE_KQUEUE 1
#elif defined(HAVE_EPOLL_CTL)
#define ACCEPTOR_USE_EPOLL 1
#elif defined(HAVE_POLL)
#define ACCEPTOR_USE_POLL 1
#else
......@@ -260,6 +263,125 @@ vca_return_session(struct sess *sp)
#endif /* ACCEPTOR_USE_POLL */
/*====================================================================*/
#ifdef ACCEPTOR_USE_EPOLL
#include <sys/epoll.h>
static int epfd = -1;
static int pipes[2];
static TAILQ_HEAD(,sess) sesshead = TAILQ_HEAD_INITIALIZER(sesshead);
static void
vca_add(int fd, void *data)
{
struct epoll_event ev = { EPOLLIN | EPOLLPRI, { data } };
AZ(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev));
}
static void
vca_del(int fd)
{
AZ(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL));
}
static void
vca_rcvhdev(struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
clock_gettime(CLOCK_MONOTONIC, &sp->t_idle);
TAILQ_INSERT_TAIL(&sesshead, sp, list);
vca_add(sp->fd, sp);
}
static void
accept_f(int fd)
{
struct sess *sp;
sp = vca_accept_sess(fd);
if (sp == NULL)
return;
http_RecvPrep(sp->http);
vca_rcvhdev(sp);
}
static void *
vca_main(void *arg)
{
struct epoll_event ev;
struct timespec t;
struct sess *sp, *sp2;
int i;
(void)arg;
epfd = epoll_create(16);
assert(epfd >= 0);
AZ(pipe(pipes));
vca_add(pipes[0], pipes);
if (heritage.socket >= 0)
vca_add(heritage.socket, accept_f);
while (1) {
if (epoll_wait(epfd, &ev, 1, 5000) > 0) {
if (ev.data.ptr == pipes) {
i = read(pipes[0], &sp, sizeof sp);
assert(i == sizeof sp);
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
if (http_RecvPrepAgain(sp->http))
vca_handover(sp, 0);
else
vca_rcvhdev(sp);
} else if (ev.data.ptr == accept_f) {
accept_f(heritage.socket);
} else {
CAST_OBJ_NOTNULL(sp, ev.data.ptr, SESS_MAGIC);
i = http_RecvSome(sp->fd, sp->http);
if (i != -1) {
TAILQ_REMOVE(&sesshead, sp, list);
vca_del(sp->fd);
vca_handover(sp, i);
}
}
}
/* check for timeouts */
clock_gettime(CLOCK_MONOTONIC, &t);
TAILQ_FOREACH_SAFE(sp, &sesshead, list, sp2) {
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
if (sp->t_idle.tv_sec + 5 < t.tv_sec) {
TAILQ_REMOVE(&sesshead, sp, list);
vca_del(sp->fd);
vca_close_session(sp, "timeout");
vca_return_session(sp);
continue;
}
}
}
INCOMPL();
}
/*--------------------------------------------------------------------*/
void
vca_return_session(struct sess *sp)
{
if (sp->fd < 0) {
SES_Delete(sp);
return;
}
(void)clock_gettime(CLOCK_REALTIME, &sp->t_open);
VSL(SLT_SessionReuse, sp->fd, "%s %s", sp->addr, sp->port);
assert(sizeof sp == write(pipes[1], &sp, sizeof sp));
}
#endif /* ACCEPTOR_USE_EPOLL */
/*====================================================================*/
#ifdef ACCEPTOR_USE_KQUEUE
#include <sys/event.h>
......
......@@ -90,6 +90,7 @@ AM_CONDITIONAL(NEED_LIBMD, test x$need_libmd = xyes)
# Check which mechanism to use for the acceptor
AC_CHECK_FUNCS([kqueue])
AC_CHECK_FUNCS([epoll_ctl])
AC_CHECK_FUNCS([poll])
AC_CONFIG_FILES([
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment