diff --git a/Makefile b/Makefile index 7d9bdc57c337c6cfb6cbf20ad2f4792d858722b6..34b35f5767c188b63b8fe9e342bf8d3335a6be98 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 0000000000000000000000000000000000000000..b63b74b51f251e919d9ad471a1cba36ee445a8db --- /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 + +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; +}