Change lttng_poll_wait behaviour of compat-poll to match compat-epoll
authorYannick Lamarre <ylamarre@efficios.com>
Thu, 25 Apr 2019 22:23:32 +0000 (18:23 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sat, 4 May 2019 19:28:25 +0000 (15:28 -0400)
This removes the need to verify for idle file descriptors and mitigates
risks of bug due to behaviour mismatch.

Signed-off-by: Yannick Lamarre <ylamarre@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/common/compat/compat-poll.c

index 2318920aed84a7c9dcdb5c1668035913ecb0ff10..0220b27854ab776294404c6c80e9a5608bfdeb54 100644 (file)
@@ -293,7 +293,9 @@ error:
  */
 int compat_poll_wait(struct lttng_poll_event *events, int timeout)
 {
-       int ret;
+       int ret, active_fd_count;
+       int idle_pfd_index = 0;
+       size_t i;
 
        if (events == NULL || events->current.events == NULL) {
                ERR("poll wait arguments error");
@@ -325,11 +327,39 @@ int compat_poll_wait(struct lttng_poll_event *events, int timeout)
                goto error;
        }
 
+       active_fd_count = ret;
+
        /*
-        * 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 active 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 active
+        * events on the file descriptors. The while loop guarantees that
+        * idle_pfd will always point to an idle fd.
         */
-       return events->wait.nb_fd;
+       if (active_fd_count == events->wait.nb_fd) {
+               goto end;
+       }
+       while (idle_pfd_index < active_fd_count &&
+                       events->wait.events[idle_pfd_index].revents != 0) {
+               idle_pfd_index++;
+       }
+
+       for (i = idle_pfd_index + 1; idle_pfd_index < active_fd_count;
+                       i++) {
+               struct pollfd swap_pfd;
+               struct pollfd *idle_pfd = &events->wait.events[idle_pfd_index];
+               struct pollfd *current_pfd = &events->wait.events[i];
+
+               if (ipfd->revents != 0) {
+                       swap_pfd = *current_pfd;
+                       *current_pfd = *idle_pfd;
+                       *idle_pfd = swap_pfd;
+                       idle_pfd_index++;
+               }
+       }
+
+end:
+       return ret;
 
 error:
        return -1;
This page took 0.027113 seconds and 4 git commands to generate.