mirror of
https://github.com/0intro/libtask
synced 2024-11-21 21:31:30 +03:00
implement epoll (Jamie Turner)
This commit is contained in:
parent
f5ea2e72ba
commit
ef218ac4d8
123
fd.c
123
fd.c
@ -1,7 +1,14 @@
|
|||||||
#include "taskimpl.h"
|
#include "taskimpl.h"
|
||||||
|
#if USE_EPOLL
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#else
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#if USE_EPOLL
|
||||||
|
static int epfd;
|
||||||
|
#else
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
MAXFD = 1024
|
MAXFD = 1024
|
||||||
@ -10,11 +17,69 @@ enum
|
|||||||
static struct pollfd pollfd[MAXFD];
|
static struct pollfd pollfd[MAXFD];
|
||||||
static Task *polltask[MAXFD];
|
static Task *polltask[MAXFD];
|
||||||
static int npollfd;
|
static int npollfd;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int startedfdtask;
|
static int startedfdtask;
|
||||||
static Tasklist sleeping;
|
static Tasklist sleeping;
|
||||||
static int sleepingcounted;
|
static int sleepingcounted;
|
||||||
static uvlong nsec(void);
|
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<nevents; i++){
|
||||||
|
taskready((Task *)events[i].data.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
now = nsec();
|
||||||
|
while((t=sleeping.head) && now >= t->alarmtime){
|
||||||
|
deltask(&sleeping, t);
|
||||||
|
if(!t->system && --sleepingcounted == 0)
|
||||||
|
taskcount--;
|
||||||
|
taskready(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
void
|
void
|
||||||
fdtask(void *v)
|
fdtask(void *v)
|
||||||
{
|
{
|
||||||
@ -60,7 +125,7 @@ fdtask(void *v)
|
|||||||
polltask[i] = polltask[npollfd];
|
polltask[i] = polltask[npollfd];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
now = nsec();
|
now = nsec();
|
||||||
while((t=sleeping.head) && now >= t->alarmtime){
|
while((t=sleeping.head) && now >= t->alarmtime){
|
||||||
deltask(&sleeping, t);
|
deltask(&sleeping, t);
|
||||||
@ -71,6 +136,8 @@ fdtask(void *v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
uint
|
uint
|
||||||
taskdelay(uint ms)
|
taskdelay(uint ms)
|
||||||
{
|
{
|
||||||
@ -79,6 +146,11 @@ taskdelay(uint ms)
|
|||||||
|
|
||||||
if(!startedfdtask){
|
if(!startedfdtask){
|
||||||
startedfdtask = 1;
|
startedfdtask = 1;
|
||||||
|
#if USE_EPOLL
|
||||||
|
epfd = epoll_create(1);
|
||||||
|
if(epfd < 0)
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
taskcreate(fdtask, 0, 32768);
|
taskcreate(fdtask, 0, 32768);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,6 +185,53 @@ taskdelay(uint ms)
|
|||||||
return (nsec() - now)/1000000;
|
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
|
void
|
||||||
fdwait(int fd, int rw)
|
fdwait(int fd, int rw)
|
||||||
{
|
{
|
||||||
@ -147,6 +266,8 @@ fdwait(int fd, int rw)
|
|||||||
taskswitch();
|
taskswitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Like fdread but always calls fdwait before reading. */
|
/* Like fdread but always calls fdwait before reading. */
|
||||||
int
|
int
|
||||||
fdread1(int fd, void *buf, int n)
|
fdread1(int fd, void *buf, int n)
|
||||||
|
@ -26,6 +26,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define USE_EPOLL 1
|
||||||
|
|
||||||
|
#if !defined(__linux)
|
||||||
|
#undef USE_EPOLL
|
||||||
|
#define USE_EPOLL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user