MEDIUM: poll: don't use the old FD state anymore

The polling updates are now performed exactly like the epoll/kqueue
ones : only the new polled state is considered, and the previous one
is checked using polled_mask. The only specific stuff here is that
the fd state is shared between all threads, so an FD removal has to
be done only once.
This commit is contained in:
Willy Tarreau 2018-01-25 17:11:33 +01:00
parent 56dd12a7f0
commit fc6eea4de2

View File

@ -77,25 +77,37 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
fdtab[fd].state = en; fdtab[fd].state = en;
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock); HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
if ((eo ^ en) & FD_EV_POLLED_RW) { /* we have a single state for all threads, which is why we
/* poll status changed, update the lists */ * don't check the tid_bit. First thread to see the update
if ((eo & ~en) & FD_EV_POLLED_R) * takes it for every other one.
*/
if (!(en & FD_EV_POLLED_RW)) {
if (!fdtab[fd].polled_mask) {
/* fd was not watched, it's still not */
continue;
}
/* fd totally removed from poll list */
hap_fd_clr(fd, fd_evts[DIR_RD]); hap_fd_clr(fd, fd_evts[DIR_RD]);
else if ((en & ~eo) & FD_EV_POLLED_R) {
hap_fd_set(fd, fd_evts[DIR_RD]);
if (fd > max_add_fd)
max_add_fd = fd;
}
if ((eo & ~en) & FD_EV_POLLED_W)
hap_fd_clr(fd, fd_evts[DIR_WR]); hap_fd_clr(fd, fd_evts[DIR_WR]);
else if ((en & ~eo) & FD_EV_POLLED_W) { HA_ATOMIC_AND(&fdtab[fd].polled_mask, 0);
}
else {
/* OK fd has to be monitored, it was either added or changed */
if (!(en & FD_EV_POLLED_R))
hap_fd_clr(fd, fd_evts[DIR_RD]);
else
hap_fd_set(fd, fd_evts[DIR_RD]);
if (!(en & FD_EV_POLLED_W))
hap_fd_clr(fd, fd_evts[DIR_WR]);
else
hap_fd_set(fd, fd_evts[DIR_WR]); hap_fd_set(fd, fd_evts[DIR_WR]);
HA_ATOMIC_OR(&fdtab[fd].polled_mask, tid_bit);
if (fd > max_add_fd) if (fd > max_add_fd)
max_add_fd = fd; max_add_fd = fd;
} }
} }
}
/* maybe we added at least one fd larger than maxfd */ /* maybe we added at least one fd larger than maxfd */
for (old_maxfd = maxfd; old_maxfd <= max_add_fd; ) { for (old_maxfd = maxfd; old_maxfd <= max_add_fd; ) {