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 2022/11/16 08:44:24 UTC

[incubator-nuttx] branch master updated: rpmsgdev: support blocked read/write operation

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


The following commit(s) were added to refs/heads/master by this push:
     new 162870b750 rpmsgdev: support blocked read/write operation
162870b750 is described below

commit 162870b7508abc50097b77e8f4b19cb24a78d9af
Author: wangbowen6 <wa...@xiaomi.com>
AuthorDate: Mon Nov 14 16:55:46 2022 +0800

    rpmsgdev: support blocked read/write operation
    
    Signed-off-by: wangbowen6 <wa...@xiaomi.com>
---
 drivers/misc/rpmsgdev.c | 138 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 132 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/rpmsgdev.c b/drivers/misc/rpmsgdev.c
index 294f1a3f07..94cefe8c9c 100644
--- a/drivers/misc/rpmsgdev.c
+++ b/drivers/misc/rpmsgdev.c
@@ -56,7 +56,8 @@
 
 struct rpmsgdev_priv_s
 {
-  uint64_t filep; /* store server file pointer */
+  uint64_t filep;    /* store server file pointer */
+  bool     nonblock; /* true: open with O_NONBLOCK */
 };
 
 struct rpmsgdev_s
@@ -87,6 +88,8 @@ struct rpmsgdev_cookie_s
 
 static int     rpmsgdev_open(FAR struct file *filep);
 static int     rpmsgdev_close(FAR struct file *filep);
+static void    rpmsgdev_wait_cb(FAR struct pollfd *fds);
+static int     rpmsgdev_wait(FAR struct file *filep, pollevent_t events);
 static ssize_t rpmsgdev_read(FAR struct file *filep, FAR char *buffer,
                              size_t buflen);
 static ssize_t rpmsgdev_write(FAR struct file *filep, FAR const char *buffer,
@@ -210,9 +213,12 @@ static int rpmsgdev_open(FAR struct file *filep)
       return -ENOMEM;
     }
 
-  /* Try to open the device in the remote cpu */
+  /* Try to open the device in the remote cpu, open with O_NONBLOCK
+   * by default to avoid the server rptun thread blocked in read/write
+   * operations.
+   */
 
-  msg.flags = filep->f_oflags;
+  msg.flags = filep->f_oflags | O_NONBLOCK;
   ret = rpmsgdev_send_recv(dev, RPMSGDEV_OPEN, true, &msg.header,
                            sizeof(msg), NULL);
   if (ret < 0)
@@ -222,7 +228,8 @@ static int rpmsgdev_open(FAR struct file *filep)
       return ret;
     }
 
-  priv->filep = msg.filep;
+  priv->filep    = msg.filep;
+  priv->nonblock = (filep->f_oflags & O_NONBLOCK) != 0;
 
   /* Attach the private date to the struct file instance */
 
@@ -279,6 +286,89 @@ static int rpmsgdev_close(FAR struct file *filep)
   return ret;
 }
 
+/****************************************************************************
+ * Name: rpmsgdev_wait_cb
+ *
+ * Description:
+ *   Rpmsg-device read/write operation wait callback function
+ *
+ * Parameters:
+ *   fds  - The structure describing the events to be monitored.
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void rpmsgdev_wait_cb(FAR struct pollfd *fds)
+{
+  int semcount = 0;
+  FAR sem_t *pollsem = (FAR sem_t *)fds->arg;
+
+  nxsem_get_value(pollsem, &semcount);
+  if (semcount < 1)
+    {
+      nxsem_post(pollsem);
+    }
+}
+
+/****************************************************************************
+ * Name: rpmsgdev_wait
+ *
+ * Description:
+ *   Rpmsg-device read/write operation wait function, this function will be
+ *   called in the rpmsgdev_read()/rpmsgdev_write() when the open flags is
+ *   not NONBLOCKED to avoid the server rptun thread blocked in file_read()
+ *   or file_write(). By calling this function before sending the READ or
+ *   WRITE command to server, a simulated blocked read/write operation is
+ *   achived.
+ *
+ * Parameters:
+ *   filep  - the file instance
+ *   events - the events to be monitored
+ *
+ * Returned Values:
+ *   OK on success; A negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int rpmsgdev_wait(FAR struct file *filep, pollevent_t events)
+{
+  int ret;
+  sem_t sem;
+  struct pollfd fds;
+
+  nxsem_init(&sem, 0, 0);
+
+  fds.events  = events;
+  fds.arg     = &sem;
+  fds.cb      = rpmsgdev_wait_cb;
+  events     |= POLLERR | POLLHUP;
+
+  while (1)
+    {
+      ret = rpmsgdev_poll(filep, &fds, true);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      ret = nxsem_wait(&sem);
+      rpmsgdev_poll(filep, &fds, false);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      if ((fds.revents & events) != 0)
+        {
+          break;
+        }
+    }
+
+  return ret;
+}
+
 /****************************************************************************
  * Name: rpmsgdev_read
  *
@@ -320,6 +410,20 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR char *buffer,
   priv = filep->f_priv;
   DEBUGASSERT(dev != NULL && priv != NULL);
 
+  /* If the open flags is not nonblock, should poll the device for
+   * read ready first to avoid the server rptun thread blocked in
+   * device read operation.
+   */
+
+  if (priv->nonblock == false)
+    {
+      ret = rpmsgdev_wait(filep, POLLIN);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+
   /* Call the host to perform the read */
 
   read.iov_base = buffer;
@@ -377,6 +481,20 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer,
   priv = filep->f_priv;
   DEBUGASSERT(dev != NULL && priv != NULL);
 
+  /* If the open flags is not nonblock, should poll the device for
+   * write ready first to avoid the server rptun thread blocked in
+   * device write operation.
+   */
+
+  if (priv->nonblock == false)
+    {
+      ret = rpmsgdev_wait(filep, POLLOUT);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+
   /* Perform the rpmsg write */
 
   memset(&cookie, 0, sizeof(cookie));
@@ -532,6 +650,7 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
   uint32_t space;
   size_t arglen;
   size_t msglen;
+  int ret;
 
   /* Sanity checks */
 
@@ -564,8 +683,15 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
       memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen);
     }
 
-  return rpmsgdev_send_recv(dev, RPMSGDEV_IOCTL, false, &msg->header,
-                            msglen, arglen > 0 ? (FAR void *)arg : NULL);
+  ret = rpmsgdev_send_recv(dev, RPMSGDEV_IOCTL, false, &msg->header,
+                           msglen, arglen > 0 ? (FAR void *)arg : NULL);
+  if (cmd == FIONBIO && ret >= 0)
+    {
+      int *nonblock = (FAR int *)(uintptr_t)arg;
+      priv->nonblock = *nonblock;
+    }
+
+  return ret;
 }
 
 /****************************************************************************