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 817259ec2d454a2974b39ad16dc48138dae35931
Author: Jiuzhu Dong <dongjiuz...@xiaomi.com>
AuthorDate: Thu Jun 17 17:00:47 2021 +0800

    syslog/ramlog_channel: fix log confusion when multi task writing together
    
    Signed-off-by: Jiuzhu Dong <dongjiuz...@xiaomi.com>
---
 drivers/syslog/ramlog.c         | 212 ++++++++++++++++++++++------------------
 drivers/syslog/syslog_channel.c |   4 +-
 include/nuttx/syslog/ramlog.h   |  13 +++
 3 files changed, 131 insertions(+), 98 deletions(-)

diff --git a/drivers/syslog/ramlog.c b/drivers/syslog/ramlog.c
index df65b4d..e183900 100644
--- a/drivers/syslog/ramlog.c
+++ b/drivers/syslog/ramlog.c
@@ -92,14 +92,14 @@ static int     ramlog_addchar(FAR struct ramlog_dev_s 
*priv, char ch);
 
 /* Character driver methods */
 
-static ssize_t ramlog_read(FAR struct file *filep, FAR char *buffer,
-                           size_t buflen);
-static ssize_t ramlog_write(FAR struct file *filep, FAR const char *buffer,
-                            size_t buflen);
-static int     ramlog_ioctl(FAR struct file *filep, int cmd,
-                            unsigned long arg);
-static int     ramlog_poll(FAR struct file *filep, FAR struct pollfd *fds,
-                           bool setup);
+static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
+                                size_t buflen);
+static ssize_t ramlog_file_write(FAR struct file *filep,
+                                 FAR const char *buffer, size_t buflen);
+static int     ramlog_file_ioctl(FAR struct file *filep, int cmd,
+                                 unsigned long arg);
+static int     ramlog_file_poll(FAR struct file *filep,
+                                FAR struct pollfd *fds, bool setup);
 
 /****************************************************************************
  * Private Data
@@ -107,15 +107,15 @@ static int     ramlog_poll(FAR struct file *filep, FAR 
struct pollfd *fds,
 
 static const struct file_operations g_ramlogfops =
 {
-  NULL,         /* open */
-  NULL,         /* close */
-  ramlog_read,  /* read */
-  ramlog_write, /* write */
-  NULL,         /* seek */
-  ramlog_ioctl, /* ioctl */
-  ramlog_poll   /* poll */
+  NULL,              /* open */
+  NULL,              /* close */
+  ramlog_file_read,  /* read */
+  ramlog_file_write, /* write */
+  NULL,              /* seek */
+  ramlog_file_ioctl, /* ioctl */
+  ramlog_file_poll   /* poll */
 #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
-  , NULL        /* unlink */
+  , NULL             /* unlink */
 #endif
 };
 
@@ -287,11 +287,88 @@ again:
 }
 
 /****************************************************************************
+ * Name: ramlog_addbuf
+ ****************************************************************************/
+
+static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
+                             FAR const char *buffer, size_t len)
+{
+  int readers_waken;
+  ssize_t nwritten;
+  char ch;
+  int ret;
+
+  ret = nxsem_wait(&priv->rl_exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  for (nwritten = 0; (size_t)nwritten < len; nwritten++)
+    {
+      /* Get the next character to output */
+
+      ch = buffer[nwritten];
+
+      /* Then output the character */
+
+      ret = ramlog_addchar(priv, ch);
+      if (ret < 0)
+        {
+          /* The buffer is full and nothing was saved.  The remaining
+           * data to be written is dropped on the floor.
+           */
+
+          break;
+        }
+    }
+
+  /* Was anything written? */
+
+  if (nwritten > 0)
+    {
+      readers_waken = 0;
+
+#ifndef CONFIG_RAMLOG_NONBLOCKING
+      /* Are there threads waiting for read data? */
+
+      readers_waken = ramlog_readnotify(priv);
+#endif
+
+      /* If there are multiple readers, some of them might block despite
+       * POLLIN because first reader might read all data. Favor readers
+       * and notify poll waiters only if no reader was awaken, even if the
+       * latter may starve.
+       *
+       * This also implies we do not have to make these two notify
+       * operations a critical section.
+       */
+
+      if (readers_waken == 0)
+        {
+          /* Notify all poll/select waiters that they can read from the
+           * FIFO.
+           */
+
+          ramlog_pollnotify(priv, POLLIN);
+        }
+    }
+
+  /* We always have to return the number of bytes requested and NOT the
+   * number of bytes that were actually written.  Otherwise, callers
+   * probably retry, causing same error condition again.
+   */
+
+  nxsem_post(&priv->rl_exclsem);
+  return len;
+}
+
+/****************************************************************************
  * Name: ramlog_read
  ****************************************************************************/
 
-static ssize_t ramlog_read(FAR struct file *filep, FAR char *buffer,
-                           size_t len)
+static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
+                                size_t len)
 {
   FAR struct inode *inode = filep->f_inode;
   FAR struct ramlog_dev_s *priv;
@@ -354,8 +431,8 @@ static ssize_t ramlog_read(FAR struct file *filep, FAR char 
*buffer,
 
           /* Otherwise, wait for something to be written to the circular
            * buffer. Increment the number of waiters so that the
-           * ramlog_write() will note that it needs to post the semaphore
-           * to wake us up.
+           * ramlog_file_write() will note that it needs to post the
+           * semaphore to wake us up.
            */
 
           sched_lock();
@@ -452,96 +529,29 @@ errout_without_sem:
 }
 
 /****************************************************************************
- * Name: ramlog_write
+ * Name: ramlog_file_write
  ****************************************************************************/
 
-static ssize_t ramlog_write(FAR struct file *filep, FAR const char *buffer,
-                            size_t len)
+static ssize_t ramlog_file_write(FAR struct file *filep,
+                                 FAR const char *buffer, size_t len)
 {
   FAR struct inode *inode = filep->f_inode;
   FAR struct ramlog_dev_s *priv;
-  int readers_waken;
-  ssize_t nwritten;
-  char ch;
-  int ret;
 
   /* Some sanity checking */
 
   DEBUGASSERT(inode && inode->i_private);
   priv = (FAR struct ramlog_dev_s *)inode->i_private;
 
-  /* Loop until all of the bytes have been written.  This function may be
-   * called from an interrupt handler!  Semaphores cannot be used!
-   *
-   * The write logic only needs to modify the rl_head index.  Therefore,
-   * there is a difference in the way that rl_head and rl_tail are protected:
-   * rl_tail is protected with a semaphore; rl_head is protected by disabling
-   * interrupts.
-   */
-
-  for (nwritten = 0; (size_t)nwritten < len; nwritten++)
-    {
-      /* Get the next character to output */
-
-      ch = buffer[nwritten];
-
-      /* Then output the character */
-
-      ret = ramlog_addchar(priv, ch);
-      if (ret < 0)
-        {
-          /* The buffer is full and nothing was saved.  The remaining
-           * data to be written is dropped on the floor.
-           */
-
-          break;
-        }
-    }
-
-  /* Was anything written? */
-
-  if (nwritten > 0)
-    {
-      readers_waken = 0;
-
-#ifndef CONFIG_RAMLOG_NONBLOCKING
-      /* Are there threads waiting for read data? */
-
-      readers_waken = ramlog_readnotify(priv);
-#endif
-
-      /* If there are multiple readers, some of them might block despite
-       * POLLIN because first reader might read all data. Favor readers
-       * and notify poll waiters only if no reader was awaken, even if the
-       * latter may starve.
-       *
-       * This also implies we do not have to make these two notify
-       * operations a critical section.
-       */
-
-      if (readers_waken == 0)
-        {
-          /* Notify all poll/select waiters that they can read from the
-           * FIFO.
-           */
-
-          ramlog_pollnotify(priv, POLLIN);
-        }
-    }
-
-  /* We always have to return the number of bytes requested and NOT the
-   * number of bytes that were actually written.  Otherwise, callers
-   * probably retry, causing same error condition again.
-   */
-
-  return len;
+  return ramlog_addbuf(priv, buffer, len);
 }
 
 /****************************************************************************
- * Name: ramlog_ioctl
+ * Name: ramlog_file_ioctl
  ****************************************************************************/
 
-static int ramlog_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+static int ramlog_file_ioctl(FAR struct file *filep, int cmd,
+                             unsigned long arg)
 {
   FAR struct inode *inode = filep->f_inode;
   FAR struct ramlog_dev_s *priv;
@@ -573,11 +583,11 @@ static int ramlog_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
 }
 
 /****************************************************************************
- * Name: ramlog_poll
+ * Name: ramlog_file_poll
  ****************************************************************************/
 
-static int ramlog_poll(FAR struct file *filep, FAR struct pollfd *fds,
-                       bool setup)
+static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
+                            bool setup)
 {
   FAR struct inode *inode = filep->f_inode;
   FAR struct ramlog_dev_s *priv;
@@ -868,6 +878,14 @@ int ramlog_putc(FAR struct syslog_channel_s *channel, int 
ch)
 
   return ch;
 }
+
+ssize_t ramlog_write(FAR struct syslog_channel_s *channel,
+                     FAR const char *buffer, size_t buflen)
+{
+  FAR struct ramlog_dev_s *priv = &g_sysdev;
+
+  return ramlog_addbuf(priv, buffer, buflen);
+}
 #endif
 
 #endif /* CONFIG_RAMLOG */
diff --git a/drivers/syslog/syslog_channel.c b/drivers/syslog/syslog_channel.c
index 2357993..c05c4ba 100644
--- a/drivers/syslog/syslog_channel.c
+++ b/drivers/syslog/syslog_channel.c
@@ -68,7 +68,9 @@ static ssize_t syslog_default_write(FAR struct 
syslog_channel_s *channel,
 static const struct syslog_channel_ops_s g_ramlog_channel_ops =
 {
   ramlog_putc,
-  ramlog_putc
+  ramlog_putc,
+  NULL,
+  ramlog_write
 };
 
 static struct syslog_channel_s g_ramlog_channel =
diff --git a/include/nuttx/syslog/ramlog.h b/include/nuttx/syslog/ramlog.h
index 0d13010..a71f02e 100644
--- a/include/nuttx/syslog/ramlog.h
+++ b/include/nuttx/syslog/ramlog.h
@@ -140,6 +140,19 @@ void ramlog_syslog_register(void);
 int ramlog_putc(FAR struct syslog_channel_s *channel, int ch);
 #endif
 
+/****************************************************************************
+ * Name: ramlog_write
+ *
+ * Description:
+ *   This is the low-level system logging interface.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RAMLOG_SYSLOG
+ssize_t ramlog_write(FAR struct syslog_channel_s *channel,
+                     FAR const char *buffer, size_t buflen);
+#endif
+
 #undef EXTERN
 #ifdef __cplusplus
 }

Reply via email to