diff --git a/framework/jinux-frame/src/bus/pci/capability/mod.rs b/framework/jinux-frame/src/bus/pci/capability/mod.rs index 2072ba7c2..92cb145af 100644 --- a/framework/jinux-frame/src/bus/pci/capability/mod.rs +++ b/framework/jinux-frame/src/bus/pci/capability/mod.rs @@ -87,7 +87,8 @@ impl Capability { // read all cap_ptr so that it is easy for us to get the length. while cap_ptr > 0 { cap_ptr_vec.push(cap_ptr); - cap_ptr = dev.location().read8(cap_ptr + 1) as u16 & PciDeviceLocation::BIT32_ALIGN_MASK; + cap_ptr = + dev.location().read8(cap_ptr + 1) as u16 & PciDeviceLocation::BIT32_ALIGN_MASK; } cap_ptr_vec.sort(); // Push here so that we can calculate the length of the last capability. diff --git a/framework/jinux-frame/src/lib.rs b/framework/jinux-frame/src/lib.rs index 2ce684b64..f6122a615 100644 --- a/framework/jinux-frame/src/lib.rs +++ b/framework/jinux-frame/src/lib.rs @@ -23,8 +23,8 @@ pub mod bus; pub mod config; pub mod cpu; mod error; -pub mod logger; pub mod io_mem; +pub mod logger; pub mod prelude; pub mod sync; pub mod task; diff --git a/framework/jinux-frame/src/sync/mod.rs b/framework/jinux-frame/src/sync/mod.rs index a2f554f5f..b3b8f62b0 100644 --- a/framework/jinux-frame/src/sync/mod.rs +++ b/framework/jinux-frame/src/sync/mod.rs @@ -9,9 +9,6 @@ mod wait; pub use self::atomic_bits::AtomicBits; pub use self::mutex::{Mutex, MutexGuard}; pub use self::rcu::{pass_quiescent_state, OwnerPtr, Rcu, RcuReadGuard, RcuReclaimer}; -pub use self::rwlock::{ - RwLock, RwLockReadGuard, RwLockReadIrqDisabledGuard, RwLockWriteGuard, - RwLockWriteIrqDisabledGuard, -}; -pub use self::spin::{SpinLock, SpinLockGuard, SpinLockIrqDisabledGuard}; +pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; +pub use self::spin::{SpinLock, SpinLockGuard}; pub use self::wait::WaitQueue; diff --git a/framework/jinux-frame/src/sync/rwlock.rs b/framework/jinux-frame/src/sync/rwlock.rs index 6a9ddcc48..b8b9da3be 100644 --- a/framework/jinux-frame/src/sync/rwlock.rs +++ b/framework/jinux-frame/src/sync/rwlock.rs @@ -4,6 +4,7 @@ use core::ops::{Deref, DerefMut}; use core::sync::atomic::AtomicUsize; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use crate::task::{disable_preempt, DisablePreemptGuard}; use crate::trap::disable_local; use crate::trap::DisabledLocalIrqGuard; @@ -37,7 +38,7 @@ impl RwLock { /// This method runs in a busy loop until the lock can be acquired (when there are /// no writers). /// After acquiring the spin lock, all interrupts are disabled. - pub fn read_irq_disabled(&self) -> RwLockReadIrqDisabledGuard { + pub fn read_irq_disabled(&self) -> RwLockReadGuard { loop { if let Some(readguard) = self.try_read_irq_disabled() { return readguard; @@ -53,7 +54,7 @@ impl RwLock { /// This method runs in a busy loop until the lock can be acquired (when there are /// no writers and readers). /// After acquiring the spin lock, all interrupts are disabled. - pub fn write_irq_disabled(&self) -> RwLockWriteIrqDisabledGuard { + pub fn write_irq_disabled(&self) -> RwLockWriteGuard { loop { if let Some(writeguard) = self.try_write_irq_disabled() { return writeguard; @@ -64,14 +65,13 @@ impl RwLock { } /// Try acquire a read lock with disabling local IRQs. - pub fn try_read_irq_disabled(&self) -> Option> { - // FIXME: add disable_preemption + pub fn try_read_irq_disabled(&self) -> Option> { let irq_guard = disable_local(); let lock = self.lock.fetch_add(READER, Acquire); if lock & (WRITER | MAX_READER) == 0 { - Some(RwLockReadIrqDisabledGuard { + Some(RwLockReadGuard { inner: &self, - irq_guard, + inner_guard: InnerGuard::IrqGuard(irq_guard), }) } else { self.lock.fetch_sub(READER, Release); @@ -80,17 +80,16 @@ impl RwLock { } /// Try acquire a write lock with disabling local IRQs. - pub fn try_write_irq_disabled(&self) -> Option> { - // FIXME: add disable_preemption + pub fn try_write_irq_disabled(&self) -> Option> { let irq_guard = disable_local(); if self .lock .compare_exchange(0, WRITER, Acquire, Relaxed) .is_ok() { - Some(RwLockWriteIrqDisabledGuard { + Some(RwLockWriteGuard { inner: &self, - irq_guard, + inner_guard: InnerGuard::IrqGuard(irq_guard), }) } else { None @@ -127,10 +126,13 @@ impl RwLock { /// Try acquire a read lock without disabling the local IRQs. pub fn try_read(&self) -> Option> { - // FIXME: add disable_preemption + let guard = disable_preempt(); let lock = self.lock.fetch_add(READER, Acquire); if lock & (WRITER | MAX_READER) == 0 { - Some(RwLockReadGuard { inner: &self }) + Some(RwLockReadGuard { + inner: &self, + inner_guard: InnerGuard::PreemptGuard(guard), + }) } else { self.lock.fetch_sub(READER, Release); None @@ -139,13 +141,16 @@ impl RwLock { /// Try acquire a write lock without disabling the local IRQs. pub fn try_write(&self) -> Option> { - // FIXME: add disable_preemption + let guard = disable_preempt(); if self .lock .compare_exchange(0, WRITER, Acquire, Relaxed) .is_ok() { - Some(RwLockWriteGuard { inner: &self }) + Some(RwLockWriteGuard { + inner: &self, + inner_guard: InnerGuard::PreemptGuard(guard), + }) } else { None } @@ -163,103 +168,21 @@ impl fmt::Debug for RwLock { unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} -impl<'a, T> !Send for RwLockWriteIrqDisabledGuard<'a, T> {} -unsafe impl Sync for RwLockWriteIrqDisabledGuard<'_, T> {} - -impl<'a, T> !Send for RwLockReadIrqDisabledGuard<'a, T> {} -unsafe impl Sync for RwLockReadIrqDisabledGuard<'_, T> {} - -/// The guard of a read lock that disables the local IRQs. -pub struct RwLockReadIrqDisabledGuard<'a, T> { - inner: &'a RwLock, - irq_guard: DisabledLocalIrqGuard, -} - -/// Upgrade a read lock that disables the local IRQs to a write lock. -/// -/// This method first release the old read lock and then aquire a new write lock. -/// So it may not return the guard immidiately -/// due to other readers or another writer. -impl<'a, T> RwLockReadIrqDisabledGuard<'a, T> { - pub fn upgrade(mut self) -> RwLockWriteIrqDisabledGuard<'a, T> { - let inner = self.inner; - let irq_guard = self.irq_guard.transfer_to(); - drop(self); - while inner - .lock - .compare_exchange(0, WRITER, Acquire, Relaxed) - .is_err() - { - core::hint::spin_loop(); - } - RwLockWriteIrqDisabledGuard { inner, irq_guard } - } -} - -impl<'a, T> Deref for RwLockReadIrqDisabledGuard<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.inner.val.get() } - } -} - -impl<'a, T> Drop for RwLockReadIrqDisabledGuard<'a, T> { - fn drop(&mut self) { - self.inner.lock.fetch_sub(READER, Release); - } -} - -/// The guard of a write lock that disables the local IRQs. -pub struct RwLockWriteIrqDisabledGuard<'a, T> { - inner: &'a RwLock, - irq_guard: DisabledLocalIrqGuard, -} - -/// Downgrade a write lock that disables the local IRQs to a read lock. -/// -/// This method can return the read guard immidiately -/// due to there must be no other users. -impl<'a, T> RwLockWriteIrqDisabledGuard<'a, T> { - pub fn downgrade(mut self) -> RwLockReadIrqDisabledGuard<'a, T> { - self.inner.lock.fetch_add(READER, Acquire); - let inner = self.inner; - let irq_guard = self.irq_guard.transfer_to(); - drop(self); - let irq_guard = disable_local(); - RwLockReadIrqDisabledGuard { inner, irq_guard } - } -} - -impl<'a, T> Deref for RwLockWriteIrqDisabledGuard<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.inner.val.get() } - } -} - -impl<'a, T> DerefMut for RwLockWriteIrqDisabledGuard<'a, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut *self.inner.val.get() } - } -} - -impl<'a, T> Drop for RwLockWriteIrqDisabledGuard<'a, T> { - fn drop(&mut self) { - self.inner.lock.fetch_and(!(WRITER), Release); - } -} - impl<'a, T> !Send for RwLockWriteGuard<'a, T> {} unsafe impl Sync for RwLockWriteGuard<'_, T> {} impl<'a, T> !Send for RwLockReadGuard<'a, T> {} unsafe impl Sync for RwLockReadGuard<'_, T> {} +enum InnerGuard { + IrqGuard(DisabledLocalIrqGuard), + PreemptGuard(DisablePreemptGuard), +} + /// The guard of the read lock. pub struct RwLockReadGuard<'a, T> { inner: &'a RwLock, + inner_guard: InnerGuard, } /// Upgrade a read lock to a write lock. @@ -268,8 +191,14 @@ pub struct RwLockReadGuard<'a, T> { /// So it may not return the write guard immidiately /// due to other readers or another writer. impl<'a, T> RwLockReadGuard<'a, T> { - pub fn upgrade(self) -> RwLockWriteGuard<'a, T> { + pub fn upgrade(mut self) -> RwLockWriteGuard<'a, T> { let inner = self.inner; + let inner_guard = match &mut self.inner_guard { + InnerGuard::IrqGuard(irq_guard) => InnerGuard::IrqGuard(irq_guard.transfer_to()), + InnerGuard::PreemptGuard(preempt_guard) => { + InnerGuard::PreemptGuard(preempt_guard.transfer_to()) + } + }; drop(self); while inner .lock @@ -278,7 +207,7 @@ impl<'a, T> RwLockReadGuard<'a, T> { { core::hint::spin_loop(); } - RwLockWriteGuard { inner } + RwLockWriteGuard { inner, inner_guard } } } @@ -298,6 +227,7 @@ impl<'a, T> Drop for RwLockReadGuard<'a, T> { pub struct RwLockWriteGuard<'a, T> { inner: &'a RwLock, + inner_guard: InnerGuard, } /// Downgrade a write lock to a read lock. @@ -305,11 +235,15 @@ pub struct RwLockWriteGuard<'a, T> { /// This method can return the read guard immidiately /// due to there are no other users. impl<'a, T> RwLockWriteGuard<'a, T> { - pub fn downgrade(self) -> RwLockReadGuard<'a, T> { + pub fn downgrade(mut self) -> RwLockReadGuard<'a, T> { self.inner.lock.fetch_add(READER, Acquire); let inner = self.inner; + let inner_guard = match &mut self.inner_guard { + InnerGuard::IrqGuard(irq_guard) => InnerGuard::IrqGuard(irq_guard.transfer_to()), + InnerGuard::PreemptGuard(preempt_guard) => InnerGuard::PreemptGuard(disable_preempt()), + }; drop(self); - RwLockReadGuard { inner } + RwLockReadGuard { inner, inner_guard } } } diff --git a/framework/jinux-frame/src/sync/spin.rs b/framework/jinux-frame/src/sync/spin.rs index b3a4860e0..0349110a0 100644 --- a/framework/jinux-frame/src/sync/spin.rs +++ b/framework/jinux-frame/src/sync/spin.rs @@ -3,6 +3,7 @@ use core::fmt; use core::ops::{Deref, DerefMut}; use core::sync::atomic::{AtomicBool, Ordering}; +use crate::task::{disable_preempt, DisablePreemptGuard}; use crate::trap::disable_local; use crate::trap::DisabledLocalIrqGuard; @@ -26,24 +27,22 @@ impl SpinLock { /// /// This method runs in a busy loop until the lock can be acquired. /// After acquiring the spin lock, all interrupts are disabled. - pub fn lock_irq_disabled(&self) -> SpinLockIrqDisabledGuard { - // FIXME: add disable_preemption + pub fn lock_irq_disabled(&self) -> SpinLockGuard { let guard = disable_local(); self.acquire_lock(); - SpinLockIrqDisabledGuard { + SpinLockGuard { lock: &self, - irq_guard: guard, + inner_guard: InnerGuard::IrqGuard(guard), } } /// Try acquiring the spin lock immedidately with disabling the local IRQs. - pub fn try_lock_irq_disabled(&self) -> Option> { - // FIXME: add disable_preemption + pub fn try_lock_irq_disabled(&self) -> Option> { let irq_guard = disable_local(); if self.try_acquire_lock() { - let lock_guard = SpinLockIrqDisabledGuard { + let lock_guard = SpinLockGuard { lock: &self, - irq_guard, + inner_guard: InnerGuard::IrqGuard(irq_guard), }; return Some(lock_guard); } @@ -59,16 +58,22 @@ impl SpinLock { /// in the interrupt context, then it is ok to use this method /// in the process context. pub fn lock(&self) -> SpinLockGuard { - // FIXME: add disable_preemption + let guard = disable_preempt(); self.acquire_lock(); - SpinLockGuard { lock: &self } + SpinLockGuard { + lock: &self, + inner_guard: InnerGuard::PreemptGuard(guard), + } } /// Try acquiring the spin lock immedidately without disabling the local IRQs. pub fn try_lock(&self) -> Option> { - // FIXME: add disable_preemption + let guard = disable_preempt(); if self.try_acquire_lock() { - let lock_guard = SpinLockGuard { lock: &self }; + let lock_guard = SpinLockGuard { + lock: &self, + inner_guard: InnerGuard::PreemptGuard(guard), + }; return Some(lock_guard); } return None; @@ -102,46 +107,15 @@ impl fmt::Debug for SpinLock { unsafe impl Send for SpinLock {} unsafe impl Sync for SpinLock {} +enum InnerGuard { + IrqGuard(DisabledLocalIrqGuard), + PreemptGuard(DisablePreemptGuard), +} + /// The guard of a spin lock that disables the local IRQs. -pub struct SpinLockIrqDisabledGuard<'a, T> { - lock: &'a SpinLock, - irq_guard: DisabledLocalIrqGuard, -} - -impl<'a, T> Deref for SpinLockIrqDisabledGuard<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &mut *self.lock.val.get() } - } -} - -impl<'a, T> DerefMut for SpinLockIrqDisabledGuard<'a, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut *self.lock.val.get() } - } -} - -impl<'a, T> Drop for SpinLockIrqDisabledGuard<'a, T> { - fn drop(&mut self) { - self.lock.release_lock(); - } -} - -impl<'a, T: fmt::Debug> fmt::Debug for SpinLockIrqDisabledGuard<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<'a, T> !Send for SpinLockIrqDisabledGuard<'a, T> {} - -// Safety. `SpinLockIrqDisabledGuard` can be shared between tasks/threads in same CPU. -// As `lock_irq_disabled()` disables interrupts to prevent race conditions caused by interrupts. -unsafe impl Sync for SpinLockIrqDisabledGuard<'_, T> {} - pub struct SpinLockGuard<'a, T> { lock: &'a SpinLock, + inner_guard: InnerGuard, } impl<'a, T> Deref for SpinLockGuard<'a, T> { diff --git a/framework/jinux-frame/src/task/mod.rs b/framework/jinux-frame/src/task/mod.rs index 5548defac..d172bbe8c 100644 --- a/framework/jinux-frame/src/task/mod.rs +++ b/framework/jinux-frame/src/task/mod.rs @@ -5,6 +5,6 @@ mod scheduler; #[allow(clippy::module_inception)] mod task; -pub use self::processor::{current_task, schedule}; +pub use self::processor::{current_task, disable_preempt, schedule, DisablePreemptGuard}; pub use self::scheduler::{add_task, set_scheduler, Scheduler}; pub use self::task::{Task, TaskAdapter, TaskStatus}; diff --git a/framework/jinux-frame/src/task/processor.rs b/framework/jinux-frame/src/task/processor.rs index e2892d9bc..15ba79d07 100644 --- a/framework/jinux-frame/src/task/processor.rs +++ b/framework/jinux-frame/src/task/processor.rs @@ -1,3 +1,10 @@ +use core::sync::atomic::AtomicUsize; + +use crate::cpu::CpuLocal; +use crate::cpu_local; + +use core::sync::atomic::Ordering::Relaxed; + use super::{ scheduler::{fetch_task, GLOBAL_SCHEDULER}, task::{context_switch, TaskContext}, @@ -5,6 +12,7 @@ use super::{ }; use alloc::sync::Arc; use lazy_static::lazy_static; +use log::warn; use spin::Mutex; pub struct Processor { @@ -64,6 +72,14 @@ pub fn schedule() { /// /// before context switch, current task will switch to the next task pub fn switch_to_task(next_task: Arc) { + if !PREEMPT_COUNT.is_preemptive() { + panic!( + "Calling schedule() while holding {} locks", + PREEMPT_COUNT.num_locks() + ); + //GLOBAL_SCHEDULER.lock_irq_disabled().enqueue(next_task); + //return; + } let current_task_option = current_task(); let next_task_cx_ptr = &next_task.inner_ctx() as *const TaskContext; let current_task: Arc; @@ -85,3 +101,70 @@ pub fn switch_to_task(next_task: Arc) { context_switch(current_task_cx_ptr, next_task_cx_ptr); } } + +cpu_local! { + static PREEMPT_COUNT: PreemptInfo = PreemptInfo::new(); +} + +/// Currently, ``PreemptInfo`` only holds the number of spin +/// locks held by the current CPU. When it has a non-zero value, +/// the CPU cannot call ``schedule()``. +struct PreemptInfo { + num_locks: AtomicUsize, +} + +impl PreemptInfo { + const fn new() -> Self { + Self { + num_locks: AtomicUsize::new(0), + } + } + + fn incease_num_locks(&self) { + self.num_locks.fetch_add(1, Relaxed); + } + + fn decrease_num_locks(&self) { + self.num_locks.fetch_sub(1, Relaxed); + } + + fn is_preemptive(&self) -> bool { + self.num_locks.load(Relaxed) == 0 + } + + fn num_locks(&self) -> usize { + self.num_locks.load(Relaxed) + } +} + +/// a guard for disable preempt. +pub struct DisablePreemptGuard { + // This private field prevents user from constructing values of this type directly. + private: (), +} + +impl !Send for DisablePreemptGuard {} + +impl DisablePreemptGuard { + fn new() -> Self { + PREEMPT_COUNT.incease_num_locks(); + Self { private: () } + } + + /// Transfer this guard to a new guard. + /// This guard must be dropped after this function. + pub fn transfer_to(&self) -> Self { + disable_preempt() + } +} + +impl Drop for DisablePreemptGuard { + fn drop(&mut self) { + PREEMPT_COUNT.decrease_num_locks(); + } +} + +#[must_use] +pub fn disable_preempt() -> DisablePreemptGuard { + DisablePreemptGuard::new() +} diff --git a/framework/jinux-frame/src/trap/irq.rs b/framework/jinux-frame/src/trap/irq.rs index 708b83ac5..a384a1ff4 100644 --- a/framework/jinux-frame/src/trap/irq.rs +++ b/framework/jinux-frame/src/trap/irq.rs @@ -1,12 +1,10 @@ use crate::arch::irq; use crate::arch::irq::{IRQ_LIST, NOT_USING_IRQ}; -use crate::cpu::CpuLocal; -use crate::cpu_local; +use crate::task::{disable_preempt, DisablePreemptGuard}; use crate::util::recycle_allocator::RecycleAllocator; use crate::{prelude::*, Error}; use core::fmt::Debug; -use core::sync::atomic::{AtomicBool, AtomicU32, Ordering::Relaxed}; use spin::{Mutex, MutexGuard}; use trapframe::TrapFrame; @@ -198,6 +196,7 @@ pub fn disable_local() -> DisabledLocalIrqGuard { /// A guard for disabled local IRQs. pub struct DisabledLocalIrqGuard { was_enabled: bool, + preempt_guard: DisablePreemptGuard, } impl !Send for DisabledLocalIrqGuard {} @@ -208,7 +207,11 @@ impl DisabledLocalIrqGuard { if was_enabled { irq::disable_local(); } - Self { was_enabled } + let preempt_guard = disable_preempt(); + Self { + was_enabled, + preempt_guard, + } } /// Transfer the saved IRQ status of this guard to a new guard. @@ -216,7 +219,10 @@ impl DisabledLocalIrqGuard { pub fn transfer_to(&mut self) -> Self { let was_enabled = self.was_enabled; self.was_enabled = false; - Self { was_enabled } + Self { + was_enabled, + preempt_guard: disable_preempt(), + } } } diff --git a/services/comps/framebuffer/src/lib.rs b/services/comps/framebuffer/src/lib.rs index 36b42dfbe..cba12ea06 100644 --- a/services/comps/framebuffer/src/lib.rs +++ b/services/comps/framebuffer/src/lib.rs @@ -12,9 +12,7 @@ use core::{ ops::{Index, IndexMut}, }; use font8x8::UnicodeFonts; -use jinux_frame::{ - config::PAGE_SIZE, io_mem::IoMem, sync::SpinLock, vm::VmIo, arch::boot, -}; +use jinux_frame::{arch::boot, config::PAGE_SIZE, io_mem::IoMem, sync::SpinLock, vm::VmIo}; use spin::Once; #[init_component] @@ -55,7 +53,7 @@ pub(crate) fn init() { width: framebuffer.width as usize, height: framebuffer.height as usize, buffer: buffer.leak(), - }) + }); writer.unwrap() }; diff --git a/services/libs/jinux-std/src/net/iface/common.rs b/services/libs/jinux-std/src/net/iface/common.rs index bde9bd4b7..21541af1e 100644 --- a/services/libs/jinux-std/src/net/iface/common.rs +++ b/services/libs/jinux-std/src/net/iface/common.rs @@ -38,11 +38,11 @@ impl IfaceCommon { } } - pub(super) fn interface(&self) -> SpinLockIrqDisabledGuard { + pub(super) fn interface(&self) -> SpinLockGuard { self.interface.lock_irq_disabled() } - pub(super) fn sockets(&self) -> SpinLockIrqDisabledGuard> { + pub(super) fn sockets(&self) -> SpinLockGuard> { self.sockets.lock_irq_disabled() } diff --git a/services/libs/jinux-std/src/net/iface/mod.rs b/services/libs/jinux-std/src/net/iface/mod.rs index f53c44ac0..04fb0b4bb 100644 --- a/services/libs/jinux-std/src/net/iface/mod.rs +++ b/services/libs/jinux-std/src/net/iface/mod.rs @@ -65,11 +65,11 @@ mod internal { pub trait IfaceInternal { fn common(&self) -> &IfaceCommon; /// The inner socket set - fn sockets(&self) -> SpinLockIrqDisabledGuard> { + fn sockets(&self) -> SpinLockGuard> { self.common().sockets() } /// The inner iface. - fn iface_inner(&self) -> SpinLockIrqDisabledGuard { + fn iface_inner(&self) -> SpinLockGuard { self.common().interface() } /// The time we should do another poll. diff --git a/services/libs/jinux-std/src/prelude.rs b/services/libs/jinux-std/src/prelude.rs index 1b03d4186..701fe1b13 100644 --- a/services/libs/jinux-std/src/prelude.rs +++ b/services/libs/jinux-std/src/prelude.rs @@ -18,7 +18,7 @@ pub(crate) use core::ffi::CStr; pub(crate) use int_to_c_enum::TryFromInt; pub(crate) use jinux_frame::config::PAGE_SIZE; // pub(crate) use jinux_frame::sync::{Mutex, MutexGuard}; -pub(crate) use jinux_frame::sync::{SpinLock, SpinLockGuard, SpinLockIrqDisabledGuard}; +pub(crate) use jinux_frame::sync::{SpinLock, SpinLockGuard}; pub(crate) use jinux_frame::vm::Vaddr; pub(crate) use jinux_frame::{print, println}; pub(crate) use log::{debug, error, info, trace, warn};