Activate fd events in a pseudorandom order on older backends.

New backends like poll and kqueue and so on add fds to the queue in
the order that they are triggered.  But the select backend currently
activates low-numbered fds first, whereas the poll and win32 backends
currently favor whatever fds have been on for the longest.  This is no
good for fairness.

svn:r1318
This commit is contained in:
Nick Mathewson 2009-05-27 15:35:00 +00:00
parent 11a178f2bd
commit cdaca02c29
4 changed files with 40 additions and 17 deletions

View File

@ -33,6 +33,7 @@ Changes in 2.0.2-alpha:
o Fix a deadlock when suspending reads in a bufferevent due to a full buffer. (Spotted by Joachim Bauch.) o Fix a deadlock when suspending reads in a bufferevent due to a full buffer. (Spotted by Joachim Bauch.)
o Fix a memory error when freeing a thread-enabled event base with registered events. (Spotted by Joachim Bauch.) o Fix a memory error when freeing a thread-enabled event base with registered events. (Spotted by Joachim Bauch.)
o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair. o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair.
o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32).
Changes in 2.0.1-alpha: Changes in 2.0.1-alpha:

View File

@ -282,8 +282,9 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
{ {
struct win32op *win32op = base->evbase; struct win32op *win32op = base->evbase;
int res = 0; int res = 0;
unsigned i; unsigned j, i;
int fd_count; int fd_count;
SOCKET s;
fd_set_copy(win32op->readset_out, win32op->readset_in); fd_set_copy(win32op->readset_out, win32op->readset_in);
fd_set_copy(win32op->exset_out, win32op->readset_in); fd_set_copy(win32op->exset_out, win32op->readset_in);
@ -314,19 +315,33 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
evsig_process(base); evsig_process(base);
} }
for (i=0; i<win32op->readset_out->fd_count; ++i) { if (win32op->readset_out->fd_count) {
SOCKET s = win32op->readset_out->fd_array[i]; i = rand() % win32op->readset_out->fd_count;
for (j=0; j<win32op->readset_out->fd_count; ++j) {
if (++i >= win32op->readset_out->fd_count)
i = 0;
s = win32op->readset_out->fd_array[i];
evmap_io_active(base, s, EV_READ); evmap_io_active(base, s, EV_READ);
} }
for (i=0; i<win32op->exset_out->fd_count; ++i) { }
SOCKET s = win32op->exset_out->fd_array[i]; if (win32op->exset_out->fd_count) {
i = rand() % win32op->exset_out->fd_count;
for (j=0; j<win32op->exset_out->fd_count; ++j) {
if (++i >= win32op-exset_out->fd_count)
i = 0;
s = win32op->exset_out->fd_array[i];
evmap_io_active(base, s, EV_READ); evmap_io_active(base, s, EV_READ);
} }
for (i=0; i<win32op->writeset_out->fd_count; ++i) { }
if (win32op->writeset_out->fd_count) {
i = rand() % win32op->writeset_out->fd_count;
for (j=0; j<win32op->writeset_out->fd_count; ++j) {
if (++i >= win32op-exset_out->fd_count)
i = 0;
SOCKET s = win32op->writeset_out->fd_array[i]; SOCKET s = win32op->writeset_out->fd_array[i];
evmap_io_active(base, s, EV_WRITE); evmap_io_active(base, s, EV_WRITE);
} }
}
return (0); return (0);
} }

12
poll.c
View File

@ -117,7 +117,7 @@ poll_check_ok(struct pollop *pop)
static int static int
poll_dispatch(struct event_base *base, struct timeval *tv) poll_dispatch(struct event_base *base, struct timeval *tv)
{ {
int res, i, msec = -1, nfds; int res, i, j, msec = -1, nfds;
struct pollop *pop = base->evbase; struct pollop *pop = base->evbase;
poll_check_ok(pop); poll_check_ok(pop);
@ -142,11 +142,15 @@ poll_dispatch(struct event_base *base, struct timeval *tv)
event_debug(("%s: poll reports %d", __func__, res)); event_debug(("%s: poll reports %d", __func__, res));
if (res == 0) if (res == 0 || nfds == 0)
return (0); return (0);
for (i = 0; i < nfds; i++) { i = random() % nfds;
int what = pop->event_set[i].revents; for (j = 0; j < nfds; j++) {
int what;
if (++i == nfds)
i = 0;
what = pop->event_set[i].revents;
if (!what) if (!what)
continue; continue;

View File

@ -114,7 +114,7 @@ check_selectop(struct selectop *sop)
static int static int
select_dispatch(struct event_base *base, struct timeval *tv) select_dispatch(struct event_base *base, struct timeval *tv)
{ {
int res, i; int res, i, j;
struct selectop *sop = base->evbase; struct selectop *sop = base->evbase;
check_selectop(sop); check_selectop(sop);
@ -144,7 +144,10 @@ select_dispatch(struct event_base *base, struct timeval *tv)
event_debug(("%s: select reports %d", __func__, res)); event_debug(("%s: select reports %d", __func__, res));
check_selectop(sop); check_selectop(sop);
for (i = 0; i <= sop->event_fds; ++i) { i = random() % (sop->event_fds+1);
for (j = 0; j <= sop->event_fds; ++j) {
if (++i >= sop->event_fds+1)
i = 0;
res = 0; res = 0;
if (FD_ISSET(i, sop->event_readset_out)) if (FD_ISSET(i, sop->event_readset_out))
res |= EV_READ; res |= EV_READ;