From d481b10f63a800f5ea5853eec55ee8b96ed96ed5 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Mon, 11 Aug 2025 17:27:24 +0800 Subject: [PATCH] Polish the Rust doc of OSTD's logger module --- ostd/src/logger.rs | 57 +++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/ostd/src/logger.rs b/ostd/src/logger.rs index 31a700d41..a7ddbfcd2 100644 --- a/ostd/src/logger.rs +++ b/ostd/src/logger.rs @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MPL-2.0 -//! Logging support. +//! Logger injection. //! -//! This module provides a default log implementation while allowing users to inject -//! their own logger at a higher level. +//! OSTD allows its client to inject a custom implementation of logger. +//! If no such logger is injected, +//! then OSTD falls back to a built-in logger that +//! simply dumps all log records with [`crate::console::early_print`]. //! -//! Generally IRQs are disabled while printing. So do not print long log messages. +//! OSTD's logger facility relies on the [log] crate. +//! Both an OSTD client and OSTD itself use the macros from the `log` crate +//! such as `error`, `info`, and `debug` to emit log records. +//! The injected logger is required to implement the [`log::Log`] trait. +//! +//! [log]: https://docs.rs/log use core::str::FromStr; @@ -14,6 +21,29 @@ use spin::Once; use crate::boot::EARLY_INFO; +/// Injects a logger. +/// +/// This method can be called at most once; calling it more than once has no effect. +/// +/// # Requirements +/// +/// As the logger may be invoked in stringent situations, +/// such as an interrupt handler, an out-of-memory handler, or a panic handler, +/// a logger should be implemented to be +/// _short_ (simple and non-sleeping) and +/// _heapless_ (not trigger heap allocations). +/// Failing to do so may cause the kernel to panic or deadlock. +pub fn inject_logger(new_logger: &'static dyn log::Log) { + LOGGER.backend.call_once(|| new_logger); +} + +/// Initializes the logger. Users should avoid using the log macros before this function is called. +pub(crate) fn init() { + let level = get_log_level().unwrap_or(LevelFilter::Off); + log::set_max_level(level); + log::set_logger(&LOGGER).unwrap(); +} + static LOGGER: Logger = Logger::new(); struct Logger { @@ -28,18 +58,6 @@ impl Logger { } } -/// Injects a logger as the global logger backend. -/// -/// This method allows upper-level users to inject their own implemented loggers, -/// but only allows injecting once. Subsequent injection will have no effect. -/// -/// **Caution**: The implementation of log operation in the injected logger should ideally be -/// heap-free and not involve sleep operations. Otherwise, users should refrain from calling `log` -/// in sensitive locations, such as during heap allocations, as this may cause the system to block. -pub fn inject_logger(new_logger: &'static dyn log::Log) { - LOGGER.backend.call_once(|| new_logger); -} - impl log::Log for Logger { fn enabled(&self, metadata: &Metadata) -> bool { if let Some(logger) = self.backend.get() { @@ -67,13 +85,6 @@ impl log::Log for Logger { } } -/// Initialize the logger. Users should avoid using the log macros before this function is called. -pub(crate) fn init() { - let level = get_log_level().unwrap_or(LevelFilter::Off); - log::set_max_level(level); - log::set_logger(&LOGGER).unwrap(); -} - fn get_log_level() -> Option { let kcmdline = EARLY_INFO.get().unwrap().kernel_cmdline;