syslog/ramlog: Replace mutex with spinlock
and optimize the critical section usage 1.Remove the unnecessary critical section in ramlog_readnotify 2.Move the enter/leave critical section out of ramlog_pollnotify loop 3.Move the critical section of ramlog_addchar to caller Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
046dd38c55
commit
a0813b808f
|
@ -42,7 +42,7 @@
|
|||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
@ -96,7 +96,6 @@ struct ramlog_dev_s
|
|||
|
||||
FAR struct ramlog_header_s *rl_header;
|
||||
|
||||
mutex_t rl_lock; /* Enforces mutually exclusive access */
|
||||
uint32_t rl_bufsize; /* Size of the Circular RAM buffer */
|
||||
struct list_node rl_list; /* The head of ramlog_user_s list */
|
||||
};
|
||||
|
@ -163,7 +162,6 @@ static uint32_t g_sysbuffer[CONFIG_RAMLOG_BUFSIZE / 4];
|
|||
static struct ramlog_dev_s g_sysdev =
|
||||
{
|
||||
(FAR struct ramlog_header_s *)g_sysbuffer, /* rl_buffer */
|
||||
NXMUTEX_INITIALIZER, /* rl_lock */
|
||||
sizeof(g_sysbuffer) - sizeof(struct ramlog_header_s), /* rl_bufsize */
|
||||
LIST_INITIAL_VALUE(g_sysdev.rl_list) /* rl_list */
|
||||
};
|
||||
|
@ -193,11 +191,9 @@ static uint32_t ramlog_bufferused(FAR struct ramlog_dev_s *priv,
|
|||
static void ramlog_readnotify(FAR struct ramlog_dev_s *priv)
|
||||
{
|
||||
FAR struct ramlog_user_s *upriv;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Notify all waiting readers that they can read from the FIFO */
|
||||
|
||||
flags = enter_critical_section();
|
||||
list_for_every_entry(&priv->rl_list, upriv, struct ramlog_user_s, rl_node)
|
||||
{
|
||||
for (; ; )
|
||||
|
@ -213,8 +209,6 @@ static void ramlog_readnotify(FAR struct ramlog_dev_s *priv)
|
|||
nxsem_post(&upriv->rl_waitsem);
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -225,11 +219,9 @@ static void ramlog_readnotify(FAR struct ramlog_dev_s *priv)
|
|||
static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv)
|
||||
{
|
||||
FAR struct ramlog_user_s *upriv;
|
||||
irqstate_t flags;
|
||||
|
||||
/* This function may be called from an interrupt handler */
|
||||
|
||||
flags = enter_critical_section();
|
||||
list_for_every_entry(&priv->rl_list, upriv, struct ramlog_user_s, rl_node)
|
||||
{
|
||||
if (ramlog_bufferused(priv, upriv) >= upriv->rl_threashold)
|
||||
|
@ -241,8 +233,6 @@ static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv)
|
|||
poll_notify(&upriv->rl_fds, 1, POLLIN);
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -252,11 +242,6 @@ static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv)
|
|||
static void ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch)
|
||||
{
|
||||
FAR struct ramlog_header_s *header = priv->rl_header;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Disable interrupts (in case we are NOT called from interrupt handler) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
#ifdef CONFIG_RAMLOG_SYSLOG
|
||||
if (priv == &g_sysdev && header->rl_magic != RAMLOG_MAGIC_NUMBER)
|
||||
|
@ -271,7 +256,6 @@ static void ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch)
|
|||
|
||||
if (ch == '\r')
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -294,8 +278,6 @@ again:
|
|||
goto again;
|
||||
}
|
||||
#endif
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -305,15 +287,13 @@ again:
|
|||
static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
|
||||
FAR const char *buffer, size_t len)
|
||||
{
|
||||
irqstate_t flags;
|
||||
size_t nwritten;
|
||||
char ch;
|
||||
int ret;
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
/* Disable interrupts (in case we are NOT called from interrupt handler) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
for (nwritten = 0; nwritten < len; nwritten++)
|
||||
{
|
||||
|
@ -345,7 +325,7 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
|
|||
* probably retry, causing same error condition again.
|
||||
*/
|
||||
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
leave_critical_section(flags);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -360,10 +340,10 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
|
|||
FAR struct ramlog_dev_s *priv = inode->i_private;
|
||||
FAR struct ramlog_header_s *header = priv->rl_header;
|
||||
FAR struct ramlog_user_s *upriv = filep->f_priv;
|
||||
irqstate_t flags;
|
||||
uint32_t tail;
|
||||
ssize_t nread;
|
||||
char ch;
|
||||
int ret;
|
||||
|
||||
/* If the circular buffer is empty, then wait for something to be written
|
||||
* to it. This function may NOT be called from an interrupt handler.
|
||||
|
@ -373,11 +353,7 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
|
|||
|
||||
/* Get exclusive access to the rl_tail index */
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Determine whether the read pointer is overwritten */
|
||||
|
||||
|
@ -403,6 +379,8 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
|
|||
|
||||
break;
|
||||
#else
|
||||
int ret;
|
||||
|
||||
/* Did we read anything? */
|
||||
|
||||
if (nread > 0)
|
||||
|
@ -422,14 +400,6 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, wait for something to be written to the circular
|
||||
* buffer. Increment the number of waiters so that the
|
||||
* ramlog_file_write() will note that it needs to post the
|
||||
* semaphore to wake us up.
|
||||
*/
|
||||
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
|
||||
/* We may now be pre-empted! But that should be okay because we
|
||||
* have already incremented nwaiters. Pre-emptions is disabled
|
||||
* but will be re-enabled while we are waiting.
|
||||
|
@ -439,20 +409,9 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
|
|||
|
||||
/* Did we successfully get the rl_waitsem? */
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Yes... then retake the mutual exclusion mutex */
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
}
|
||||
|
||||
/* Was the mutex wait successful? Did we successful re-take the
|
||||
* mutual exclusion mutex?
|
||||
*/
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* No.. One of the two nxsem_wait's failed. */
|
||||
/* No.. nxsem_wait's failed. */
|
||||
|
||||
/* Return the error. We did handle the case where we read
|
||||
* anything already before waiting.
|
||||
|
@ -485,9 +444,7 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
/* Relinquish the mutual exclusion mutex */
|
||||
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Return the number of characters actually read */
|
||||
|
||||
|
@ -517,13 +474,10 @@ static int ramlog_file_ioctl(FAR struct file *filep, int cmd,
|
|||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ramlog_dev_s *priv = inode->i_private;
|
||||
FAR struct ramlog_user_s *upriv = filep->f_priv;
|
||||
int ret;
|
||||
irqstate_t flags;
|
||||
int ret = 0;
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
|
@ -538,7 +492,7 @@ static int ramlog_file_ioctl(FAR struct file *filep, int cmd,
|
|||
break;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -554,15 +508,10 @@ static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||
FAR struct ramlog_user_s *upriv = filep->f_priv;
|
||||
pollevent_t eventset = POLLOUT;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Get exclusive access to the poll structures */
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Are we setting up the poll? Or tearing it down? */
|
||||
|
||||
|
@ -580,8 +529,6 @@ static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||
|
||||
/* Should immediately notify on any of the requested events? */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Check if the receive buffer is not empty. */
|
||||
|
||||
if (ramlog_bufferused(priv, upriv) >= upriv->rl_threashold)
|
||||
|
@ -589,8 +536,6 @@ static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||
eventset |= POLLIN;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
poll_notify(&fds, 1, eventset);
|
||||
}
|
||||
else if (fds->priv)
|
||||
|
@ -605,8 +550,8 @@ static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||
fds->priv = NULL;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
return ret;
|
||||
leave_critical_section(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -619,7 +564,7 @@ static int ramlog_file_open(FAR struct file *filep)
|
|||
FAR struct ramlog_dev_s *priv = inode->i_private;
|
||||
FAR struct ramlog_header_s *header = priv->rl_header;
|
||||
FAR struct ramlog_user_s *upriv;
|
||||
int ret;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Get exclusive access to the rl_tail index */
|
||||
|
||||
|
@ -634,23 +579,14 @@ static int ramlog_file_open(FAR struct file *filep)
|
|||
nxsem_init(&upriv->rl_waitsem, 0, 0);
|
||||
#endif
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
#ifndef CONFIG_RAMLOG_NONBLOCKING
|
||||
nxsem_destroy(&upriv->rl_waitsem);
|
||||
#endif
|
||||
kmm_free(upriv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
list_add_tail(&priv->rl_list, &upriv->rl_node);
|
||||
|
||||
upriv->rl_tail = header->rl_head > priv->rl_bufsize ?
|
||||
header->rl_head - priv->rl_bufsize : 0;
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
filep->f_priv = upriv;
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -659,27 +595,20 @@ static int ramlog_file_open(FAR struct file *filep)
|
|||
|
||||
static int ramlog_file_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ramlog_dev_s *priv = inode->i_private;
|
||||
FAR struct ramlog_user_s *upriv = filep->f_priv;
|
||||
int ret;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Get exclusive access to the rl_tail index */
|
||||
|
||||
ret = nxmutex_lock(&priv->rl_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
list_delete(&upriv->rl_node);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
#ifndef CONFIG_RAMLOG_NONBLOCKING
|
||||
nxsem_destroy(&upriv->rl_waitsem);
|
||||
#endif
|
||||
|
||||
list_delete(&upriv->rl_node);
|
||||
kmm_free(upriv);
|
||||
nxmutex_unlock(&priv->rl_lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -710,7 +639,6 @@ int ramlog_register(FAR const char *devpath, FAR char *buffer, size_t buflen)
|
|||
{
|
||||
/* Initialize the non-zero values in the RAM logging device structure */
|
||||
|
||||
nxmutex_init(&priv->rl_lock);
|
||||
list_initialize(&priv->rl_list);
|
||||
priv->rl_bufsize = buflen - sizeof(struct ramlog_header_s);
|
||||
priv->rl_header = (FAR struct ramlog_header_s *)buffer;
|
||||
|
@ -720,7 +648,6 @@ int ramlog_register(FAR const char *devpath, FAR char *buffer, size_t buflen)
|
|||
ret = register_driver(devpath, &g_ramlogfops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
nxmutex_destroy(&priv->rl_lock);
|
||||
kmm_free(priv);
|
||||
}
|
||||
}
|
||||
|
@ -758,11 +685,13 @@ void ramlog_syslog_register(void)
|
|||
int ramlog_putc(FAR struct syslog_channel_s *channel, int ch)
|
||||
{
|
||||
FAR struct ramlog_dev_s *priv = &g_sysdev;
|
||||
irqstate_t flags;
|
||||
|
||||
UNUSED(channel);
|
||||
|
||||
/* Add the character to the RAMLOG */
|
||||
|
||||
flags = enter_critical_section();
|
||||
ramlog_addchar(priv, ch);
|
||||
|
||||
#ifndef CONFIG_RAMLOG_NONBLOCKING
|
||||
|
@ -774,6 +703,7 @@ int ramlog_putc(FAR struct syslog_channel_s *channel, int ch)
|
|||
/* Notify all poll/select waiters that they can read from the FIFO */
|
||||
|
||||
ramlog_pollnotify(priv);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Return the character added on success */
|
||||
|
||||
|
|
Loading…
Reference in New Issue