From d9185dbab66e8ea3bafd1d43660ae44311da7a81 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 31 Mar 2013 14:06:57 +0200 Subject: [PATCH 39/42] MEDIUM: poll: do not use FD_* macros anymore Some recent glibc updates have added controls on FD_SET/FD_CLR/FD_ISSET that crash the program if it tries to use a file descriptor larger than FD_SETSIZE. Do not rely on FD_* macros anymore and replace them with bit fields. (cherry picked from commit 80da05a4cfb881663dc1f38a94d613f37e54552a) --- src/ev_poll.c | 87 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/src/ev_poll.c b/src/ev_poll.c index f5d011e..02e89ad 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -27,12 +27,25 @@ #include -static fd_set *fd_evts[2]; +static unsigned int *fd_evts[2]; /* private data */ static struct pollfd *poll_events = NULL; +static inline unsigned int hap_fd_isset(int fd, unsigned int *evts) +{ + return evts[fd / (8*sizeof(*evts))] & (1U << (fd & (8*sizeof(*evts) - 1))); +} + +static inline void hap_fd_set(int fd, unsigned int *evts) +{ + evts[fd / (8*sizeof(*evts))] |= 1U << (fd & (8*sizeof(*evts) - 1)); +} +static inline void hap_fd_clr(int fd, unsigned int *evts) +{ + evts[fd / (8*sizeof(*evts))] &= ~(1U << (fd & (8*sizeof(*evts) - 1))); +} /* * Benchmarks performed on a Pentium-M notebook show that using functions * instead of the usual macros improve the FD_* performance by about 80%, @@ -40,43 +53,43 @@ static struct pollfd *poll_events = NULL; */ REGPRM2 static int __fd_is_set(const int fd, int dir) { - return FD_ISSET(fd, fd_evts[dir]); + return hap_fd_isset(fd, fd_evts[dir]); } REGPRM2 static int __fd_set(const int fd, int dir) { - FD_SET(fd, fd_evts[dir]); + hap_fd_set(fd, fd_evts[dir]); return 0; } REGPRM2 static int __fd_clr(const int fd, int dir) { - FD_CLR(fd, fd_evts[dir]); + hap_fd_clr(fd, fd_evts[dir]); return 0; } REGPRM2 static int __fd_cond_s(const int fd, int dir) { int ret; - ret = !FD_ISSET(fd, fd_evts[dir]); + ret = !hap_fd_isset(fd, fd_evts[dir]); if (ret) - FD_SET(fd, fd_evts[dir]); + hap_fd_set(fd, fd_evts[dir]); return ret; } REGPRM2 static int __fd_cond_c(const int fd, int dir) { int ret; - ret = FD_ISSET(fd, fd_evts[dir]); + ret = hap_fd_isset(fd, fd_evts[dir]); if (ret) - FD_CLR(fd, fd_evts[dir]); + hap_fd_clr(fd, fd_evts[dir]); return ret; } REGPRM1 static void __fd_rem(const int fd) { - FD_CLR(fd, fd_evts[DIR_RD]); - FD_CLR(fd, fd_evts[DIR_WR]); + hap_fd_clr(fd, fd_evts[DIR_RD]); + hap_fd_clr(fd, fd_evts[DIR_WR]); } /* @@ -93,33 +106,20 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) unsigned rn, wn; /* read new, write new */ nbfd = 0; - for (fds = 0; (fds * BITS_PER_INT) < maxfd; fds++) { - - rn = ((int*)fd_evts[DIR_RD])[fds]; - wn = ((int*)fd_evts[DIR_WR])[fds]; + for (fds = 0; (fds * 8*sizeof(**fd_evts)) < maxfd; fds++) { + rn = fd_evts[DIR_RD][fds]; + wn = fd_evts[DIR_WR][fds]; - if ((rn|wn)) { - for (count = 0, fd = fds * BITS_PER_INT; count < BITS_PER_INT && fd < maxfd; count++, fd++) { -#define FDSETS_ARE_INT_ALIGNED -#ifdef FDSETS_ARE_INT_ALIGNED - -#define WE_REALLY_KNOW_THAT_FDSETS_ARE_INTS -#ifdef WE_REALLY_KNOW_THAT_FDSETS_ARE_INTS - sr = (rn >> count) & 1; - sw = (wn >> count) & 1; -#else - sr = FD_ISSET(fd&(BITS_PER_INT-1), (typeof(fd_set*))&rn); - sw = FD_ISSET(fd&(BITS_PER_INT-1), (typeof(fd_set*))&wn); -#endif -#else - sr = FD_ISSET(fd, fd_evts[DIR_RD]); - sw = FD_ISSET(fd, fd_evts[DIR_WR]); -#endif - if ((sr|sw)) { - poll_events[nbfd].fd = fd; - poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0); - nbfd++; - } + if (!(rn|wn)) + continue; + + for (count = 0, fd = fds * 8*sizeof(**fd_evts); count < 8*sizeof(**fd_evts) && fd < maxfd; count++, fd++) { + sr = (rn >> count) & 1; + sw = (wn >> count) & 1; + if ((sr|sw)) { + poll_events[nbfd].fd = fd; + poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0); + nbfd++; } } } @@ -149,14 +149,14 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) /* ok, we found one active fd */ status--; - if (FD_ISSET(fd, fd_evts[DIR_RD])) { + if (hap_fd_isset(fd, fd_evts[DIR_RD])) { if (fdtab[fd].state == FD_STCLOSE) continue; if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP )) fdtab[fd].cb[DIR_RD].f(fd); } - if (FD_ISSET(fd, fd_evts[DIR_WR])) { + if (hap_fd_isset(fd, fd_evts[DIR_WR])) { if (fdtab[fd].state == FD_STCLOSE) continue; if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP )) @@ -174,21 +174,20 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) REGPRM1 static int _do_init(struct poller *p) { __label__ fail_swevt, fail_srevt, fail_pe; - int fd_set_bytes; + int fd_evts_bytes; p->private = NULL; - fd_set_bytes = sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE; + fd_evts_bytes = (global.maxsock + sizeof(**fd_evts) - 1) / sizeof(**fd_evts) * sizeof(**fd_evts); - poll_events = (struct pollfd*) - calloc(1, sizeof(struct pollfd) * global.maxsock); + poll_events = calloc(1, sizeof(struct pollfd) * global.maxsock); if (poll_events == NULL) goto fail_pe; - if ((fd_evts[DIR_RD] = (fd_set *)calloc(1, fd_set_bytes)) == NULL) + if ((fd_evts[DIR_RD] = calloc(1, fd_evts_bytes)) == NULL) goto fail_srevt; - if ((fd_evts[DIR_WR] = (fd_set *)calloc(1, fd_set_bytes)) == NULL) + if ((fd_evts[DIR_WR] = calloc(1, fd_evts_bytes)) == NULL) goto fail_swevt; return 1; -- 1.8.1.5