From 82175f342e1b64fcdf5e7d96319016fdbaf9b39a Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Sat, 15 Feb 2025 20:18:30 +0200 Subject: [PATCH] debug: avoid debugging deadlocks --- kernel/driver/virtio/core/src/queue.rs | 5 ++--- kernel/libk/src/debug/mod.rs | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/kernel/driver/virtio/core/src/queue.rs b/kernel/driver/virtio/core/src/queue.rs index f3df3819..45ea0f25 100644 --- a/kernel/driver/virtio/core/src/queue.rs +++ b/kernel/driver/virtio/core/src/queue.rs @@ -1,13 +1,12 @@ //! VirtIO queue implementation. -use core::{future::poll_fn, mem::MaybeUninit, task::Poll, time::Duration}; +use core::{future::poll_fn, mem::MaybeUninit, task::Poll}; use alloc::{boxed::Box, sync::Arc}; use device_api::dma::DmaAllocator; use libk::{ dma::{BusAddress, DmaBuffer, DmaSlice, DmaSliceMut}, error::Error, - task::runtime::psleep, }; use libk_util::{ event::OneTimeEvent, hash_table::DefaultHashTable, sync::IrqSafeSpinlock, waker::QueueWaker, @@ -451,7 +450,7 @@ impl VirtQueue { if length != 0 { break; } - psleep(Duration::from_millis(1)); + core::hint::spin_loop(); } Ok(length) } diff --git a/kernel/libk/src/debug/mod.rs b/kernel/libk/src/debug/mod.rs index 8c19dece..462c92d6 100644 --- a/kernel/libk/src/debug/mod.rs +++ b/kernel/libk/src/debug/mod.rs @@ -7,15 +7,16 @@ use alloc::{ use core::{ fmt, str::FromStr, - sync::atomic::{AtomicBool, Ordering}, + sync::atomic::{AtomicBool, AtomicU32, Ordering}, }; use ring::RingLoggerSink; -use libk_util::{sync::IrqSafeSpinlock, OneTimeInit}; +use libk_util::OneTimeInit; use sink::DEBUG_SINKS; use yggdrasil_abi::error::Error; use crate::{ + arch::Cpu, fs::sysfs::{ attribute::{StringAttribute, StringAttributeOps}, object::KObject, @@ -31,7 +32,7 @@ pub use panic::{panic_log, PanicLoggerSink}; pub use ring::add_kernel_log_file; pub use sink::{add_early_sink, add_serial_sink, add_sink, disable_early_sinks, DebugSink}; -static DEBUG_LOCK: IrqSafeSpinlock<()> = IrqSafeSpinlock::new(()); +static DEBUG_LOCK: AtomicU32 = AtomicU32::new(u32::MAX); static MUTE_DEBUG: AtomicBool = AtomicBool::new(false); pub struct MuteGuard(bool); @@ -104,6 +105,17 @@ impl From for LogLevel { } } +fn lock_debug() -> bool { + let cpu = Cpu::try_local().map_or(0, |cpu| cpu.id()); + loop { + match DEBUG_LOCK.compare_exchange(u32::MAX, cpu, Ordering::Acquire, Ordering::Relaxed) { + Ok(_) => return true, + Err(x) if x == cpu => return false, + _ => core::hint::spin_loop(), + } + } +} + impl log::Log for KernelLoggerSink { fn enabled(&self, metadata: &log::Metadata) -> bool { metadata.target() != "io" @@ -120,12 +132,15 @@ impl log::Log for KernelLoggerSink { RingLoggerSink.log(record); - let _guard = DEBUG_LOCK.lock(); + if !lock_debug() { + return; + } for sink in DEBUG_SINKS.read().iter() { if sink.enabled(record.metadata()) { sink.log(record); } } + DEBUG_LOCK.store(u32::MAX, Ordering::Release); } fn flush(&self) {}