From cb4320791b301cbf8c0e2cbf5f09a7807b627810 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Thu, 4 Feb 2010 18:52:13 +0100 Subject: [PATCH] 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). --- configure.in | 2 ++ src/filescanner.c | 50 ++++++++++++++++++++++++++++++++--- src/httpd.c | 50 ++++++++++++++++++++++++++++++++--- src/remote_pairing.c | 62 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 151 insertions(+), 13 deletions(-) diff --git a/configure.in b/configure.in index dc971ba5..d453ed86 100644 --- a/configure.in +++ b/configure.in @@ -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) diff --git a/src/filescanner.c b/src/filescanner.c index bdaee39d..fca1c57a 100644 --- a/src/filescanner.c +++ b/src/filescanner.c @@ -44,6 +44,11 @@ # include #endif +#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD) +# define USE_EVENTFD +# include +#endif + #include #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); } diff --git a/src/httpd.c b/src/httpd.c index 62855f36..cedce0a6 100644 --- a/src/httpd.c +++ b/src/httpd.c @@ -36,6 +36,11 @@ #include #include +#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD) +# define USE_EVENTFD +# include +#endif + #include #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); } diff --git a/src/remote_pairing.c b/src/remote_pairing.c index 257819cc..46aebdc2 100644 --- a/src/remote_pairing.c +++ b/src/remote_pairing.c @@ -46,6 +46,11 @@ # include #endif +#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD) +# define USE_EVENTFD +# include +#endif + #include #include @@ -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 }