mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-08 03:44:22 -04:00
performance improvements by Nick Mathewson; we modify the arrays directly
in poll_add and poll_del; some minor tweaks by me. earmark this as 1.0f svn:r161
This commit is contained in:
parent
d6e56988a7
commit
c15db0349a
@ -2,7 +2,7 @@ dnl configure.in for libevent
|
||||
dnl Dug Song <dugsong@monkey.org>
|
||||
AC_INIT(event.c)
|
||||
|
||||
AM_INIT_AUTOMAKE(libevent,1.0e)
|
||||
AM_INIT_AUTOMAKE(libevent,1.0f)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
247
poll.c
247
poll.c
@ -45,6 +45,9 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef CHECK_INVARIANTS
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
@ -55,6 +58,7 @@ extern volatile sig_atomic_t evsignal_caught;
|
||||
|
||||
struct pollop {
|
||||
int event_count; /* Highest number alloc */
|
||||
int nfds; /* Size of event_* */
|
||||
int fd_count; /* Size of idxplus1_by_fd */
|
||||
struct pollfd *event_set;
|
||||
struct event **event_r_back;
|
||||
@ -110,97 +114,52 @@ poll_recalc(struct event_base *base, void *arg, int max)
|
||||
return (evsignal_recalc(&pop->evsigmask));
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
static void
|
||||
poll_check_ok(struct pollop *pop)
|
||||
{
|
||||
int i, idx;
|
||||
struct event *ev;
|
||||
|
||||
for (i = 0; i < pop->fd_count; ++i) {
|
||||
idx = pop->idxplus1_by_fd[i]-1;
|
||||
if (idx < 0)
|
||||
continue;
|
||||
assert(pop->event_set[idx].fd == i);
|
||||
if (pop->event_set[idx].events & POLLIN) {
|
||||
ev = pop->event_r_back[idx];
|
||||
assert(ev);
|
||||
assert(ev->ev_events & EV_READ);
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
if (pop->event_set[idx].events & POLLOUT) {
|
||||
ev = pop->event_w_back[idx];
|
||||
assert(ev);
|
||||
assert(ev->ev_events & EV_WRITE);
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < pop->nfds; ++i) {
|
||||
struct pollfd *pfd = &pop->event_set[i];
|
||||
assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define poll_check_ok(pop)
|
||||
#endif
|
||||
|
||||
int
|
||||
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int res, i, count, fd_count, sec, nfds;
|
||||
struct event *ev;
|
||||
int res, i, sec, nfds;
|
||||
struct pollop *pop = arg;
|
||||
int *idxplus1_by_fd;
|
||||
|
||||
count = pop->event_count;
|
||||
fd_count = pop->fd_count;
|
||||
idxplus1_by_fd = pop->idxplus1_by_fd;
|
||||
memset(idxplus1_by_fd, 0, sizeof(int)*fd_count);
|
||||
nfds = 0;
|
||||
|
||||
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
|
||||
struct pollfd *pfd = NULL;
|
||||
if (nfds + 1 >= count) {
|
||||
if (count < 32)
|
||||
count = 32;
|
||||
else
|
||||
count *= 2;
|
||||
|
||||
/* We need more file descriptors */
|
||||
pop->event_set = realloc(pop->event_set,
|
||||
count * sizeof(struct pollfd));
|
||||
if (pop->event_set == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_r_back = realloc(pop->event_r_back,
|
||||
count * sizeof(struct event *));
|
||||
pop->event_w_back = realloc(pop->event_w_back,
|
||||
count * sizeof(struct event *));
|
||||
if (pop->event_r_back == NULL ||
|
||||
pop->event_w_back == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_count = count;
|
||||
}
|
||||
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
|
||||
continue;
|
||||
if (ev->ev_fd >= fd_count) {
|
||||
int new_count;
|
||||
if (fd_count < 32)
|
||||
new_count = 32;
|
||||
else
|
||||
new_count = fd_count * 2;
|
||||
while (new_count <= ev->ev_fd)
|
||||
new_count *= 2;
|
||||
idxplus1_by_fd = pop->idxplus1_by_fd =
|
||||
realloc(pop->idxplus1_by_fd, new_count*sizeof(int));
|
||||
if (idxplus1_by_fd == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
memset(pop->idxplus1_by_fd + fd_count,
|
||||
0, sizeof(int)*(new_count-fd_count));
|
||||
fd_count = pop->fd_count = new_count;
|
||||
}
|
||||
i = idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i >= 0) {
|
||||
pfd = &pop->event_set[i];
|
||||
} else {
|
||||
i = nfds++;
|
||||
pfd = &pop->event_set[i];
|
||||
pop->event_w_back[i] = pop->event_r_back[i] = NULL;
|
||||
pfd->events = 0;
|
||||
idxplus1_by_fd[ev->ev_fd] = i + 1;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
pfd->fd = ev->ev_fd;
|
||||
pfd->events |= POLLOUT;
|
||||
pfd->revents = 0;
|
||||
|
||||
pop->event_w_back[i] = ev;
|
||||
}
|
||||
if (ev->ev_events & EV_READ) {
|
||||
pfd->fd = ev->ev_fd;
|
||||
pfd->events |= POLLIN;
|
||||
pfd->revents = 0;
|
||||
|
||||
pop->event_r_back[i] = ev;
|
||||
}
|
||||
}
|
||||
|
||||
if (evsignal_deliver(&pop->evsigmask) == -1)
|
||||
return (-1);
|
||||
|
||||
poll_check_ok();
|
||||
sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
nfds = pop->nfds;
|
||||
res = poll(pop->event_set, nfds, sec);
|
||||
|
||||
if (evsignal_recalc(&pop->evsigmask) == -1)
|
||||
@ -225,14 +184,14 @@ poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
for (i = 0; i < nfds; i++) {
|
||||
int what = pop->event_set[i].revents;
|
||||
struct event *r_ev = NULL, *w_ev = NULL;
|
||||
|
||||
if (!what)
|
||||
continue;
|
||||
|
||||
res = 0;
|
||||
|
||||
/* If the file gets closed notify */
|
||||
if (what & POLLHUP)
|
||||
if (what & (POLLHUP|POLLERR))
|
||||
what |= POLLIN|POLLOUT;
|
||||
if (what & POLLERR)
|
||||
what |= POLLIN|POLLOUT;
|
||||
if (what & POLLIN) {
|
||||
res |= EV_READ;
|
||||
r_ev = pop->event_r_back[i];
|
||||
@ -263,9 +222,79 @@ int
|
||||
poll_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
struct pollfd *pfd = NULL;
|
||||
int i;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_add(&pop->evsigmask, ev));
|
||||
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
poll_check_ok(pop);
|
||||
if (pop->nfds + 1 >= pop->event_count) {
|
||||
if (pop->event_count < 32)
|
||||
pop->event_count = 32;
|
||||
else
|
||||
pop->event_count *= 2;
|
||||
|
||||
/* We need more file descriptors */
|
||||
pop->event_set = realloc(pop->event_set,
|
||||
pop->event_count * sizeof(struct pollfd));
|
||||
if (pop->event_set == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_r_back = realloc(pop->event_r_back,
|
||||
pop->event_count * sizeof(struct event *));
|
||||
pop->event_w_back = realloc(pop->event_w_back,
|
||||
pop->event_count * sizeof(struct event *));
|
||||
if (pop->event_r_back == NULL ||
|
||||
pop->event_w_back == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (ev->ev_fd >= pop->fd_count) {
|
||||
int new_count;
|
||||
if (pop->fd_count < 32)
|
||||
new_count = 32;
|
||||
else
|
||||
new_count = pop->fd_count * 2;
|
||||
while (new_count <= ev->ev_fd)
|
||||
new_count *= 2;
|
||||
pop->idxplus1_by_fd =
|
||||
realloc(pop->idxplus1_by_fd, new_count*sizeof(int));
|
||||
if (pop->idxplus1_by_fd == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
memset(pop->idxplus1_by_fd + pop->fd_count,
|
||||
0, sizeof(int)*(new_count - pop->fd_count));
|
||||
pop->fd_count = new_count;
|
||||
}
|
||||
|
||||
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i >= 0) {
|
||||
pfd = &pop->event_set[i];
|
||||
} else {
|
||||
i = pop->nfds++;
|
||||
pfd = &pop->event_set[i];
|
||||
pfd->events = 0;
|
||||
pfd->fd = ev->ev_fd;
|
||||
pop->event_w_back[i] = pop->event_r_back[i] = NULL;
|
||||
pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
|
||||
}
|
||||
|
||||
pfd->revents = 0;
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
pfd->events |= POLLOUT;
|
||||
pop->event_w_back[i] = ev;
|
||||
}
|
||||
if (ev->ev_events & EV_READ) {
|
||||
pfd->events |= POLLIN;
|
||||
pop->event_r_back[i] = ev;
|
||||
}
|
||||
poll_check_ok(pop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -278,9 +307,51 @@ int
|
||||
poll_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
struct pollfd *pfd = NULL;
|
||||
int i;
|
||||
|
||||
if (!(ev->ev_events & EV_SIGNAL))
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_del(&pop->evsigmask, ev));
|
||||
|
||||
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
return (evsignal_del(&pop->evsigmask, ev));
|
||||
poll_check_ok(pop);
|
||||
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i < 0)
|
||||
return (-1);
|
||||
|
||||
/* Do we still want to read or write? */
|
||||
pfd = &pop->event_set[i];
|
||||
if (ev->ev_events & EV_READ) {
|
||||
pfd->events &= ~POLLIN;
|
||||
pop->event_r_back[i] = NULL;
|
||||
}
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
pfd->events &= ~POLLOUT;
|
||||
pop->event_w_back[i] = NULL;
|
||||
}
|
||||
poll_check_ok(pop);
|
||||
if (pfd->events)
|
||||
/* Another event cares about that fd. */
|
||||
return (0);
|
||||
|
||||
/* Okay, so we aren't interested in that fd anymore. */
|
||||
pop->idxplus1_by_fd[ev->ev_fd] = 0;
|
||||
|
||||
--pop->nfds;
|
||||
if (i != pop->nfds) {
|
||||
/*
|
||||
* Shift the last pollfd down into the now-unoccupied
|
||||
* position.
|
||||
*/
|
||||
memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
|
||||
sizeof(struct pollfd));
|
||||
pop->event_r_back[i] = pop->event_r_back[pop->nfds];
|
||||
pop->event_w_back[i] = pop->event_w_back[pop->nfds];
|
||||
pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
|
||||
}
|
||||
|
||||
poll_check_ok(pop);
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user