]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: poll: don't use the old FD state anymore
authorWilly Tarreau <w@1wt.eu>
Thu, 25 Jan 2018 16:11:33 +0000 (17:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 29 Jan 2018 15:03:15 +0000 (16:03 +0100)
The polling updates are now performed exactly like the epoll/kqueue
ones : only the new polled state is considered, and the previous one
is checked using polled_mask. The only specific stuff here is that
the fd state is shared between all threads, so an FD removal has to
be done only once.

src/ev_poll.c

index 69c9a648cf38a19f50f5a447198c30f06517b1c6..1ab345a6a47a2d6df740f159529225550023f568 100644 (file)
@@ -77,23 +77,35 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
                fdtab[fd].state = en;
                HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
 
-               if ((eo ^ en) & FD_EV_POLLED_RW) {
-                       /* poll status changed, update the lists */
-                       if ((eo & ~en) & FD_EV_POLLED_R)
+               /* we have a single state for all threads, which is why we
+                * don't check the tid_bit. First thread to see the update
+                * takes it for every other one.
+                */
+               if (!(en & FD_EV_POLLED_RW)) {
+                       if (!fdtab[fd].polled_mask) {
+                               /* fd was not watched, it's still not */
+                               continue;
+                       }
+                       /* fd totally removed from poll list */
+                       hap_fd_clr(fd, fd_evts[DIR_RD]);
+                       hap_fd_clr(fd, fd_evts[DIR_WR]);
+                       HA_ATOMIC_AND(&fdtab[fd].polled_mask, 0);
+               }
+               else {
+                       /* OK fd has to be monitored, it was either added or changed */
+                       if (!(en & FD_EV_POLLED_R))
                                hap_fd_clr(fd, fd_evts[DIR_RD]);
-                       else if ((en & ~eo) & FD_EV_POLLED_R) {
+                       else
                                hap_fd_set(fd, fd_evts[DIR_RD]);
-                               if (fd > max_add_fd)
-                                       max_add_fd = fd;
-                       }
 
-                       if ((eo & ~en) & FD_EV_POLLED_W)
+                       if (!(en & FD_EV_POLLED_W))
                                hap_fd_clr(fd, fd_evts[DIR_WR]);
-                       else if ((en & ~eo) & FD_EV_POLLED_W) {
+                       else
                                hap_fd_set(fd, fd_evts[DIR_WR]);
-                               if (fd > max_add_fd)
-                                       max_add_fd = fd;
-                       }
+
+                       HA_ATOMIC_OR(&fdtab[fd].polled_mask, tid_bit);
+                       if (fd > max_add_fd)
+                               max_add_fd = fd;
                }
        }