]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CLEANUP: polling: gcc doesn't always optimize constants away
authorWilly Tarreau <w@1wt.eu>
Thu, 13 Dec 2012 21:26:37 +0000 (22:26 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 13 Dec 2012 21:30:17 +0000 (22:30 +0100)
In ev_poll and ev_epoll, we have a bit-to-bit mapping between the POLL_
constants and the FD_POLL_ constants. A comment said that gcc was able
to detect this and to automatically apply a mask. Things have possibly
changed since the output assembly doesn't always reflect this. So let's
perform an explicit assignment when bits are equal.

src/ev_epoll.c
src/ev_poll.c

index 2cd596aa39f374c4a0e90d1d8b03da77f9bf4265..8b0d684d6f19902cf32d6ba8ff31939d51e3e962 100644 (file)
@@ -144,15 +144,22 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                        continue;
 
                /* it looks complicated but gcc can optimize it away when constants
-                * have same values.
+                * have same values... In fact it depends on gcc :-(
                 */
                fdtab[fd].ev &= FD_POLL_STICKY;
-               fdtab[fd].ev |=
-                       ((e & EPOLLIN ) ? FD_POLL_IN  : 0) |
-                       ((e & EPOLLPRI) ? FD_POLL_PRI : 0) |
-                       ((e & EPOLLOUT) ? FD_POLL_OUT : 0) |
-                       ((e & EPOLLERR) ? FD_POLL_ERR : 0) |
-                       ((e & EPOLLHUP) ? FD_POLL_HUP : 0);
+               if (EPOLLIN == FD_POLL_IN && EPOLLOUT == FD_POLL_OUT &&
+                   EPOLLPRI == FD_POLL_PRI && EPOLLERR == FD_POLL_ERR &&
+                   EPOLLHUP == FD_POLL_HUP) {
+                       fdtab[fd].ev |= e & (EPOLLIN|EPOLLOUT|EPOLLPRI|EPOLLERR|EPOLLHUP);
+               }
+               else {
+                       fdtab[fd].ev |=
+                               ((e & EPOLLIN ) ? FD_POLL_IN  : 0) |
+                               ((e & EPOLLPRI) ? FD_POLL_PRI : 0) |
+                               ((e & EPOLLOUT) ? FD_POLL_OUT : 0) |
+                               ((e & EPOLLERR) ? FD_POLL_ERR : 0) |
+                               ((e & EPOLLHUP) ? FD_POLL_HUP : 0);
+               }
 
                if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev) {
                        int new_updt, old_updt = fd_nbupdt; /* Save number of updates to detect creation of new FDs. */
index cdc357fbeaa9b7934967447e533fbe76bfa45225..2c7501d9ddc8447e155d3478d7d32345dabafae2 100644 (file)
@@ -154,12 +154,21 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                if (!fdtab[fd].owner)
                        continue;
 
+               /* it looks complicated but gcc can optimize it away when constants
+                * have same values... In fact it depends on gcc :-(
+                */
                fdtab[fd].ev &= FD_POLL_STICKY;
-               fdtab[fd].ev |=
-                       ((e & POLLIN ) ? FD_POLL_IN  : 0) |
-                       ((e & POLLOUT) ? FD_POLL_OUT : 0) |
-                       ((e & POLLERR) ? FD_POLL_ERR : 0) |
-                       ((e & POLLHUP) ? FD_POLL_HUP : 0);
+               if (POLLIN == FD_POLL_IN && POLLOUT == FD_POLL_OUT &&
+                   POLLERR == FD_POLL_ERR && POLLHUP == FD_POLL_HUP) {
+                       fdtab[fd].ev |= e & (POLLIN|POLLOUT|POLLERR|POLLHUP);
+               }
+               else {
+                       fdtab[fd].ev |=
+                               ((e & POLLIN ) ? FD_POLL_IN  : 0) |
+                               ((e & POLLOUT) ? FD_POLL_OUT : 0) |
+                               ((e & POLLERR) ? FD_POLL_ERR : 0) |
+                               ((e & POLLHUP) ? FD_POLL_HUP : 0);
+               }
 
                if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev) {
                        /* Mark the events as speculative before processing