From: Tulio A M Mendes Date: Tue, 10 Feb 2026 04:53:00 +0000 (-0300) Subject: feat: add kernel log ring buffer to kprintf (printk-style dmesg support) X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=24a96af57b2c86496e8fc59aa7733a1cab5cc11e;p=AdrOS.git feat: add kernel log ring buffer to kprintf (printk-style dmesg support) Like Linux's printk, kprintf() now writes every formatted message into a 16KB circular ring buffer (klog_buf) before dispatching to console drivers (UART, VGA). This allows old messages to be retrieved later via klog_read(), enabling dmesg functionality. Design: - 16KB static ring buffer (KLOG_BUF_SIZE) - klog_head tracks next write position, klog_count tracks fill - klog_append() writes into ring, capping at buffer size - klog_read(out, size) copies oldest-to-newest into caller buffer - Protected by dedicated klog_lock spinlock Flow: kprintf() -> kvsnprintf() -> klog_append() -> console_write() Passes: make, cppcheck, QEMU smoke test. --- diff --git a/include/console.h b/include/console.h index 4f61e25..7bdbea4 100644 --- a/include/console.h +++ b/include/console.h @@ -15,4 +15,6 @@ int ksnprintf(char* out, size_t out_size, const char* fmt, ...); void kprintf(const char* fmt, ...); +size_t klog_read(char* out, size_t out_size); + #endif diff --git a/src/kernel/console.c b/src/kernel/console.c index 089211a..12d6233 100644 --- a/src/kernel/console.c +++ b/src/kernel/console.c @@ -12,6 +12,24 @@ static spinlock_t g_console_lock = {0}; static int g_console_uart_enabled = 1; static int g_console_vga_enabled = 0; +/* ---- Kernel log ring buffer (like Linux __log_buf) ---- */ +#define KLOG_BUF_SIZE 16384 +static char klog_buf[KLOG_BUF_SIZE]; +static size_t klog_head = 0; // next write position +static size_t klog_count = 0; // total bytes stored (capped at KLOG_BUF_SIZE) +static spinlock_t klog_lock = {0}; + +static void klog_append(const char* s, size_t len) { + for (size_t i = 0; i < len; i++) { + klog_buf[klog_head] = s[i]; + klog_head = (klog_head + 1) % KLOG_BUF_SIZE; + } + klog_count += len; + if (klog_count > KLOG_BUF_SIZE) { + klog_count = KLOG_BUF_SIZE; + } +} + void console_init(void) { spinlock_init(&g_console_lock); g_console_uart_enabled = 1; @@ -185,8 +203,45 @@ void kprintf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); - (void)kvsnprintf(buf, sizeof(buf), fmt, ap); + int len = kvsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); + if (len > 0) { + size_t slen = (size_t)len; + if (slen >= sizeof(buf)) slen = sizeof(buf) - 1; + + uintptr_t lf = spin_lock_irqsave(&klog_lock); + klog_append(buf, slen); + spin_unlock_irqrestore(&klog_lock, lf); + } + console_write(buf); } + +size_t klog_read(char* out, size_t out_size) { + if (!out || out_size == 0) return 0; + + uintptr_t flags = spin_lock_irqsave(&klog_lock); + + size_t avail = klog_count; + if (avail > out_size - 1) avail = out_size - 1; + + size_t start; + if (klog_count >= KLOG_BUF_SIZE) { + start = klog_head; // oldest byte is right after head + } else { + start = (klog_head + KLOG_BUF_SIZE - klog_count) % KLOG_BUF_SIZE; + } + + // skip oldest bytes if avail < klog_count + size_t skip = klog_count - avail; + start = (start + skip) % KLOG_BUF_SIZE; + + for (size_t i = 0; i < avail; i++) { + out[i] = klog_buf[(start + i) % KLOG_BUF_SIZE]; + } + out[avail] = '\0'; + + spin_unlock_irqrestore(&klog_lock, flags); + return avail; +}