Browse Source

implement select method

tags/rel-0.5
Marc Alexander Lehmann 13 years ago
parent
commit
22a3064bad
4 changed files with 146 additions and 37 deletions
  1. +3
    -0
      README
  2. +31
    -4
      ev.c
  3. +20
    -33
      ev_epoll.c
  4. +92
    -0
      ev_select.c

+ 3
- 0
README View File

@@ -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)


+ 31
- 4
ev.c View File

@@ -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)


+ 20
- 33
ev_epoll.c View File

@@ -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
- 0
ev_select.c View File

@@ -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…
Cancel
Save