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;
}
/****************************************************************************