diff options
author | Volker Lendecke <vl@samba.org> | 2016-08-12 16:32:33 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2016-08-24 01:33:48 +0200 |
commit | c7e2cb839df13bcbd14a05a39559366813b8c566 (patch) | |
tree | 1e8660222a73bd6781808ca9443e91564c9da499 /lib/tevent | |
parent | f40c171743d011e70e9674af312046034278b1e1 (diff) | |
download | samba-c7e2cb839df13bcbd14a05a39559366813b8c566.tar.gz |
tevent: Use eventfd for signal/thread wakeup
According to the manpage, eventfd is cheaper than a pipe. At least, we can save
a file descriptor and space for it in struct tevent_context :-)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tevent')
-rw-r--r-- | lib/tevent/tevent.c | 66 | ||||
-rw-r--r-- | lib/tevent/tevent_internal.h | 7 |
2 files changed, 53 insertions, 20 deletions
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index e35eb5ddc93..331be0eb110 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -66,6 +66,9 @@ #include "tevent.h" #include "tevent_internal.h" #include "tevent_util.h" +#ifdef HAVE_EVENTFD +#include <sys/eventfd.h> +#endif static void tevent_abort(struct tevent_context *ev, const char *reason); @@ -767,7 +770,7 @@ done: bool tevent_common_have_events(struct tevent_context *ev) { if (ev->fd_events != NULL) { - if (ev->fd_events != ev->pipe_fde) { + if (ev->fd_events != ev->wakeup_fde) { return true; } if (ev->fd_events->next != NULL) { @@ -840,10 +843,14 @@ static void wakeup_pipe_handler(struct tevent_context *ev, { ssize_t ret; - /* its non-blocking, doesn't matter if we read too much */ do { - char c[16]; - ret = read(fde->fd, c, sizeof(c)); + /* + * This is the boilerplate for eventfd, but it works + * for pipes too. And as we don't care about the data + * we read, we're fine. + */ + uint64_t val; + ret = read(fde->fd, &val, sizeof(val)); } while (ret == -1 && errno == EINTR); } @@ -855,23 +862,39 @@ int tevent_common_wakeup_init(struct tevent_context *ev) { int ret; - if (ev->pipe_fde != NULL) { + if (ev->wakeup_fde != NULL) { return 0; } - ret = pipe(ev->pipe_fds); +#ifdef HAVE_EVENTFD + ret = eventfd(0, EFD_NONBLOCK); if (ret == -1) { return errno; } - ev_set_blocking(ev->pipe_fds[0], false); - ev_set_blocking(ev->pipe_fds[1], false); + ev->wakeup_fd = ret; +#else + { + int pipe_fds[2]; + ret = pipe(pipe_fds); + if (ret == -1) { + return errno; + } + ev->wakeup_fd = pipe_fds[0]; + ev->wakeup_write_fd = pipe_fds[1]; + + ev_set_blocking(ev->wakeup_fd, false); + ev_set_blocking(ev->wakeup_write_fd, false); + } +#endif - ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0], + ev->wakeup_fde = tevent_add_fd(ev, ev, ev->wakeup_fd, TEVENT_FD_READ, wakeup_pipe_handler, NULL); - if (ev->pipe_fde == NULL) { - close(ev->pipe_fds[0]); - close(ev->pipe_fds[1]); + if (ev->wakeup_fde == NULL) { + close(ev->wakeup_fd); +#ifndef HAVE_EVENTFD + close(ev->wakeup_write_fd); +#endif return ENOMEM; } @@ -882,13 +905,18 @@ int tevent_common_wakeup(struct tevent_context *ev) { ssize_t ret; - if (ev->pipe_fds[1] == -1) { + if (ev->wakeup_fde == NULL) { return ENOTCONN; } do { +#ifdef HAVE_EVENTFD + uint64_t val = 1; + ret = write(ev->wakeup_fd, &val, sizeof(val)); +#else char c = '\0'; - ret = write(ev->pipe_fds[1], &c, 1); + ret = write(ev->wakeup_write_fd, &c, 1); +#endif } while ((ret == -1) && (errno == EINTR)); return 0; @@ -896,12 +924,14 @@ int tevent_common_wakeup(struct tevent_context *ev) static void tevent_common_wakeup_fini(struct tevent_context *ev) { - if (ev->pipe_fde == NULL) { + if (ev->wakeup_fde == NULL) { return; } - TALLOC_FREE(ev->pipe_fde); + TALLOC_FREE(ev->wakeup_fde); - close(ev->pipe_fds[0]); - close(ev->pipe_fds[1]); + close(ev->wakeup_fd); +#ifndef HAVE_EVENTFD + close(ev->wakeup_write_fd); +#endif } diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index f17ce940365..d9605449708 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -276,8 +276,11 @@ struct tevent_context { void *additional_data; /* pipe hack used with signal handlers */ - struct tevent_fd *pipe_fde; - int pipe_fds[2]; + struct tevent_fd *wakeup_fde; + int wakeup_fd; +#ifndef HAVE_EVENT_FD + int wakeup_write_fd; +#endif /* debugging operations */ struct tevent_debug_ops debug_ops; |