From: Willy Tarreau Date: Sun, 11 Nov 2012 15:53:50 +0000 (+0100) Subject: MAJOR: ev_select: make the poller support speculative events X-Git-Tag: v1.5-dev13~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4d31fb2643cc10602b859309eb7913ee3fb33f2a;p=thirdparty%2Fhaproxy.git MAJOR: ev_select: make the poller support speculative events The poller was updated to support speculative events. We'll need this to fully support SSL. --- diff --git a/src/ev_select.c b/src/ev_select.c index 100bc57565..a4fe3d7398 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -1,7 +1,7 @@ /* * FD polling functions for generic select() * - * Copyright 2000-2008 Willy Tarreau + * Copyright 2000-2012 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,28 +29,8 @@ static fd_set *fd_evts[2]; static fd_set *tmp_evts[2]; - -/* - * Benchmarks performed on a Pentium-M notebook show that using functions - * instead of the usual macros improve the FD_* performance by about 80%, - * and that marking them regparm(2) adds another 20%. - */ -REGPRM2 static int __fd_is_set(const int fd, int dir) -{ - return FD_ISSET(fd, fd_evts[dir]); -} - -REGPRM2 static void __fd_set(const int fd, int dir) -{ - FD_SET(fd, fd_evts[dir]); -} - -REGPRM2 static void __fd_clr(const int fd, int dir) -{ - FD_CLR(fd, fd_evts[dir]); -} - -REGPRM1 static void __fd_rem(int fd) +/* Immediately remove the entry upon close() */ +REGPRM1 static void __fd_clo(int fd) { FD_CLR(fd, fd_evts[DIR_RD]); FD_CLR(fd, fd_evts[DIR_WR]); @@ -67,13 +47,53 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) int delta_ms; int readnotnull, writenotnull; int fds; + int updt_idx, en, eo; char count; + /* first, scan the update list to find changes */ + for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) { + fd = fd_updt[updt_idx]; + en = fdtab[fd].spec_e & 15; /* new events */ + eo = fdtab[fd].spec_e >> 4; /* previous events */ + + if (fdtab[fd].owner && (eo ^ en)) { + if ((eo ^ en) & FD_EV_POLLED_RW) { + /* poll status changed, update the lists */ + if ((eo & ~en) & FD_EV_POLLED_R) + FD_CLR(fd, fd_evts[DIR_RD]); + else if ((en & ~eo) & FD_EV_POLLED_R) + FD_SET(fd, fd_evts[DIR_RD]); + + if ((eo & ~en) & FD_EV_POLLED_W) + FD_CLR(fd, fd_evts[DIR_WR]); + else if ((en & ~eo) & FD_EV_POLLED_W) + FD_SET(fd, fd_evts[DIR_WR]); + } + + fdtab[fd].spec_e = (en << 4) + en; /* save new events */ + + if (!(en & FD_EV_ACTIVE_RW)) { + /* This fd doesn't use any active entry anymore, we can + * kill its entry. + */ + release_spec_entry(fd); + } + else if ((en & ~eo) & FD_EV_ACTIVE_RW) { + /* we need a new spec entry now */ + alloc_spec_entry(fd); + } + + } + fdtab[fd].updated = 0; + fdtab[fd].new = 0; + } + fd_nbupdt = 0; + delta_ms = 0; delta.tv_sec = 0; delta.tv_usec = 0; - if (!run_queue && !signal_queue_len) { + if (!fd_nbspec && !run_queue && !signal_queue_len) { if (!exp) { delta_ms = MAX_DELAY_MS; delta.tv_sec = (MAX_DELAY_MS / 1000); @@ -136,8 +156,19 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) if (FD_ISSET(fd, tmp_evts[DIR_WR])) fdtab[fd].ev |= FD_POLL_OUT; - if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev) + if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev) { + /* Mark the events as speculative before processing + * them so that if nothing can be done we don't need + * to poll again. + */ + if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR)) + fd_ev_set(fd, DIR_RD); + + if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR)) + fd_ev_set(fd, DIR_WR); + fdtab[fd].iocb(fd); + } } } } @@ -225,11 +256,12 @@ static void _do_register(void) p->init = _do_init; p->term = _do_term; p->poll = _do_poll; - p->is_set = __fd_is_set; - p->set = __fd_set; - p->wai = __fd_set; - p->clr = __fd_clr; - p->clo = p->rem = __fd_rem; + p->is_set = NULL; + p->set = NULL; + p->wai = NULL; + p->clr = NULL; + p->rem = NULL; + p->clo = __fd_clo; }