You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2020/12/27 17:08:23 UTC

[incubator-nuttx] branch master updated (39caf09 -> 39146ee)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from 39caf09  Fix inode lock at umount2
     new 0114f7c  fs/epoll: add sanity check to handle invalid control option
     new 39146ee  fs/epoll: add asynchronous epoll control support

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 fs/vfs/fs_epoll.c | 218 ++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 145 insertions(+), 73 deletions(-)


[incubator-nuttx] 02/02: fs/epoll: add asynchronous epoll control support

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 39146ee367c4b93922c6d894417c8dc3c5eddd88
Author: chao.an <an...@xiaomi.com>
AuthorDate: Wed Dec 23 10:45:10 2020 +0800

    fs/epoll: add asynchronous epoll control support
    
    In current implementation, the asynchronous call "epoll_ctl()" unable
    to wakeup the thread if pending on "epoll_wait()", the newly
    added/delete FD cannot be used in the current waiting list,
    this patch uses a reserved file object to wake up pending poll internal,
    re-traverse the waiting list when a new event comes.
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 fs/vfs/fs_epoll.c | 125 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 93 insertions(+), 32 deletions(-)

diff --git a/fs/vfs/fs_epoll.c b/fs/vfs/fs_epoll.c
index 83adf12..c36ccff 100644
--- a/fs/vfs/fs_epoll.c
+++ b/fs/vfs/fs_epoll.c
@@ -48,6 +48,8 @@
 #include <string.h>
 #include <debug.h>
 
+#include <nuttx/clock.h>
+#include <nuttx/fs/fs.h>
 #include <nuttx/kmalloc.h>
 
 /****************************************************************************
@@ -58,11 +60,39 @@ struct epoll_head
 {
   int size;
   int occupied;
+  struct file fp;
+  struct inode in;
   FAR epoll_data_t *data;
   FAR struct pollfd *poll;
 };
 
 /****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int epoll_poll(FAR struct file *filep,
+                      FAR struct pollfd *fds, bool setup);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_epoll_ops =
+{
+  .poll = epoll_poll
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int epoll_poll(FAR struct file *filep,
+                      FAR struct pollfd *fds, bool setup)
+{
+  return OK;
+}
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -79,15 +109,25 @@ struct epoll_head
 
 int epoll_create(int size)
 {
-  FAR struct epoll_head *eph =
-    (FAR struct epoll_head *)kmm_malloc(sizeof(struct epoll_head) +
-                                        sizeof(epoll_data_t) * size +
-                                        sizeof(struct pollfd) * size);
+  FAR struct epoll_head *eph;
+  int reserve = size + 1;
+
+  eph = (FAR struct epoll_head *)
+        kmm_zalloc(sizeof(struct epoll_head) +
+                   sizeof(epoll_data_t) * reserve +
+                   sizeof(struct pollfd) * reserve);
 
   eph->size = size;
-  eph->occupied = 0;
   eph->data = (FAR epoll_data_t *)(eph + 1);
-  eph->poll = (FAR struct pollfd *)(eph->data + size);
+  eph->poll = (FAR struct pollfd *)(eph->data + reserve);
+
+  INODE_SET_DRIVER(&eph->in);
+  eph->in.u.i_ops = &g_epoll_ops;
+  eph->fp.f_inode = &eph->in;
+  eph->in.i_private = eph;
+
+  eph->poll[0].ptr = &eph->fp;
+  eph->poll[0].events = POLLIN | POLLFILE;
 
   /* REVISIT: This will not work on machines where:
    * sizeof(struct epoll_head *) > sizeof(int)
@@ -175,7 +215,7 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
             return -1;
           }
 
-        for (i = 0; i < eph->occupied; i++)
+        for (i = 1; i <= eph->occupied; i++)
           {
             if (eph->poll[i].fd == fd)
               {
@@ -184,14 +224,14 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
               }
           }
 
-        eph->data[eph->occupied]        = ev->data;
+        eph->data[++eph->occupied]      = ev->data;
         eph->poll[eph->occupied].events = ev->events | POLLERR | POLLHUP;
-        eph->poll[eph->occupied++].fd   = fd;
+        eph->poll[eph->occupied].fd     = fd;
 
         break;
 
       case EPOLL_CTL_DEL:
-        for (i = 0; i < eph->occupied; i++)
+        for (i = 1; i <= eph->occupied; i++)
           {
             if (eph->poll[i].fd == fd)
               {
@@ -214,8 +254,7 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
       case EPOLL_CTL_MOD:
         finfo("%08x CTL MOD(%d): fd=%d ev=%08" PRIx32 "\n",
               epfd, eph->occupied, fd, ev->events);
-
-        for (i = 0; i < eph->occupied; i++)
+        for (i = 1; i <= eph->occupied; i++)
           {
             if (eph->poll[i].fd == fd)
               {
@@ -233,6 +272,12 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
         return -1;
     }
 
+  if (eph->poll[0].sem)
+    {
+      eph->poll[0].revents |= eph->poll[0].events;
+      nxsem_post(eph->poll[0].sem);
+    }
+
   return 0;
 }
 
@@ -248,48 +293,64 @@ int epoll_pwait(int epfd, FAR struct epoll_event *evs,
    */
 
   FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
+  struct timespec expire;
+  struct timespec curr;
+  struct timespec diff;
   int counter;
   int rc;
   int i;
 
+  if (timeout >= 0)
+    {
+      expire.tv_sec  = timeout / 1000;
+      expire.tv_nsec = timeout % 1000 * 1000;
+
+#ifdef CONFIG_CLOCK_MONOTONIC
+      clock_gettime(CLOCK_MONOTONIC, &curr);
+#else
+      clock_gettime(CLOCK_REALTIME, &curr);
+#endif
+
+      clock_timespec_add(&curr, &expire, &expire);
+    }
+
+again:
   if (timeout < 0)
     {
-      rc = ppoll(eph->poll, eph->occupied, NULL, sigmask);
+      rc = ppoll(eph->poll, eph->occupied + 1, NULL, sigmask);
     }
   else
     {
-      struct timespec timeout_ts;
-
-      timeout_ts.tv_sec  = timeout / 1000;
-      timeout_ts.tv_nsec = timeout % 1000 * 1000;
-
-      rc = ppoll(eph->poll, eph->occupied, &timeout_ts, sigmask);
+#ifdef CONFIG_CLOCK_MONOTONIC
+      clock_gettime(CLOCK_MONOTONIC, &curr);
+#else
+      clock_gettime(CLOCK_REALTIME, &curr);
+#endif
+      clock_timespec_subtract(&expire, &curr, &diff);
+
+      rc = ppoll(eph->poll, eph->occupied + 1, &diff, sigmask);
     }
 
   if (rc <= 0)
     {
-      if (rc < 0)
+      return rc;
+    }
+  else if (eph->poll[0].revents != 0)
+    {
+      if (--rc == 0)
         {
-          ferr("ERROR: %08x poll fail: %d for %d, %d msecs\n",
-               epfd, rc, eph->occupied, timeout);
-
-          for (i = 0; i < eph->occupied; i++)
-            {
-              ferr("  %02d: fd=%d\n", i, eph->poll[i].fd);
-            }
+          goto again;
         }
-
-      return rc;
     }
 
-  /* Iterate over non NULL event fds */
-
   if (rc > maxevents)
     {
       rc = maxevents;
     }
 
-  for (i = 0, counter = 0; i < rc && counter < eph->occupied; counter++)
+  /* Iterate over non NULL event fds */
+
+  for (i = 0, counter = 1; i < rc && counter <= eph->occupied; counter++)
     {
       if (eph->poll[counter].revents != 0)
         {


[incubator-nuttx] 01/02: fs/epoll: add sanity check to handle invalid control option

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 0114f7c58f9c57992c383ef44a4148d85d83454b
Author: chao.an <an...@xiaomi.com>
AuthorDate: Wed Dec 23 10:41:13 2020 +0800

    fs/epoll: add sanity check to handle invalid control option
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 fs/vfs/fs_epoll.c | 99 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 55 insertions(+), 44 deletions(-)

diff --git a/fs/vfs/fs_epoll.c b/fs/vfs/fs_epoll.c
index ef1b1fd..83adf12 100644
--- a/fs/vfs/fs_epoll.c
+++ b/fs/vfs/fs_epoll.c
@@ -162,67 +162,78 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
    */
 
   FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
+  int i;
 
   switch (op)
     {
       case EPOLL_CTL_ADD:
         finfo("%08x CTL ADD(%d): fd=%d ev=%08" PRIx32 "\n",
               epfd, eph->occupied, fd, ev->events);
+        if (eph->occupied >= eph->size)
+          {
+            set_errno(ENOMEM);
+            return -1;
+          }
+
+        for (i = 0; i < eph->occupied; i++)
+          {
+            if (eph->poll[i].fd == fd)
+              {
+                set_errno(EEXIST);
+                return -1;
+              }
+          }
 
         eph->data[eph->occupied]        = ev->data;
         eph->poll[eph->occupied].events = ev->events | POLLERR | POLLHUP;
         eph->poll[eph->occupied++].fd   = fd;
-        return 0;
 
-      case EPOLL_CTL_DEL:
-        {
-          int i;
+        break;
 
-          for (i = 0; i < eph->occupied; i++)
-            {
-              if (eph->poll[i].fd == fd)
-                {
-                  if (i != eph->occupied - 1)
-                    {
-                      memmove(&eph->data[i], &eph->data[i + 1],
-                              sizeof(epoll_data_t) * (eph->occupied - i));
-                      memmove(&eph->poll[i], &eph->poll[i + 1],
-                              sizeof(struct pollfd) * (eph->occupied - i));
-                    }
-
-                  eph->occupied--;
-                  return 0;
-                }
-            }
-
-          set_errno(ENOENT);
-          return -1;
-        }
+      case EPOLL_CTL_DEL:
+        for (i = 0; i < eph->occupied; i++)
+          {
+            if (eph->poll[i].fd == fd)
+              {
+                if (i != eph->occupied - 1)
+                  {
+                    memmove(&eph->data[i], &eph->data[i + 1],
+                            sizeof(epoll_data_t) * (eph->occupied - i));
+                    memmove(&eph->poll[i], &eph->poll[i + 1],
+                            sizeof(struct pollfd) * (eph->occupied - i));
+                  }
+
+                eph->occupied--;
+                break;
+              }
+          }
+
+        set_errno(ENOENT);
+        return -1;
 
       case EPOLL_CTL_MOD:
-        {
-          int i;
-
-          finfo("%08x CTL MOD(%d): fd=%d ev=%08" PRIx32 "\n",
-                epfd, eph->occupied, fd, ev->events);
-
-          for (i = 0; i < eph->occupied; i++)
-            {
-              if (eph->poll[i].fd == fd)
-                {
-                  eph->data[i]        = ev->data;
-                  eph->poll[i].events = ev->events | POLLERR | POLLHUP;
-                  return 0;
-                }
-            }
+        finfo("%08x CTL MOD(%d): fd=%d ev=%08" PRIx32 "\n",
+              epfd, eph->occupied, fd, ev->events);
 
-          set_errno(ENOENT);
-          return -1;
-        }
+        for (i = 0; i < eph->occupied; i++)
+          {
+            if (eph->poll[i].fd == fd)
+              {
+                eph->data[i]        = ev->data;
+                eph->poll[i].events = ev->events | POLLERR | POLLHUP;
+                break;
+              }
+          }
+
+        set_errno(ENOENT);
+        return -1;
+
+      default:
+        set_errno(EINVAL);
+        return -1;
     }
 
-  set_errno(EINVAL);
-  return -1;
+  return 0;
 }
 
 /****************************************************************************