mirror of /home/gitosis/repositories/libev.git
implement select method
parent
7e9192be63
commit
22a3064bad
3
README
3
README
|
@ -22,6 +22,9 @@ to be faster and more correct, and also more featureful. Examples:
|
|||
- can correctly remove timers while executing callbacks
|
||||
(libevent doesn't handle this reliably and can crash)
|
||||
|
||||
- race-free signal processing
|
||||
(libevent may delay processing signals till after the next event)
|
||||
|
||||
- less calls to epoll_ctl
|
||||
(stopping and starting an io watcher between two loop iterations will now
|
||||
result in spuriois epoll_ctl calls)
|
||||
|
|
35
ev.c
35
ev.c
|
@ -14,7 +14,7 @@
|
|||
|
||||
#define HAVE_EPOLL 1
|
||||
#define HAVE_REALTIME 1
|
||||
#define HAVE_SELECT 0
|
||||
#define HAVE_SELECT 1
|
||||
|
||||
#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
|
||||
#define MAX_BLOCKTIME 60.
|
||||
|
@ -36,7 +36,7 @@ int ev_method;
|
|||
static int have_monotonic; /* runtime */
|
||||
|
||||
static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */
|
||||
static void (*method_reify)(void);
|
||||
static void (*method_modify)(int fd, int oev, int nev);
|
||||
static void (*method_poll)(ev_tstamp timeout);
|
||||
|
||||
ev_tstamp
|
||||
|
@ -236,10 +236,37 @@ void ev_postfork_parent (void)
|
|||
void ev_postfork_child (void)
|
||||
{
|
||||
#if HAVE_EPOLL
|
||||
epoll_postfork_child ();
|
||||
if (ev_method == EVMETHOD_EPOLL)
|
||||
epoll_postfork_child ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
fd_reify (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fdchangecnt; ++i)
|
||||
{
|
||||
int fd = fdchanges [i];
|
||||
ANFD *anfd = anfds + fd;
|
||||
struct ev_io *w;
|
||||
|
||||
int wev = 0;
|
||||
|
||||
for (w = anfd->head; w; w = w->next)
|
||||
wev |= w->events;
|
||||
|
||||
if (anfd->wev != wev)
|
||||
{
|
||||
method_modify (fd, anfd->wev, wev);
|
||||
anfd->wev = wev;
|
||||
}
|
||||
}
|
||||
|
||||
fdchangecnt = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
call_pending ()
|
||||
{
|
||||
|
@ -338,7 +365,7 @@ void ev_loop (int flags)
|
|||
do
|
||||
{
|
||||
/* update fd-related kernel structures */
|
||||
method_reify (); fdchangecnt = 0;
|
||||
fd_reify ();
|
||||
|
||||
/* calculate blocking time */
|
||||
if (flags & EVLOOP_NONBLOCK)
|
||||
|
|
53
ev_epoll.c
53
ev_epoll.c
|
@ -3,44 +3,31 @@
|
|||
static int epoll_fd = -1;
|
||||
|
||||
static void
|
||||
epoll_reify_fd (int fd)
|
||||
epoll_modify (int fd, int oev, int nev)
|
||||
{
|
||||
ANFD *anfd = anfds + fd;
|
||||
struct ev_io *w;
|
||||
int mode = nev ? oev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD : EPOLL_CTL_DEL;
|
||||
|
||||
int wev = 0;
|
||||
struct epoll_event ev;
|
||||
ev.data.fd = fd;
|
||||
ev.events =
|
||||
(nev & EV_READ ? EPOLLIN : 0)
|
||||
| (nev & EV_WRITE ? EPOLLOUT : 0);
|
||||
|
||||
for (w = anfd->head; w; w = w->next)
|
||||
wev |= w->events;
|
||||
|
||||
if (anfd->wev != wev)
|
||||
{
|
||||
int mode = wev ? anfd->wev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD : EPOLL_CTL_DEL;
|
||||
struct epoll_event ev;
|
||||
ev.events = wev;
|
||||
ev.data.fd = fd;
|
||||
fprintf (stderr, "reify %d,%d,%d m%d (r=%d)\n", fd, anfd->wev, wev, mode,//D
|
||||
epoll_ctl (epoll_fd, mode, fd, &ev)
|
||||
);//D
|
||||
anfd->wev = wev;
|
||||
}
|
||||
fprintf (stderr, "reify %d,%d,%d m%d (r=%d)\n", fd, oev, nev, mode,//D
|
||||
epoll_ctl (epoll_fd, mode, fd, &ev)
|
||||
);//D
|
||||
}
|
||||
|
||||
void epoll_postfork_child (void)
|
||||
{
|
||||
int i;
|
||||
int fd;
|
||||
|
||||
epoll_fd = epoll_create (256);
|
||||
|
||||
for (i = 0; i < anfdmax; ++i)
|
||||
epoll_reify_fd (i);
|
||||
}
|
||||
|
||||
static void epoll_reify (void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fdchangecnt; ++i)
|
||||
epoll_reify_fd (fdchanges [i]);
|
||||
/* re-register interest in fds */
|
||||
for (fd = 0; fd < anfdmax; ++fd)
|
||||
if (anfds [fd].wev)
|
||||
epoll_modify (fd, EV_NONE, anfds [fd].wev);
|
||||
}
|
||||
|
||||
static struct epoll_event *events;
|
||||
|
@ -57,8 +44,8 @@ static void epoll_poll (ev_tstamp timeout)
|
|||
for (i = 0; i < eventcnt; ++i)
|
||||
fd_event (
|
||||
events [i].data.fd,
|
||||
(events [i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLPRI) ? EV_WRITE : 0)
|
||||
| (events [i].events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0)
|
||||
(events [i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)
|
||||
| (events [i].events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0)
|
||||
);
|
||||
|
||||
/* if the receive array was full, increase its size */
|
||||
|
@ -78,9 +65,9 @@ int epoll_init (int flags)
|
|||
return 0;
|
||||
|
||||
ev_method = EVMETHOD_EPOLL;
|
||||
method_fudge = 1e-3; /* needed to compensate fro epoll returning early */
|
||||
method_reify = epoll_reify;
|
||||
method_poll = epoll_poll;
|
||||
method_fudge = 1e-3; /* needed to compensate for epoll returning early */
|
||||
method_modify = epoll_modify;
|
||||
method_poll = epoll_poll;
|
||||
|
||||
eventmax = 64; /* intiial number of events receivable per poll */
|
||||
events = malloc (sizeof (struct epoll_event) * eventmax);
|
||||
|
|
92
ev_select.c
92
ev_select.c
|
@ -0,0 +1,92 @@
|
|||
/* for broken bsd's */
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* for unix systems */
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static unsigned char *vec_ri, *vec_ro, *vec_wi, *vec_wo;
|
||||
static int vec_max;
|
||||
|
||||
static void
|
||||
select_modify (int fd, int oev, int nev)
|
||||
{
|
||||
int offs = fd >> 3;
|
||||
int mask = 1 << (fd & 7);
|
||||
|
||||
if (vec_max < (fd >> 5) + 1)
|
||||
{
|
||||
vec_max = (fd >> 5) + 1;
|
||||
|
||||
vec_ri = (unsigned char *)realloc (vec_ri, vec_max * 4);
|
||||
vec_ro = (unsigned char *)realloc (vec_ro, vec_max * 4); /* could free/malloc */
|
||||
vec_wi = (unsigned char *)realloc (vec_wi, vec_max * 4);
|
||||
vec_wo = (unsigned char *)realloc (vec_wo, vec_max * 4); /* could free/malloc */
|
||||
}
|
||||
|
||||
vec_ri [offs] |= mask;
|
||||
if (!(nev & EV_READ))
|
||||
vec_ri [offs] &= ~mask;
|
||||
|
||||
vec_wi [offs] |= mask;
|
||||
if (!(nev & EV_WRITE))
|
||||
vec_wi [offs] &= ~mask;
|
||||
}
|
||||
|
||||
static void select_poll (ev_tstamp timeout)
|
||||
{
|
||||
struct timeval tv;
|
||||
int res;
|
||||
|
||||
memcpy (vec_ro, vec_ri, vec_max * 4);
|
||||
memcpy (vec_wo, vec_wi, vec_max * 4);
|
||||
|
||||
tv.tv_sec = (long)timeout;
|
||||
tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
|
||||
|
||||
res = select (vec_max * 32, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
int word, offs;
|
||||
|
||||
for (word = vec_max; word--; )
|
||||
{
|
||||
if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
|
||||
for (offs = 4; offs--; )
|
||||
{
|
||||
int idx = word * 4 + offs;
|
||||
unsigned char byte_r = vec_ro [idx];
|
||||
unsigned char byte_w = vec_wo [idx];
|
||||
int bit;
|
||||
|
||||
if (byte_r | byte_w)
|
||||
for (bit = 8; bit--; )
|
||||
{
|
||||
int events = 0;
|
||||
events |= byte_r & (1 << bit) ? EV_READ : 0;
|
||||
events |= byte_w & (1 << bit) ? EV_WRITE : 0;
|
||||
|
||||
if (events)
|
||||
fd_event (idx * 8 + bit, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int select_init (int flags)
|
||||
{
|
||||
ev_method = EVMETHOD_SELECT;
|
||||
method_fudge = 1e-2; /* needed to compensate for select returning early, very conservative */
|
||||
method_modify = select_modify;
|
||||
method_poll = select_poll;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue