diff --git a/drivers/syslog/ramlog.c b/drivers/syslog/ramlog.c index df65b4d414..e1839004e5 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 }; @@ -286,12 +286,89 @@ again: return OK; } +/**************************************************************************** + * 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 2357993cc5..c05c4ba1df 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 0d13010d15..a71f02eb34 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 }