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);
}