eal/linux: add function to allow interruptible epoll
authorStephen Hemminger <stephen@networkplumber.org>
Thu, 3 Sep 2020 23:28:22 +0000 (16:28 -0700)
committerThomas Monjalon <thomas@monjalon.net>
Mon, 19 Oct 2020 10:17:25 +0000 (12:17 +0200)
The existing definition of rte_epoll_wait retries if interrupted
by a signal. This behavior makes it hard to use rte_epoll_wait
for applications that want to use signals do do things like
exit polling loop and shutdown.

Since changing existing semantic might break applications, add
a new rte_epoll_wait_interruptible() function that does the
same thing as rte_epoll_wait but will return -1 and errno of EINTR
if it receives a signal.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Harman Kalra <hkalra@marvell.com>
lib/librte_eal/freebsd/eal_interrupts.c
lib/librte_eal/include/rte_eal_interrupts.h
lib/librte_eal/linux/eal_interrupts.c
lib/librte_eal/rte_eal_version.map

index 6d53d33..b07cff6 100644 (file)
@@ -684,6 +684,18 @@ rte_epoll_wait(int epfd, struct rte_epoll_event *events,
        return -ENOTSUP;
 }
 
+int
+rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
+                            int maxevents, int timeout)
+{
+       RTE_SET_USED(epfd);
+       RTE_SET_USED(events);
+       RTE_SET_USED(maxevents);
+       RTE_SET_USED(timeout);
+
+       return -ENOTSUP;
+}
+
 int
 rte_epoll_ctl(int epfd, int op, int fd, struct rte_epoll_event *event)
 {
index b80edfc..00bcc19 100644 (file)
@@ -95,6 +95,7 @@ struct rte_intr_handle {
 
 /**
  * It waits for events on the epoll instance.
+ * Retries if signal received.
  *
  * @param epfd
  *   Epoll instance fd on which the caller wait for events.
@@ -113,6 +114,28 @@ int
 rte_epoll_wait(int epfd, struct rte_epoll_event *events,
               int maxevents, int timeout);
 
+/**
+ * It waits for events on the epoll instance.
+ * Does not retry if signal received.
+ *
+ * @param epfd
+ *   Epoll instance fd on which the caller wait for events.
+ * @param events
+ *   Memory area contains the events that will be available for the caller.
+ * @param maxevents
+ *   Up to maxevents are returned, must greater than zero.
+ * @param timeout
+ *   Specifying a timeout of -1 causes a block indefinitely.
+ *   Specifying a timeout equal to zero cause to return immediately.
+ * @return
+ *   - On success, returns the number of available event.
+ *   - On failure, a negative value.
+ */
+__rte_experimental
+int
+rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
+              int maxevents, int timeout);
+
 /**
  * It performs control operations on epoll instance referred by the epfd.
  * It requests that the operation op be performed for the target fd.
index 13db5c4..26b5dd4 100644 (file)
@@ -1275,9 +1275,9 @@ rte_intr_tls_epfd(void)
        return RTE_PER_LCORE(_epfd);
 }
 
-int
-rte_epoll_wait(int epfd, struct rte_epoll_event *events,
-              int maxevents, int timeout)
+static int
+eal_epoll_wait(int epfd, struct rte_epoll_event *events,
+              int maxevents, int timeout, bool interruptible)
 {
        struct epoll_event evs[maxevents];
        int rc;
@@ -1298,8 +1298,12 @@ rte_epoll_wait(int epfd, struct rte_epoll_event *events,
                        rc = eal_epoll_process_event(evs, rc, events);
                        break;
                } else if (rc < 0) {
-                       if (errno == EINTR)
-                               continue;
+                       if (errno == EINTR) {
+                               if (interruptible)
+                                       return -1;
+                               else
+                                       continue;
+                       }
                        /* epoll_wait fail */
                        RTE_LOG(ERR, EAL, "epoll_wait returns with fail %s\n",
                                strerror(errno));
@@ -1314,6 +1318,20 @@ rte_epoll_wait(int epfd, struct rte_epoll_event *events,
        return rc;
 }
 
+int
+rte_epoll_wait(int epfd, struct rte_epoll_event *events,
+              int maxevents, int timeout)
+{
+       return eal_epoll_wait(epfd, events, maxevents, timeout, false);
+}
+
+int
+rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
+                            int maxevents, int timeout)
+{
+       return eal_epoll_wait(epfd, events, maxevents, timeout, true);
+}
+
 static inline void
 eal_epoll_data_safe_free(struct rte_epoll_event *ev)
 {
index f56de02..df8e0af 100644 (file)
@@ -398,6 +398,7 @@ EXPERIMENTAL {
 
        # added in 20.11
        __rte_eal_trace_generic_size_t;
+       rte_epoll_wait_interruptible;
        rte_service_lcore_may_be_active;
 };