MEDIUM: fd: simplify the fd_*_{recv,send} functions using BTS/BTR

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.
diff --git a/include/proto/fd.h b/include/proto/fd.h
index 0b56bdc..b072b30 100644
--- a/include/proto/fd.h
+++ b/include/proto/fd.h
@@ -218,28 +218,18 @@
 /* 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 @@
 /* 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 @@
 		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 @@
 /* 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);
 }
 
diff --git a/include/types/fd.h b/include/types/fd.h
index 6794d74..28f0c52 100644
--- a/include/types/fd.h
+++ b/include/types/fd.h
@@ -52,7 +52,10 @@
 #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)