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_epoll.c b/src/ev_epoll.c
index bd2d616..dd3a561 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -53,7 +53,7 @@
REGPRM1 static void __fd_clo(int fd)
{
if (unlikely(fdtab[fd].cloned)) {
- unsigned long m = polled_mask[fd];
+ unsigned long m = polled_mask[fd].poll_recv | polled_mask[fd].poll_send;
int i;
for (i = global.nbthread - 1; i >= 0; i--)
@@ -68,13 +68,35 @@
en = fdtab[fd].state;
- if (polled_mask[fd] & tid_bit) {
+ if ((polled_mask[fd].poll_send | polled_mask[fd].poll_recv) & tid_bit) {
if (!(fdtab[fd].thread_mask & tid_bit) || !(en & FD_EV_POLLED_RW)) {
/* fd removed from poll list */
opcode = EPOLL_CTL_DEL;
- _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 {
+ if (((en & FD_EV_POLLED_R) != 0) ==
+ ((polled_mask[fd].poll_recv & tid_bit) != 0) &&
+ ((en & FD_EV_POLLED_W) != 0) ==
+ ((polled_mask[fd].poll_send & tid_bit) != 0))
+ return;
+ 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);
+ }
/* fd status changed */
opcode = EPOLL_CTL_MOD;
}
@@ -82,7 +104,10 @@
else if ((fdtab[fd].thread_mask & tid_bit) && (en & FD_EV_POLLED_RW)) {
/* new fd in the poll list */
opcode = EPOLL_CTL_ADD;
- _HA_ATOMIC_OR(&polled_mask[fd], tid_bit);
+ if (en & FD_EV_POLLED_R)
+ _HA_ATOMIC_OR(&polled_mask[fd].poll_recv, tid_bit);
+ if (en & FD_EV_POLLED_W)
+ _HA_ATOMIC_OR(&polled_mask[fd].poll_send, tid_bit);
}
else {
return;
@@ -188,7 +213,8 @@
/* FD has been migrated */
activity[tid].poll_skip++;
epoll_ctl(epoll_fd[tid], EPOLL_CTL_DEL, fd, &ev);
- _HA_ATOMIC_AND(&polled_mask[fd], ~tid_bit);
+ _HA_ATOMIC_AND(&polled_mask[fd].poll_recv, ~tid_bit);
+ _HA_ATOMIC_AND(&polled_mask[fd].poll_send, ~tid_bit);
continue;
}