]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: fd: simplify the fd_*_{recv,send} functions using BTS/BTR
authorWilly Tarreau <w@1wt.eu>
Wed, 4 Sep 2019 11:22:50 +0000 (13:22 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Sep 2019 07:31:18 +0000 (09:31 +0200)
Now that we don't have to update FD_EV_POLLED_* at the same time as
FD_EV_ACTIVE_*, we don't need to use a CAS anymore, a bit-test-and-set
operation is enough. Doing so reduces the code size by a bit more than
1 kB. One function was special, fd_done_recv(), whose comments and doc
were inaccurate for the part related to the lack of polling.

include/proto/fd.h
include/types/fd.h

index 0b56bdccc4f8e86140f9481886476c4ce93109e0..b072b30445cd7e5bfadaa313d026d204fe02a0a1 100644 (file)
@@ -218,28 +218,18 @@ static inline int fd_active(const int fd)
 /* Disable processing recv events on fd <fd> */
 static inline void fd_stop_recv(int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if (!(old & FD_EV_ACTIVE_R))
-                       return;
-               new = old & ~FD_EV_ACTIVE_R;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
+       if (!(fdtab[fd].state & FD_EV_ACTIVE_R) ||
+           !HA_ATOMIC_BTR(&fdtab[fd].state, FD_EV_ACTIVE_R_BIT))
+               return;
        updt_fd_polling(fd);
 }
 
 /* Disable processing send events on fd <fd> */
 static inline void fd_stop_send(int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if (!(old & FD_EV_ACTIVE_W))
-                       return;
-               new = old & ~FD_EV_ACTIVE_W;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
+       if (!(fdtab[fd].state & FD_EV_ACTIVE_W) ||
+           !HA_ATOMIC_BTR(&fdtab[fd].state, FD_EV_ACTIVE_W_BIT))
+               return;
        updt_fd_polling(fd);
 }
 
@@ -260,14 +250,10 @@ static inline void fd_stop_both(int fd)
 /* Report that FD <fd> cannot receive anymore without polling (EAGAIN detected). */
 static inline void fd_cant_recv(const int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if (!(old & FD_EV_READY_R))
-                       return;
-               new = old & ~FD_EV_READY_R;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
+       /* marking ready never changes polled status */
+       if (!(fdtab[fd].state & FD_EV_READY_R) ||
+           !HA_ATOMIC_BTR(&fdtab[fd].state, FD_EV_READY_R_BIT))
+               return;
 }
 
 /* Report that FD <fd> may receive again without polling. */
@@ -279,35 +265,26 @@ static inline void fd_may_recv(const int fd)
                return;
 }
 
-/* Disable readiness when polled. This is useful to interrupt reading when it
+/* Disable readiness when active. This is useful to interrupt reading when it
  * is suspected that the end of data might have been reached (eg: short read).
  * This can only be done using level-triggered pollers, so if any edge-triggered
  * is ever implemented, a test will have to be added here.
  */
 static inline void fd_done_recv(const int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if ((old & (FD_EV_ACTIVE_R|FD_EV_READY_R)) != (FD_EV_ACTIVE_R|FD_EV_READY_R))
-                       return;
-               new = old & ~FD_EV_READY_R;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
-       updt_fd_polling(fd);
+       /* removing ready never changes polled status */
+       if ((fdtab[fd].state & (FD_EV_ACTIVE_R|FD_EV_READY_R)) != (FD_EV_ACTIVE_R|FD_EV_READY_R) ||
+           !HA_ATOMIC_BTR(&fdtab[fd].state, FD_EV_READY_R_BIT))
+               return;
 }
 
 /* Report that FD <fd> cannot send anymore without polling (EAGAIN detected). */
 static inline void fd_cant_send(const int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if (!(old & FD_EV_READY_W))
-                       return;
-               new = old & ~FD_EV_READY_W;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
+       /* removing ready never changes polled status */
+       if (!(fdtab[fd].state & FD_EV_READY_W) ||
+           !HA_ATOMIC_BTR(&fdtab[fd].state, FD_EV_READY_W_BIT))
+               return;
 }
 
 /* Report that FD <fd> may send again without polling (EAGAIN not detected). */
@@ -322,28 +299,18 @@ static inline void fd_may_send(const int fd)
 /* Prepare FD <fd> to try to receive */
 static inline void fd_want_recv(int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if (old & FD_EV_ACTIVE_R)
-                       return;
-               new = old | FD_EV_ACTIVE_R;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
+       if ((fdtab[fd].state & FD_EV_ACTIVE_R) ||
+           HA_ATOMIC_BTS(&fdtab[fd].state, FD_EV_ACTIVE_R_BIT))
+               return;
        updt_fd_polling(fd);
 }
 
 /* Prepare FD <fd> to try to send */
 static inline void fd_want_send(int fd)
 {
-       unsigned char old, new;
-
-       old = fdtab[fd].state;
-       do {
-               if (old & FD_EV_ACTIVE_W)
-                       return;
-               new = old | FD_EV_ACTIVE_W;
-       } while (unlikely(!_HA_ATOMIC_CAS(&fdtab[fd].state, &old, new)));
+       if ((fdtab[fd].state & FD_EV_ACTIVE_W) ||
+           HA_ATOMIC_BTS(&fdtab[fd].state, FD_EV_ACTIVE_W_BIT))
+               return;
        updt_fd_polling(fd);
 }
 
index 6794d742df39470eb0d00050660d1b35b4091169..28f0c52e333b3b1b720bb3356b84bd44d017add3 100644 (file)
@@ -52,7 +52,10 @@ enum {
 #define FD_EV_READY     2U
 
 /* bits positions for a few flags */
+#define FD_EV_ACTIVE_R_BIT 0
 #define FD_EV_READY_R_BIT 1
+
+#define FD_EV_ACTIVE_W_BIT 4
 #define FD_EV_READY_W_BIT 5
 
 #define FD_EV_STATUS    (FD_EV_ACTIVE | FD_EV_READY)