This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 875e86bd35d syslog/ramlog: Survive writes made before the OS is ready.
875e86bd35d is described below
commit 875e86bd35db31ddfa99a2e21ed01807fff6725b
Author: Justin Hammond <[email protected]>
AuthorDate: Fri Aug 7 10:09:40 2026 +0800
syslog/ramlog: Survive writes made before the OS is ready.
The RAM log is the natural home for boot messages, yet writing to it
during early boot could crash the system it was meant to describe.
ramlog_addbuf took the critical section on every write, and
enter_critical_section consults the current task; on ports whose
first syslog output happens before the task lists exist, that lookup
walks uninitialized state and faults. The notification path was
worse still, locking a scheduler that did not exist yet.
Guard both. Before the task lists exist, plain interrupt masking
protects the buffer just as well, since there is only one thread of
control; and readers are only notified once there is an operating
system to notify them through. The bytes land in the buffer either
way, so nothing logged before the OS is ready is lost.
Found on the EIC7700X port, which logs from its start routine before
the MMU is up: enabling RAMLOG_SYSLOG there turned the boot into a
silent wedge two characters in. With this change the same
configuration boots and `dmesg` replays the full early history.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <[email protected]>
---
drivers/syslog/ramlog.c | 46 ++++++++++++++++++++++++++++++++++++++++------
1 file changed, 40 insertions(+), 6 deletions(-)
diff --git a/drivers/syslog/ramlog.c b/drivers/syslog/ramlog.c
index 0e2ac3401b3..e35a65ae0a3 100644
--- a/drivers/syslog/ramlog.c
+++ b/drivers/syslog/ramlog.c
@@ -43,6 +43,7 @@
#include <sys/boardctl.h>
#include <nuttx/arch.h>
+#include <nuttx/init.h>
#include <nuttx/kmalloc.h>
#include <nuttx/spinlock.h>
#include <nuttx/semaphore.h>
@@ -365,13 +366,34 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s
*priv,
size_t buflen = len;
irqstate_t flags;
- /* Disable interrupts (in case we are NOT called from interrupt handler) */
+ /* Disable interrupts (in case we are NOT called from interrupt handler).
+ *
+ * Not enter_critical_section(): it consults the current task, and on
+ * some ports this channel takes syslog output before the task lists
+ * exist. Masking interrupts protects the buffer just as well while
+ * there is only one thread of control.
+ */
- flags = enter_critical_section();
+ if (OSINIT_TASK_READY())
+ {
+ flags = enter_critical_section();
+ }
+ else
+ {
+ flags = up_irq_save();
+ }
if (ramlog_ratelimit(priv))
{
- leave_critical_section(flags);
+ if (OSINIT_TASK_READY())
+ {
+ leave_critical_section(flags);
+ }
+ else
+ {
+ up_irq_restore(flags);
+ }
+
return len;
}
@@ -391,9 +413,13 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
ramlog_copybuf(priv, buffer, buflen);
- /* Was anything written? */
+ /* Was anything written? Notify only once the scheduler exists; early
+ * boot output reaches here long before it does, and locking a scheduler
+ * that is not there yet faults. The bytes land in the buffer either
+ * way.
+ */
- if (len > 0)
+ if (len > 0 && OSINIT_OS_READY())
{
/* Lock the scheduler do NOT switch out */
@@ -424,7 +450,15 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
* probably retry, causing same error condition again.
*/
- leave_critical_section(flags);
+ if (OSINIT_TASK_READY())
+ {
+ leave_critical_section(flags);
+ }
+ else
+ {
+ up_irq_restore(flags);
+ }
+
return len;
}