MEDIUM: pollers: Remember the state for read and write for each threads.

In the poller code, instead of just remembering if we're currently polling
a fd or not, remember if we're polling it for writing and/or for reading, that
way, we can avoid to modify the polling if it's already polled as needed.
diff --git a/src/ev_evports.c b/src/ev_evports.c
index 7842bf2..d9d1637 100644
--- a/src/ev_evports.c
+++ b/src/ev_evports.c
@@ -74,18 +74,36 @@
 	en = fdtab[fd].state;
 
 	if (!(fdtab[fd].thread_mask & tid_bit) || !(en & FD_EV_POLLED_RW)) {
-		if (!(polled_mask[fd] & tid_bit)) {
+		if (!(polled_mask[fd].poll_recv & tid_bit) &&
+		    !(polled_mask[fd].poll_send & tid_bit)) {
 			/* fd was not watched, it's still not */
 			return;
 		}
 		/* fd totally removed from poll list */
 		events = 0;
-		_HA_ATOMIC_AND(&polled_mask[fd], ~tid_bit);
+		if (polled_mask[fd].poll_recv & tid_bit)
+			_HA_ATOMIC_AND(&polled_mask[fd].poll_recv, ~tid_bit);
+		if (polled_mask[fd].poll_send & tid_bit)
+			_HA_ATOMIC_AND(&polled_mask[fd].poll_send, ~tid_bit);
 	}
 	else {
 		/* OK fd has to be monitored, it was either added or changed */
 		events = evports_state_to_events(en);
-		_HA_ATOMIC_OR(&polled_mask[fd], tid_bit);
+		if (en & FD_EV_POLLED_R) {
+			if (!(polled_mask[fd].poll_recv & tid_bit))
+				_HA_ATOMIC_OR(&polled_mask[fd].poll_recv, tid_bit);
+		} else {
+			if (polled_mask[fd].poll_recv & tid_bit)
+				_HA_ATOMIC_AND(&polled_mask[fd].poll_recv, ~tid_bit);
+		}
+		if (en & FD_EV_POLLED_W) {
+			if (!(polled_mask[fd].poll_send & tid_bit))
+				_HA_ATOMIC_OR(&polled_mask[fd].poll_send, tid_bit);
+		} else {
+			if (polled_mask[fd].poll_send & tid_bit)
+				_HA_ATOMIC_AND(&polled_mask[fd].poll_send, ~tid_bit);
+		}
+
 	}
 	evports_resync_fd(fd, events);
 }