syslog/ramlog: Prepare to support the multiple reader

1.Remove RAMLOG_OVERWRITE option and related code
2.Broadcast the readability to all reader and poller

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2023-11-18 18:14:25 +08:00 committed by Xiang Xiao
parent 6a8c638d57
commit e920883458
3 changed files with 16 additions and 109 deletions

View File

@ -45,7 +45,6 @@ CONFIG_PHOTON_WDG_THREAD=y
CONFIG_PREALLOC_TIMERS=4 CONFIG_PREALLOC_TIMERS=4
CONFIG_RAMLOG=y CONFIG_RAMLOG=y
CONFIG_RAMLOG_BUFSIZE=2048 CONFIG_RAMLOG_BUFSIZE=2048
CONFIG_RAMLOG_OVERWRITE=y
CONFIG_RAMLOG_SYSLOG=y CONFIG_RAMLOG_SYSLOG=y
CONFIG_RAM_SIZE=114688 CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000 CONFIG_RAM_START=0x20000000

View File

@ -54,13 +54,6 @@ config RAMLOG_NPOLLWAITERS
---help--- ---help---
The maximum number of threads that may be waiting on the poll method. The maximum number of threads that may be waiting on the poll method.
config RAMLOG_OVERWRITE
bool "RAMLOG overwrite circular buffer"
default n
---help---
Enable overwrite of circular buffer. If RAMLOG buffer overflows,
overwrite it from the top of buffer and always keep the latest log.
config RAMLOG_POLLTHRESHOLD config RAMLOG_POLLTHRESHOLD
int "The threshold value of circular buffer to notify poll waiters" int "The threshold value of circular buffer to notify poll waiters"
default 1 default 1

View File

@ -83,11 +83,11 @@ struct ramlog_dev_s
/* Helper functions */ /* Helper functions */
#ifndef CONFIG_RAMLOG_NONBLOCKING #ifndef CONFIG_RAMLOG_NONBLOCKING
static int ramlog_readnotify(FAR struct ramlog_dev_s *priv); static void ramlog_readnotify(FAR struct ramlog_dev_s *priv);
#endif #endif
static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv, static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv,
pollevent_t eventset); pollevent_t eventset);
static int ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch); static void ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch);
/* Character driver methods */ /* Character driver methods */
@ -166,16 +166,15 @@ static size_t ramlog_bufferused(FAR struct ramlog_dev_s *priv)
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_RAMLOG_NONBLOCKING #ifndef CONFIG_RAMLOG_NONBLOCKING
static int ramlog_readnotify(FAR struct ramlog_dev_s *priv) static void ramlog_readnotify(FAR struct ramlog_dev_s *priv)
{ {
irqstate_t flags; irqstate_t flags;
int i;
/* Notify all waiting readers that they can read from the FIFO */ /* Notify all waiting readers that they can read from the FIFO */
flags = enter_critical_section(); flags = enter_critical_section();
for (i = 0; ; i++) for (; ; )
{ {
int semcount = 0; int semcount = 0;
@ -189,10 +188,6 @@ static int ramlog_readnotify(FAR struct ramlog_dev_s *priv)
} }
leave_critical_section(flags); leave_critical_section(flags);
/* Return number of notified readers. */
return i;
} }
#endif #endif
@ -286,7 +281,7 @@ static void ramlog_initbuf(void)
* Name: ramlog_addchar * Name: ramlog_addchar
****************************************************************************/ ****************************************************************************/
static int ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch) static void ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch)
{ {
irqstate_t flags; irqstate_t flags;
size_t nexthead; size_t nexthead;
@ -308,7 +303,7 @@ static int ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch)
if (ch == '\r') if (ch == '\r')
{ {
leave_critical_section(flags); leave_critical_section(flags);
return OK; return;
} }
/* Pre-pend a carriage before a linefeed */ /* Pre-pend a carriage before a linefeed */
@ -333,7 +328,6 @@ again:
if (nexthead == priv->rl_tail) if (nexthead == priv->rl_tail)
{ {
#ifdef CONFIG_RAMLOG_OVERWRITE
/* Yes... Overwrite with the latest log in the circular buffer */ /* Yes... Overwrite with the latest log in the circular buffer */
priv->rl_buffer[priv->rl_tail] = '\0'; priv->rl_buffer[priv->rl_tail] = '\0';
@ -342,12 +336,6 @@ again:
{ {
priv->rl_tail = 0; priv->rl_tail = 0;
} }
#else
/* Yes... Return an indication that nothing was saved in the buffer. */
leave_critical_section(flags);
return -EBUSY;
#endif
} }
/* No... copy the byte and re-enable interrupts */ /* No... copy the byte and re-enable interrupts */
@ -364,7 +352,6 @@ again:
#endif #endif
leave_critical_section(flags); leave_critical_section(flags);
return OK;
} }
/**************************************************************************** /****************************************************************************
@ -374,8 +361,7 @@ again:
static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv, static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
FAR const char *buffer, size_t len) FAR const char *buffer, size_t len)
{ {
int readers_waken; size_t nwritten;
ssize_t nwritten;
char ch; char ch;
int ret; int ret;
@ -385,7 +371,7 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
return ret; return ret;
} }
for (nwritten = 0; (size_t)nwritten < len; nwritten++) for (nwritten = 0; nwritten < len; nwritten++)
{ {
/* Get the next character to output */ /* Get the next character to output */
@ -393,40 +379,20 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
/* Then output the character */ /* Then output the character */
ret = ramlog_addchar(priv, ch); 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? */ /* Was anything written? */
if (nwritten > 0) if (nwritten > 0)
{ {
readers_waken = 0;
#ifndef CONFIG_RAMLOG_NONBLOCKING #ifndef CONFIG_RAMLOG_NONBLOCKING
/* Are there threads waiting for read data? */ /* Are there threads waiting for read data? */
readers_waken = ramlog_readnotify(priv); ramlog_readnotify(priv);
#endif #endif
/* If there are multiple readers, some of them might block despite if (ramlog_bufferused(priv) >= CONFIG_RAMLOG_POLLTHRESHOLD)
* POLLIN because first reader might read all data. Favor readers
* and notify poll waiters only if no reader was awakened, 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 &&
ramlog_bufferused(priv) >= CONFIG_RAMLOG_POLLTHRESHOLD)
{ {
/* Notify all poll/select waiters that they can read from the /* Notify all poll/select waiters that they can read from the
* FIFO. * FIFO.
@ -547,14 +513,7 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
* anything already before waiting. * anything already before waiting.
*/ */
nread = ret; return ret;
/* Break out to return what we have. Note, we can't exactly
* "break" out because whichever error occurred, we do not hold
* the exclusion mutex.
*/
goto errout_without_lock;
} }
#endif /* CONFIG_RAMLOG_NONBLOCKING */ #endif /* CONFIG_RAMLOG_NONBLOCKING */
} }
@ -585,17 +544,6 @@ static ssize_t ramlog_file_read(FAR struct file *filep, FAR char *buffer,
nxmutex_unlock(&priv->rl_lock); nxmutex_unlock(&priv->rl_lock);
/* Notify all poll/select waiters that they can write to the FIFO */
#ifndef CONFIG_RAMLOG_NONBLOCKING
errout_without_lock:
#endif
if (nread > 0)
{
ramlog_pollnotify(priv, POLLOUT);
}
/* Return the number of characters actually read */ /* Return the number of characters actually read */
return nread; return nread;
@ -662,9 +610,8 @@ static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
{ {
FAR struct inode *inode = filep->f_inode; FAR struct inode *inode = filep->f_inode;
FAR struct ramlog_dev_s *priv; FAR struct ramlog_dev_s *priv;
pollevent_t eventset; pollevent_t eventset = POLLOUT;
irqstate_t flags; irqstate_t flags;
size_t next_head;
int ret; int ret;
int i; int i;
@ -712,21 +659,7 @@ static int ramlog_file_poll(FAR struct file *filep, FAR struct pollfd *fds,
/* Should immediately notify on any of the requested events? */ /* Should immediately notify on any of the requested events? */
eventset = 0;
flags = enter_critical_section(); flags = enter_critical_section();
next_head = priv->rl_head + 1;
if (next_head >= priv->rl_bufsize)
{
next_head = 0;
}
/* First, check if the receive buffer is not full. */
if (next_head != priv->rl_tail)
{
eventset |= POLLOUT;
}
/* Check if the receive buffer is not empty. */ /* Check if the receive buffer is not empty. */
@ -846,38 +779,20 @@ void ramlog_syslog_register(void)
int ramlog_putc(FAR struct syslog_channel_s *channel, int ch) int ramlog_putc(FAR struct syslog_channel_s *channel, int ch)
{ {
FAR struct ramlog_dev_s *priv = &g_sysdev; FAR struct ramlog_dev_s *priv = &g_sysdev;
int readers_waken = 0;
int ret;
UNUSED(channel); UNUSED(channel);
/* Add the character to the RAMLOG */ /* Add the character to the RAMLOG */
ret = ramlog_addchar(priv, ch); ramlog_addchar(priv, ch);
if (ret < 0)
{
/* The buffer is full and 'ch' was not saved. */
return ret;
}
#ifndef CONFIG_RAMLOG_NONBLOCKING #ifndef CONFIG_RAMLOG_NONBLOCKING
/* Are there threads waiting for read data? */ /* Are there threads waiting for read data? */
readers_waken = ramlog_readnotify(priv); ramlog_readnotify(priv);
#endif #endif
/* If there are multiple readers, some of them might block despite if (ramlog_bufferused(priv) >= CONFIG_RAMLOG_POLLTHRESHOLD)
* POLLIN because first reader might read all data. Favor readers
* and notify poll waiters only if no reader was awakened, 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 &&
ramlog_bufferused(priv) >= CONFIG_RAMLOG_POLLTHRESHOLD)
{ {
/* Notify all poll/select waiters that they can read from the FIFO */ /* Notify all poll/select waiters that they can read from the FIFO */