@@ -25,7 +25,8 @@ aplay_SOURCES = \
aligner-multiple.c \
waiter.h \
waiter.c \
- waiter-poll.c
+ waiter-poll.c \
+ waiter-epoll.c
EXTRA_DIST = aplay.1 arecord.1
EXTRA_CLEAN = arecord
new file mode 100644
@@ -0,0 +1,76 @@
+/*
+ * waiter-waiter-epoll.c - Waiter for event notification by epoll(7).
+ *
+ * Copyright (c) 2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include "waiter.h"
+
+#include <sys/epoll.h>
+
+struct epoll_state {
+ int epfd;
+ struct epoll_event *events;
+ unsigned int count;
+};
+
+static int epoll_prepare(struct waiter_context *waiter, int *fds,
+ unsigned int fd_count)
+{
+ struct epoll_state *state = waiter->private_data;
+ int i;
+
+ state->events = calloc(fd_count, sizeof(struct epoll_event));
+ if (state->events == NULL)
+ return -ENOMEM;
+ state->count = fd_count;
+
+ state->epfd = epoll_create(1);
+ if (state->epfd < 0)
+ return -errno;
+
+ for (i = 0; i < fd_count; ++i) {
+ struct epoll_event *ev = &state->events[i];
+ ev->events = EPOLLIN | EPOLLOUT;
+ if (epoll_ctl(state->epfd, EPOLL_CTL_ADD, fds[i], ev) < 0)
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int epoll_wait_event(struct waiter_context *waiter)
+{
+ struct epoll_state *state = waiter->private_data;
+ int err;
+
+ err = epoll_wait(state->epfd, state->events, state->count, 0);
+ if (err < 0)
+ return -errno;
+
+ return 0;
+}
+
+static void epoll_release(struct waiter_context *waiter)
+{
+ struct epoll_state *state = waiter->private_data;
+
+ if (state->events)
+ free(state->events);
+
+ close(state->epfd);
+
+ state->events = NULL;
+ state->epfd = 0;
+}
+
+const struct waiter_data waiter_epoll = {
+ .ops = {
+ .prepare = epoll_prepare,
+ .wait_event = epoll_wait_event,
+ .release = epoll_release,
+ },
+ .private_size = sizeof(struct epoll_state),
+};
@@ -15,6 +15,7 @@ int waiter_context_init(struct waiter_context *waiter, enum waiter_type type)
const struct waiter_data *waiter;
} entries[] = {
{WAITER_TYPE_POLL, &waiter_poll},
+ {WAITER_TYPE_EPOLL, &waiter_epoll},
};
int i;
@@ -20,6 +20,7 @@
enum waiter_type {
WAITER_TYPE_POLL = 0,
+ WAITER_TYPE_EPOLL = 0,
WAITER_TYPE_COUNT,
};
@@ -53,5 +54,6 @@ struct waiter_data {
};
extern const struct waiter_data waiter_poll;
+extern const struct waiter_data waiter_epoll;
#endif