This removes the need to verify for eventless file descriptors and mitigates risks of bug due to behaviour mismatch.
Signed-off-by: Yannick Lamarre <ylama...@efficios.com> --- src/common/compat/compat-poll.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/common/compat/compat-poll.c b/src/common/compat/compat-poll.c index b7c17df7..6aa9414d 100644 --- a/src/common/compat/compat-poll.c +++ b/src/common/compat/compat-poll.c @@ -292,6 +292,7 @@ error: int compat_poll_wait(struct lttng_poll_event *events, int timeout) { int ret; + int eidx = 0; if (events == NULL || events->current.events == NULL) { ERR("poll wait arguments error"); @@ -324,10 +325,36 @@ int compat_poll_wait(struct lttng_poll_event *events, int timeout) } /* - * poll() should always iterate on all FDs since we handle the pollset in - * user space and after poll returns, we have to try every fd for a match. + * Swap all nonzero revents pollfd structs to the beginning of the array to + * emulate compat-epoll behaviour. This algorithm takes advantage of poll's + * returned value and the burst nature of waking events on the file + * descriptors. The while loop garantees that idlepfd will always point to + * a pollfd with revents == 0. */ - return events->wait.nb_fd; + if (ret == events->wait.nb_fd) { + goto skip; + } + while (eidx < ret && events->wait.events[eidx].revents != 0) { + eidx += 1; + } + + for (int idx = eidx + 1; eidx < ret; idx++) { + struct pollfd swapfd; + struct pollfd *idlepfd = &events->wait.events[eidx]; + struct pollfd *ipfd = &events->wait.events[idx]; + + assert(idx < events->wait.nb_fd); + + if (ipfd->revents != 0) { + swapfd = *ipfd; + *ipfd = *idlepfd; + *idlepfd = swapfd; + eidx += 1; + } + } + +skip: + return ret; error: return -1; -- 2.11.0 _______________________________________________ lttng-dev mailing list lttng-dev@lists.lttng.org https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev