From ef218ac4d8ec01ae866419df881a32a307b7ec22 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 1 Aug 2012 05:00:00 +0200 Subject: [PATCH] implement epoll (Jamie Turner) --- fd.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++- taskimpl.h | 7 +++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/fd.c b/fd.c index f3d5950..3fe387e 100644 --- a/fd.c +++ b/fd.c @@ -1,7 +1,14 @@ #include "taskimpl.h" +#if USE_EPOLL +#include +#else #include +#endif #include +#if USE_EPOLL +static int epfd; +#else enum { MAXFD = 1024 @@ -10,11 +17,69 @@ enum static struct pollfd pollfd[MAXFD]; static Task *polltask[MAXFD]; static int npollfd; +#endif + static int startedfdtask; static Tasklist sleeping; static int sleepingcounted; static uvlong nsec(void); +#if USE_EPOLL + +void +fdtask(void *v) +{ + struct epoll_event events[1000]; + int i, ms, nevents; + Task *t; + uvlong now; + + USED(v); + tasksystem(); + taskname("fdtask"); + for(;;){ + /* let everyone else run */ + while(taskyield() > 0) + ; + /* we're the only one runnable - poll for i/o */ + errno = 0; + taskstate("epoll"); + if((t=sleeping.head) == nil) + ms = -1; + else{ + /* sleep at most 5s */ + now = nsec(); + if(now >= t->alarmtime) + ms = 0; + else if(now+5*1000*1000*1000LL >= t->alarmtime) + ms = (t->alarmtime - now)/1000000; + else + ms = 5000; + } + if((nevents = epoll_wait(epfd, events, 1000, ms)) < 0){ + if(errno == EINTR) + continue; + fprint(2, "epoll: %s\n", strerror(errno)); + taskexitall(0); + } + + /* wake up the guys who deserve it */ + for(i=0; i= t->alarmtime){ + deltask(&sleeping, t); + if(!t->system && --sleepingcounted == 0) + taskcount--; + taskready(t); + } + } +} + +#else + void fdtask(void *v) { @@ -60,7 +125,7 @@ fdtask(void *v) polltask[i] = polltask[npollfd]; } } - + now = nsec(); while((t=sleeping.head) && now >= t->alarmtime){ deltask(&sleeping, t); @@ -71,6 +136,8 @@ fdtask(void *v) } } +#endif + uint taskdelay(uint ms) { @@ -79,6 +146,11 @@ taskdelay(uint ms) if(!startedfdtask){ startedfdtask = 1; +#if USE_EPOLL + epfd = epoll_create(1); + if(epfd < 0) + abort(); +#endif taskcreate(fdtask, 0, 32768); } @@ -113,6 +185,53 @@ taskdelay(uint ms) return (nsec() - now)/1000000; } +#if USE_EPOLL + +void +fdwait(int fd, int rw) +{ + struct epoll_event ev; + int bits, duped, r; + + if(!startedfdtask){ + startedfdtask = 1; + epfd = epoll_create(1); + if(epfd < 0) + abort(); + taskcreate(fdtask, 0, 32768); + } + + taskstate("fdwait for %s", rw=='r' ? "read" : rw=='w' ? "write" : "error"); + bits = 0; + switch(rw){ + case 'r': + bits |= EPOLLIN | EPOLLPRI; + break; + case 'w': + bits |= EPOLLOUT; + break; + } + + memset(&ev, 0, sizeof(ev)); + ev.events = bits; + ev.data.ptr = taskrunning; + r = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); + duped = 0; + if(r < 0 || errno == EEXIST){ + duped = 1; + fd = dup(fd); + r = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); + if(r != 0) + abort(); + } + taskswitch(); + epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev); + if(duped) + close(fd); +} + +#else + void fdwait(int fd, int rw) { @@ -147,6 +266,8 @@ fdwait(int fd, int rw) taskswitch(); } +#endif + /* Like fdread but always calls fdwait before reading. */ int fdread1(int fd, void *buf, int n) diff --git a/taskimpl.h b/taskimpl.h index 4fd7ba6..84a2d35 100644 --- a/taskimpl.h +++ b/taskimpl.h @@ -26,6 +26,13 @@ #endif #endif +#define USE_EPOLL 1 + +#if !defined(__linux) +#undef USE_EPOLL +#define USE_EPOLL 0 +#endif + #include #include #include