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/param.h])
AC_CHECK_HEADERS([sys/select.h]) AC_CHECK_HEADERS([sys/select.h])
AC_CHECK_HEADERS([dirent.h]) AC_CHECK_HEADERS([dirent.h])
AC_CHECK_HEADERS([sys/eventfd.h])
AC_CHECK_FUNCS(eventfd)
AC_CHECK_FUNCS(posix_fadvise) AC_CHECK_FUNCS(posix_fadvise)
AC_CHECK_FUNCS(strptime) AC_CHECK_FUNCS(strptime)
AC_CHECK_FUNCS(strtok_r) AC_CHECK_FUNCS(strtok_r)

View File

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

View File

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

View File

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