summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2009-11-23 23:40:27 +0100
committerantirez <antirez@gmail.com>2009-11-23 23:40:27 +0100
commit64f36a5836c8c375247ca0623712a35f80c6cfb2 (patch)
tree958fa3b4fb1396ed913778b0675723b36113ebdc
parentfb6a19677819cb2e35723bb5565a603cb069f461 (diff)
downloadredis-64f36a5836c8c375247ca0623712a35f80c6cfb2.tar.gz
epoll module for ae.c implemented. Some more testing needed
-rw-r--r--Makefile2
-rw-r--r--ae_epoll.c85
2 files changed, 86 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 7d9bdc57c..34b35f576 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ all: redis-server redis-benchmark redis-cli
# Deps (use make dep to generate this)
adlist.o: adlist.c adlist.h zmalloc.h
-ae.o: ae.c ae.h zmalloc.h ae_select.c
+ae.o: ae.c ae.h zmalloc.h ae_select.c ae_epoll.c
ae_select.o: ae_select.c
anet.o: anet.c fmacros.h anet.h
benchmark.o: benchmark.c fmacros.h ae.h anet.h sds.h adlist.h zmalloc.h
diff --git a/ae_epoll.c b/ae_epoll.c
new file mode 100644
index 000000000..b63b74b51
--- /dev/null
+++ b/ae_epoll.c
@@ -0,0 +1,85 @@
+/* Linux epoll(2) based ae.c module
+ * Copyright (C) 2009 Salvatore Sanfilippo - antirez@gmail.com
+ * Released under the BSD license. See the COPYING file for more info. */
+
+#include <sys/epoll.h>
+
+typedef struct aeApiState {
+ int epfd;
+ struct epoll_event events[AE_SETSIZE];
+} aeApiState;
+
+static int aeApiCreate(aeEventLoop *eventLoop) {
+ aeApiState *state = zmalloc(sizeof(aeApiState));
+
+ if (!state) return -1;
+ state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */
+ if (state->epfd == -1) return -1;
+ eventLoop->apidata = state;
+ return 0;
+}
+
+static void aeApiFree(aeEventLoop *eventLoop) {
+ aeApiState *state = eventLoop->apidata;
+
+ close(state->epfd);
+ zfree(state);
+}
+
+static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
+ aeApiState *state = eventLoop->apidata;
+ struct epoll_event ee;
+ int op = eventLoop->events[fd].mask == AE_NONE ?
+ EPOLL_CTL_ADD : EPOLL_CTL_MOD;
+
+ ee.events = 0;
+ if (mask & AE_READABLE) ee.events |= EPOLLIN;
+ if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
+ if (mask & AE_EXCEPTION) ee.events |= EPOLLPRI;
+ ee.data.fd = fd;
+ if (epoll_ctl(state->epfd,op,fd,&ee) == -1) return -1;
+ return 0;
+}
+
+static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {
+ aeApiState *state = eventLoop->apidata;
+ struct epoll_event ee;
+ int mask = eventLoop->events[fd].mask & (~delmask);
+
+ ee.events = 0;
+ if (mask & AE_READABLE) ee.events |= EPOLLIN;
+ if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
+ if (mask & AE_EXCEPTION) ee.events |= EPOLLPRI;
+ ee.data.fd = fd;
+ if (mask != AE_NONE) {
+ epoll_ctl(state->epfd,EPOLL_CTL_MOD,fd,&ee);
+ } else {
+ /* Note, Kernel < 2.6.9 requires a non null event pointer even for
+ * EPOLL_CTL_DEL. */
+ epoll_ctl(state->epfd,EPOLL_CTL_DEL,fd,&ee);
+ }
+}
+
+static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
+ aeApiState *state = eventLoop->apidata;
+ int retval, numevents = 0;
+
+ retval = epoll_wait(state->epfd,state->events,AE_SETSIZE,
+ tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);
+ if (retval > 0) {
+ int j;
+
+ numevents = retval;
+ for (j = 0; j < numevents; j++) {
+ int mask = 0;
+ struct epoll_event *e = state->events+j;
+
+ if (e->events & EPOLLIN) mask |= AE_READABLE;
+ if (e->events & EPOLLOUT) mask |= AE_WRITABLE;
+ if (e->events & EPOLLPRI) mask |= AE_EXCEPTION;
+ eventLoop->fired[j].fd = e->data.fd;
+ eventLoop->fired[j].mask = mask;
+ }
+ }
+ return numevents;
+}