]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore
authorWilly Tarreau <w@1wt.eu>
Fri, 6 Sep 2019 17:05:50 +0000 (19:05 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 6 Sep 2019 17:09:56 +0000 (19:09 +0200)
As mentioned in previous commit, these flags do not map well to
modern poller capabilities. Let's use the FD_EV_*_{R,W} flags instead.
This first patch only performs a 1-to-1 mapping making sure that the
previously reported flags are still reported identically while using
the closest possible semantics in the pollers.

It's worth noting that kqueue will now support improvements such as
returning distinctions between shut and errors on each direction,
though this is not exploited for now.

include/proto/fd.h
src/ev_epoll.c
src/ev_evports.c
src/ev_kqueue.c
src/ev_poll.c
src/ev_select.c

index e3b0b2b2f74f4d1e913231be23a77eb55676a602..3ee71a5a17a859e82a2278d39a4f7e3e265033a9 100644 (file)
@@ -318,20 +318,32 @@ static inline void fd_want_send(int fd)
        updt_fd_polling(fd);
 }
 
-/* Update events seen for FD <fd> and its state if needed. This should be called
- * by the poller to set FD_POLL_* flags. */
-static inline void fd_update_events(int fd, int evts)
+/* Update events seen for FD <fd> and its state if needed. This should be
+ * called by the poller, passing FD_EV_*_{R,W,RW} in <evts>. FD_EV_ERR_*
+ * doesn't need to also pass FD_EV_SHUT_*, it's implied. ERR and SHUT are
+ * allowed to be reported regardless of R/W readiness.
+ */
+static inline void fd_update_events(int fd, unsigned char evts)
 {
        unsigned long locked = atleast2(fdtab[fd].thread_mask);
        unsigned char old, new;
+       int new_flags;
+
+       new_flags =
+             ((evts & FD_EV_READY_R) ? FD_POLL_IN  : 0) |
+             ((evts & FD_EV_READY_W) ? FD_POLL_OUT : 0) |
+             ((evts & FD_EV_SHUT_R)  ? FD_POLL_HUP : 0) |
+             ((evts & FD_EV_SHUT_W)  ? FD_POLL_ERR : 0) |
+             ((evts & FD_EV_ERR_R)   ? FD_POLL_ERR : 0) |
+             ((evts & FD_EV_ERR_W)   ? FD_POLL_ERR : 0);
 
        old = fdtab[fd].ev;
-       new = (old & FD_POLL_STICKY) | evts;
+       new = (old & FD_POLL_STICKY) | new_flags;
 
        if (unlikely(locked)) {
                /* Locked FDs (those with more than 2 threads) are atomically updated */
                while (unlikely(new != old && !_HA_ATOMIC_CAS(&fdtab[fd].ev, &old, new)))
-                       new = (old & FD_POLL_STICKY) | evts;
+                       new = (old & FD_POLL_STICKY) | new_flags;
        } else {
                if (new != old)
                        fdtab[fd].ev = new;
index 5172aecec6539cfbc1a71ba88f571fbd3b24b5a4..dc156e58f8d6e37e23678070c624f232d7870db8 100644 (file)
@@ -218,27 +218,15 @@ REGPRM3 static void _do_poll(struct poller *p, int exp, int wake)
                        continue;
                }
 
-               /* it looks complicated but gcc can optimize it away when constants
-                * have same values... In fact it depends on gcc :-(
-                */
-               if (EPOLLIN == FD_POLL_IN && EPOLLOUT == FD_POLL_OUT &&
-                   EPOLLPRI == FD_POLL_PRI && EPOLLERR == FD_POLL_ERR &&
-                   EPOLLHUP == FD_POLL_HUP) {
-                       n = e & (EPOLLIN|EPOLLOUT|EPOLLPRI|EPOLLERR|EPOLLHUP);
-               }
-               else {
-                       n =     ((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);
-               }
+               n = ((e & EPOLLIN)    ? FD_EV_READY_R : 0) |
+                   ((e & EPOLLOUT)   ? FD_EV_READY_W : 0) |
+                   ((e & EPOLLRDHUP) ? FD_EV_SHUT_R  : 0) |
+                   ((e & EPOLLHUP)   ? FD_EV_SHUT_RW : 0) |
+                   ((e & EPOLLERR)   ? FD_EV_ERR_RW  : 0);
 
-               /* always remap RDHUP to HUP as they're used similarly */
-               if (e & EPOLLRDHUP) {
+               if ((e & EPOLLRDHUP) && !(cur_poller.flags & HAP_POLL_F_RDHUP))
                        _HA_ATOMIC_OR(&cur_poller.flags, HAP_POLL_F_RDHUP);
-                       n |= FD_POLL_HUP;
-               }
+
                fd_update_events(fd, n);
        }
        /* the caller will take care of cached events */
index 46edb6962118d5dfef17506e24b1ec062ef8b844..e734b220ed401352845dac364c91c50eb3e49d18 100644 (file)
@@ -241,14 +241,10 @@ REGPRM3 static void _do_poll(struct poller *p, int exp, int wake)
                /*
                 * Set bits based on the events we received from the port:
                 */
-               if (events & POLLIN)
-                       n |= FD_POLL_IN;
-               if (events & POLLOUT)
-                       n |= FD_POLL_OUT;
-               if (events & POLLERR)
-                       n |= FD_POLL_ERR;
-               if (events & POLLHUP)
-                       n |= FD_POLL_HUP;
+               n = ((e & POLLIN)    ? FD_EV_READY_R : 0) |
+                   ((e & POLLOUT)   ? FD_EV_READY_W : 0) |
+                   ((e & POLLHUP)   ? FD_EV_SHUT_RW : 0) |
+                   ((e & POLLERR)   ? FD_EV_ERR_RW  : 0);
 
                /*
                 * Call connection processing callbacks.  Note that it's
index 191ddce568527ddbf808ea4f21ec5d024b045d78..8f0b7c90725206339f76a16b7de54ef0f81b7157 100644 (file)
@@ -196,16 +196,16 @@ REGPRM3 static void _do_poll(struct poller *p, int exp, int wake)
                        continue;
                }
 
-               if (kev[count].filter ==  EVFILT_READ) {
+               if (kev[count].filter == EVFILT_READ) {
                        if (kev[count].data)
-                               n |= FD_POLL_IN;
+                               n |= FD_EV_READY_R;
                        if (kev[count].flags & EV_EOF)
-                               n |= FD_POLL_HUP;
+                               n |= FD_EV_SHUT_R;
                }
-               else if (kev[count].filter ==  EVFILT_WRITE) {
-                       n |= FD_POLL_OUT;
+               else if (kev[count].filter == EVFILT_WRITE) {
+                       n |= FD_EV_READY_W;
                        if (kev[count].flags & EV_EOF)
-                               n |= FD_POLL_ERR;
+                               n |= FD_EV_ERR_RW;
                }
 
                fd_update_events(fd, n);
index 6c5de9bea7f713ef4e4a44754ab446821cc51436..7655ca5590e84aae74042acd256fd17a1cee3140 100644 (file)
@@ -231,25 +231,15 @@ REGPRM3 static void _do_poll(struct poller *p, int exp, int wake)
                        continue;
                }
 
-               /* it looks complicated but gcc can optimize it away when constants
-                * have same values... In fact it depends on gcc :-(
-                */
-               if (POLLIN == FD_POLL_IN && POLLOUT == FD_POLL_OUT &&
-                   POLLERR == FD_POLL_ERR && POLLHUP == FD_POLL_HUP) {
-                       n = e & (POLLIN|POLLOUT|POLLERR|POLLHUP);
-               }
-               else {
-                       n =     ((e & POLLIN ) ? FD_POLL_IN  : 0) |
-                               ((e & POLLOUT) ? FD_POLL_OUT : 0) |
-                               ((e & POLLERR) ? FD_POLL_ERR : 0) |
-                               ((e & POLLHUP) ? FD_POLL_HUP : 0);
-               }
+               n = ((e & POLLIN)    ? FD_EV_READY_R : 0) |
+                   ((e & POLLOUT)   ? FD_EV_READY_W : 0) |
+                   ((e & POLLRDHUP) ? FD_EV_SHUT_R  : 0) |
+                   ((e & POLLHUP)   ? FD_EV_SHUT_RW : 0) |
+                   ((e & POLLERR)   ? FD_EV_ERR_RW  : 0);
 
-               /* always remap RDHUP to HUP as they're used similarly */
-               if (e & POLLRDHUP) {
+               if ((e & POLLRDHUP) && !(cur_poller.flags & HAP_POLL_F_RDHUP))
                        _HA_ATOMIC_OR(&cur_poller.flags, HAP_POLL_F_RDHUP);
-                       n |= FD_POLL_HUP;
-               }
+
                fd_update_events(fd, n);
        }
 
index 7ee915ea5adfac4323eef6c13290b37a2294a07a..dc66e71276c10b31b0d36e8cab226029ab6e5758 100644 (file)
@@ -210,10 +210,10 @@ REGPRM3 static void _do_poll(struct poller *p, int exp, int wake)
                        }
 
                        if (FD_ISSET(fd, tmp_evts[DIR_RD]))
-                               n |= FD_POLL_IN;
+                               n |= FD_EV_READY_R;
 
                        if (FD_ISSET(fd, tmp_evts[DIR_WR]))
-                               n |= FD_POLL_OUT;
+                               n |= FD_EV_READY_W;
 
                        fd_update_events(fd, n);
                }