Move the log lock to a better location

This commit is contained in:
Ruihan Li 2025-04-15 22:22:07 +08:00 committed by Tate, Hongliang Tian
parent 67e5e5a651
commit d6e40933b8
6 changed files with 46 additions and 73 deletions

View File

@ -15,12 +15,6 @@ impl log::Log for AsterLogger {
fn log(&self, record: &Record) { fn log(&self, record: &Record) {
let timestamp = Jiffies::elapsed().as_duration().as_secs_f64(); let timestamp = Jiffies::elapsed().as_duration().as_secs_f64();
// Use a global lock to prevent interleaving of log messages.
use ostd::sync::SpinLock;
static RECORD_LOCK: SpinLock<()> = SpinLock::new(());
let _lock = RECORD_LOCK.disable_irq().lock();
print_logs(record, timestamp); print_logs(record, timestamp);
} }

View File

@ -5,26 +5,34 @@
//! FIXME: It will print to all `virtio-console` devices, which is not a good choice. //! FIXME: It will print to all `virtio-console` devices, which is not a good choice.
//! //!
use core::fmt::{Arguments, Write}; use alloc::{collections::btree_map::BTreeMap, fmt, string::String, sync::Arc};
use core::fmt::Write;
struct VirtioConsolesPrinter; use aster_console::AnyConsoleDevice;
use ostd::sync::{LocalIrqDisabled, SpinLockGuard};
impl Write for VirtioConsolesPrinter { /// Prints the formatted arguments to the standard output.
fn write_str(&mut self, s: &str) -> core::fmt::Result { pub fn _print(args: fmt::Arguments) {
// We must call `all_devices_lock` instead of `all_devices` here, as `all_devices` invokes // We must call `all_devices_lock` instead of `all_devices` here, as `all_devices` invokes the
// the clone method of String and Arc, which may lead to a deadlock when there is low memory // `clone` method of `String` and `Arc`, which may lead to a deadlock when there is low memory
// in the heap (The heap allocator will log a message when memory is low.). // in the heap. (The heap allocator will log a message when memory is low.)
//
// Also, holding the lock will prevent the logs from interleaving.
let devices = aster_console::all_devices_lock(); let devices = aster_console::all_devices_lock();
for (_, device) in devices.iter() {
device.send(s.as_bytes()); struct Printer<'a>(
} SpinLockGuard<'a, BTreeMap<String, Arc<dyn AnyConsoleDevice>>, LocalIrqDisabled>,
);
impl Write for Printer<'_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.0
.values()
.for_each(|console| console.send(s.as_bytes()));
Ok(()) Ok(())
} }
} }
/// Prints the formatted arguments to the standard output. Printer(devices).write_fmt(args).unwrap();
pub fn _print(args: Arguments) {
VirtioConsolesPrinter.write_fmt(args).unwrap();
} }
/// Copied from Rust std: <https://github.com/rust-lang/rust/blob/master/library/std/src/macros.rs> /// Copied from Rust std: <https://github.com/rust-lang/rust/blob/master/library/std/src/macros.rs>

View File

@ -2,26 +2,6 @@
//! The console I/O. //! The console I/O.
use alloc::fmt;
use core::fmt::Write;
/// Prints the formatted arguments to the standard output using the serial port.
#[inline]
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
for &c in s.as_bytes() {
send(c);
}
Ok(())
}
}
/// Initializes the serial port. /// Initializes the serial port.
pub(crate) fn init() {} pub(crate) fn init() {}

View File

@ -2,29 +2,9 @@
//! The console I/O. //! The console I/O.
use alloc::fmt;
use core::fmt::Write;
use super::device::serial::SerialPort; use super::device::serial::SerialPort;
use crate::io::reserve_io_port_range; use crate::io::reserve_io_port_range;
/// Prints the formatted arguments to the standard output using the serial port.
#[inline]
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
for &c in s.as_bytes() {
send(c);
}
Ok(())
}
}
bitflags::bitflags! { bitflags::bitflags! {
struct LineSts: u8 { struct LineSts: u8 {
const INPUT_FULL = 1; const INPUT_FULL = 1;

View File

@ -2,16 +2,34 @@
//! Console output. //! Console output.
use core::fmt::Arguments; use core::fmt::{self, Arguments, Write};
use crate::if_tdx_enabled; use crate::{
if_tdx_enabled,
sync::{LocalIrqDisabled, SpinLock},
};
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
for &c in s.as_bytes() {
crate::arch::serial::send(c);
}
Ok(())
}
}
static STDOUT: SpinLock<Stdout, LocalIrqDisabled> = SpinLock::new(Stdout);
/// Prints formatted arguments to the console. /// Prints formatted arguments to the console.
pub fn early_print(args: Arguments) { pub fn early_print(args: Arguments) {
if_tdx_enabled!({ if_tdx_enabled!({
// Hold the lock to prevent the logs from interleaving.
let _guard = STDOUT.lock();
tdx_guest::print(args); tdx_guest::print(args);
} else { } else {
crate::arch::serial::print(args); STDOUT.lock().write_fmt(args).unwrap();
}); });
} }

View File

@ -56,14 +56,7 @@ impl log::Log for Logger {
}; };
// Default implementation. // Default implementation.
let level = record.level(); let level = record.level();
// Use a global lock to prevent interleaving of log messages.
use crate::sync::SpinLock;
static RECORD_LOCK: SpinLock<()> = SpinLock::new(());
let _lock = RECORD_LOCK.disable_irq().lock();
crate::console::early_print(format_args!("{}: {}\n", level, record.args())); crate::console::early_print(format_args!("{}: {}\n", level, record.args()));
} }