Use eventfd instead of pipes if available

eventfd has less overhead than a pipe, works as a counter and uses a
single fd. Use it on Linux if available (that should be pretty much
always given the glibc and kernel requirements).
This commit is contained in:
Julien BLACHE 2010-02-04 18:52:13 +01:00
parent 274dccf66c
commit cb4320791b
4 changed files with 151 additions and 13 deletions

View File

@ -34,6 +34,8 @@ AC_CHECK_HEADERS([sys/wait.h])
AC_CHECK_HEADERS([sys/param.h])
AC_CHECK_HEADERS([sys/select.h])
AC_CHECK_HEADERS([dirent.h])
AC_CHECK_HEADERS([sys/eventfd.h])
AC_CHECK_FUNCS(eventfd)
AC_CHECK_FUNCS(posix_fadvise)
AC_CHECK_FUNCS(strptime)
AC_CHECK_FUNCS(strtok_r)

View File

@ -44,6 +44,11 @@
# include <sys/event.h>
#endif
#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD)
# define USE_EVENTFD
# include <sys/eventfd.h>
#endif
#include <event.h>
#include "logger.h"
@ -68,7 +73,11 @@ struct stacked_dir {
};
#ifdef USE_EVENTFD
static int exit_efd;
#else
static int exit_pipe[2];
#endif
static int scan_exit;
static int inofd;
static struct event_base *evbase_scan;
@ -1231,17 +1240,27 @@ filescanner_init(void)
return -1;
}
#if defined(__linux__)
ret = pipe2(exit_pipe, O_CLOEXEC);
#ifdef USE_EVENTFD
exit_efd = eventfd(0, EFD_CLOEXEC);
if (exit_efd < 0)
{
DPRINTF(E_FATAL, L_SCAN, "Could not create eventfd: %s\n", strerror(errno));
goto pipe_fail;
}
#else
# if defined(__linux__)
ret = pipe2(exit_pipe, O_CLOEXEC);
# else
ret = pipe(exit_pipe);
#endif
# endif
if (ret < 0)
{
DPRINTF(E_FATAL, L_SCAN, "Could not create pipe: %s\n", strerror(errno));
goto pipe_fail;
}
#endif /* USE_EVENTFD */
#if defined(__linux__)
inofd = inotify_init1(IN_CLOEXEC);
@ -1269,7 +1288,11 @@ filescanner_init(void)
event_base_set(evbase_scan, &inoev);
#ifdef USE_EVENTFD
event_set(&exitev, exit_efd, EV_READ, exit_cb, NULL);
#else
event_set(&exitev, exit_pipe[0], EV_READ, exit_cb, NULL);
#endif
event_base_set(evbase_scan, &exitev);
event_add(&exitev, NULL);
@ -1286,8 +1309,12 @@ filescanner_init(void)
thread_fail:
close(inofd);
ino_fail:
#ifdef USE_EVENTFD
close(exit_efd);
#else
close(exit_pipe[0]);
close(exit_pipe[1]);
#endif
pipe_fail:
event_base_free(evbase_scan);
@ -1298,9 +1325,19 @@ filescanner_init(void)
void
filescanner_deinit(void)
{
int dummy = 42;
int ret;
#ifdef USE_EVENTFD
ret = eventfd_write(exit_efd, 1);
if (ret < 0)
{
DPRINTF(E_FATAL, L_SCAN, "Could not send exit event: %s\n", strerror(errno));
return;
}
#else
int dummy = 42;
ret = write(exit_pipe[1], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
{
@ -1308,6 +1345,7 @@ filescanner_deinit(void)
return;
}
#endif
ret = pthread_join(tid_scan, NULL);
if (ret != 0)
@ -1317,8 +1355,12 @@ filescanner_deinit(void)
return;
}
#ifdef USE_EVENTFD
close(exit_efd);
#else
close(exit_pipe[0]);
close(exit_pipe[1]);
#endif
close(inofd);
event_base_free(evbase_scan);
}

View File

@ -36,6 +36,11 @@
#include <stdint.h>
#include <inttypes.h>
#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD)
# define USE_EVENTFD
# include <sys/eventfd.h>
#endif
#include <event.h>
#include "evhttp/evhttp.h"
@ -107,7 +112,11 @@ static struct content_type_map ext2ctype[] =
{ NULL, NULL }
};
#ifdef USE_EVENTFD
static int exit_efd;
#else
static int exit_pipe[2];
#endif
static int httpd_exit;
static struct event_base *evbase_httpd;
static struct event exitev;
@ -1104,17 +1113,27 @@ httpd_init(void)
goto dacp_fail;
}
#if defined(__linux__)
ret = pipe2(exit_pipe, O_CLOEXEC);
#ifdef USE_EVENTFD
exit_efd = eventfd(0, EFD_CLOEXEC);
if (exit_efd < 0)
{
DPRINTF(E_FATAL, L_HTTPD, "Could not create eventfd: %s\n", strerror(errno));
goto pipe_fail;
}
#else
# if defined(__linux__)
ret = pipe2(exit_pipe, O_CLOEXEC);
# else
ret = pipe(exit_pipe);
#endif
# endif
if (ret < 0)
{
DPRINTF(E_FATAL, L_HTTPD, "Could not create pipe: %s\n", strerror(errno));
goto pipe_fail;
}
#endif /* USE_EVENTFD */
evbase_httpd = event_base_new();
if (!evbase_httpd)
@ -1124,7 +1143,11 @@ httpd_init(void)
goto evbase_fail;
}
#ifdef USE_EVENTFD
event_set(&exitev, exit_efd, EV_READ, exit_cb, NULL);
#else
event_set(&exitev, exit_pipe[0], EV_READ, exit_cb, NULL);
#endif
event_base_set(evbase_httpd, &exitev);
event_add(&exitev, NULL);
@ -1172,8 +1195,12 @@ httpd_init(void)
evhttp_fail:
event_base_free(evbase_httpd);
evbase_fail:
#ifdef USE_EVENTFD
close(exit_efd);
#else
close(exit_pipe[0]);
close(exit_pipe[1]);
#endif
pipe_fail:
dacp_deinit();
dacp_fail:
@ -1188,9 +1215,19 @@ httpd_init(void)
void
httpd_deinit(void)
{
int dummy = 42;
int ret;
#ifdef USE_EVENTFD
ret = eventfd_write(exit_efd, 1);
if (ret < 0)
{
DPRINTF(E_FATAL, L_HTTPD, "Could not send exit event: %s\n", strerror(errno));
return;
}
#else
int dummy = 42;
ret = write(exit_pipe[1], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
{
@ -1198,6 +1235,7 @@ httpd_deinit(void)
return;
}
#endif
ret = pthread_join(tid_httpd, NULL);
if (ret != 0)
@ -1211,8 +1249,12 @@ httpd_deinit(void)
dacp_deinit();
daap_deinit();
#ifdef USE_EVENTFD
close(exit_efd);
#else
close(exit_pipe[0]);
close(exit_pipe[1]);
#endif
evhttp_free(evhttpd);
event_base_free(evbase_httpd);
}

View File

@ -46,6 +46,11 @@
# include <sys/endian.h>
#endif
#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD)
# define USE_EVENTFD
# include <sys/eventfd.h>
#endif
#include <avahi-common/malloc.h>
#include <event.h>
@ -77,7 +82,11 @@ struct remote_info {
/* Main event base, from main.c */
extern struct event_base *evbase_main;
#ifdef USE_EVENTFD
static int pairing_efd;
#else
static int pairing_pipe[2];
#endif
static struct event pairingev;
static pthread_mutex_t remote_lck = PTHREAD_MUTEX_INITIALIZER;
static struct remote_info *remote_list;
@ -460,12 +469,20 @@ add_remote_pin_data(char *devname, char *pin)
static void
kickoff_pairing(void)
{
#ifdef USE_EVENTFD
int ret;
ret = eventfd_write(pairing_efd, 1);
if (ret < 0)
DPRINTF(E_LOG, L_REMOTE, "Could not send pairing event: %s\n", strerror(errno));
#else
int dummy = 42;
int ret;
ret = write(pairing_pipe[1], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
DPRINTF(E_LOG, L_REMOTE, "Could not write to pairing fd: %s\n", strerror(errno));
#endif
}
@ -845,11 +862,24 @@ static void
pairing_cb(int fd, short event, void *arg)
{
struct remote_info *ri;
#ifdef USE_EVENTFD
eventfd_t count;
int ret;
ret = eventfd_read(pairing_efd, &count);
if (ret < 0)
{
DPRINTF(E_LOG, L_REMOTE, "Could not read event counter: %s\n", strerror(errno));
return;
}
#else
int dummy;
/* Drain the pipe */
while (read(pairing_pipe[0], &dummy, sizeof(dummy)) >= 0)
; /* EMPTY */
#endif
for (;;)
{
@ -886,11 +916,20 @@ remote_pairing_init(void)
remote_list = NULL;
#if defined(__linux__)
ret = pipe2(pairing_pipe, O_CLOEXEC | O_NONBLOCK);
#ifdef USE_EVENTFD
pairing_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (pairing_efd < 0)
{
DPRINTF(E_FATAL, L_REMOTE, "Could not create eventfd: %s\n", strerror(errno));
return -1;
}
#else
# if defined(__linux__)
ret = pipe2(pairing_pipe, O_CLOEXEC | O_NONBLOCK);
# else
ret = pipe(pairing_pipe);
#endif
# endif
if (ret < 0)
{
DPRINTF(E_FATAL, L_REMOTE, "Could not create pairing pipe: %s\n", strerror(errno));
@ -898,7 +937,7 @@ remote_pairing_init(void)
return -1;
}
#ifndef __linux__
# ifndef __linux__
ret = fcntl(pairing_pipe[0], F_SETFL, O_NONBLOCK);
if (ret < 0)
{
@ -906,7 +945,8 @@ remote_pairing_init(void)
goto pairing_pipe_fail;
}
#endif
# endif
#endif /* USE_EVENTFD */
ret = mdns_browse("_touch-remote._tcp", touch_remote_cb);
if (ret < 0)
@ -919,7 +959,11 @@ remote_pairing_init(void)
libname = cfg_getstr(cfg_getnsec(cfg, "library", 0), "name");
libhash = murmur_hash64(libname, strlen(libname), 0);
#ifdef USE_EVENTFD
event_set(&pairingev, pairing_efd, EV_READ, pairing_cb, NULL);
#else
event_set(&pairingev, pairing_pipe[0], EV_READ, pairing_cb, NULL);
#endif
event_base_set(evbase_main, &pairingev);
event_add(&pairingev, NULL);
@ -929,8 +973,12 @@ remote_pairing_init(void)
pairing_pipe_fail:
#endif
mdns_browse_fail:
#ifdef USE_EVENTFD
close(pairing_efd);
#else
close(pairing_pipe[0]);
close(pairing_pipe[1]);
#endif
return -1;
}
@ -948,6 +996,10 @@ remote_pairing_deinit(void)
free_remote(ri);
}
#ifdef USE_EVENTFD
close(pairing_efd);
#else
close(pairing_pipe[0]);
close(pairing_pipe[1]);
#endif
}