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:
parent
274dccf66c
commit
cb4320791b
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
50
src/httpd.c
50
src/httpd.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue