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:r1327
This commit is contained in:
Nick Mathewson 2009-06-24 22:39:03 +00:00
parent b0d88e680b
commit b99254ac22
4 changed files with 46 additions and 28 deletions

View File

@ -2,6 +2,7 @@ Changes in 1.4.12-stable:
o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair.
o Fix an obscure timing-dependent, allocator-dependent crash in the evdns code.
o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC.
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).
o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.]
Changes in 1.4.11-stable:
@ -86,7 +87,6 @@ Changes in 1.4.4-stable:
o Fix autoconf script behavior on IRIX.
o Make sure winsock2.h include always comes before windows.h include.
Changes in 1.4.3-stable:
o include Content-Length in reply for HTTP/1.0 requests with keep-alive
o Patch from Tani Hosokawa: make some functions in http.c threadsafe.

View File

@ -352,8 +352,9 @@ win32_dispatch(struct event_base *base, void *op,
{
struct win32op *win32op = op;
int res = 0;
unsigned i;
unsigned j, i;
int fd_count;
SOCKET s;
fd_set_copy(win32op->readset_out, win32op->readset_in);
fd_set_copy(win32op->exset_out, win32op->readset_in);
@ -384,29 +385,37 @@ win32_dispatch(struct event_base *base, void *op,
evsignal_process(base);
}
for (i=0; i<win32op->readset_out->fd_count; ++i) {
struct event_entry *ent;
SOCKET s = win32op->readset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
event_active(ent->read_event, EV_READ, 1);
if (win32op->readset_out->fd_count) {
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];
if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
event_active(ent->read_event, EV_READ, 1);
}
}
for (i=0; i<win32op->exset_out->fd_count; ++i) {
struct event_entry *ent;
SOCKET s = win32op->exset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
event_active(ent->read_event, EV_READ, 1);
}
for (i=0; i<win32op->writeset_out->fd_count; ++i) {
struct event_entry *ent;
SOCKET s = win32op->writeset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->write_event)
event_active(ent->write_event, EV_WRITE, 1);
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];
if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
event_active(ent->read_event, EV_READ, 1);
}
}
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;
s = win32op->writeset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->write_event)
event_active(ent->write_event, EV_WRITE, 1);
#if 0
if (signal_recalc() == -1)
return (-1);
#endif
}
}
return (0);
}

13
poll.c
View File

@ -135,7 +135,7 @@ poll_check_ok(struct pollop *pop)
static int
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
{
int res, i, msec = -1, nfds;
int res, i, j, msec = -1, nfds;
struct pollop *pop = arg;
poll_check_ok(pop);
@ -160,12 +160,17 @@ poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
event_debug(("%s: poll reports %d", __func__, res));
if (res == 0)
if (res == 0 || nfds == 0)
return (0);
for (i = 0; i < nfds; i++) {
int what = pop->event_set[i].revents;
i = random() % nfds;
for (j = 0; j < nfds; j++) {
struct event *r_ev = NULL, *w_ev = NULL;
int what;
if (++i == nfds)
i = 0;
what = pop->event_set[i].revents;
if (!what)
continue;

View File

@ -137,7 +137,7 @@ check_selectop(struct selectop *sop)
static int
select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
{
int res, i;
int res, i, j;
struct selectop *sop = arg;
check_selectop(sop);
@ -167,8 +167,12 @@ select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
event_debug(("%s: select reports %d", __func__, res));
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) {
struct event *r_ev = NULL, *w_ev = NULL;
if (++i >= sop->event_fds+1)
i = 0;
res = 0;
if (FD_ISSET(i, sop->event_readset_out)) {
r_ev = sop->event_r_by_fd[i];