mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-18 03:56:42 +00:00
Add mutex primitive and replace mutex in Jinux
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
5277886b5d
commit
888853a6de
@ -90,7 +90,7 @@ impl UserContextApiInternal for UserContext {
|
||||
call_irq_callback_functions(&self.into_trap_frame());
|
||||
}
|
||||
|
||||
crate::arch::irq::enable_interrupts();
|
||||
crate::arch::irq::enable_local();
|
||||
if self.user_context.trap_num as u16 != SYSCALL_TRAPNUM {
|
||||
self.trap_information = TrapInformation {
|
||||
cr2: unsafe { x86::controlregs::cr2() },
|
||||
|
@ -20,6 +20,14 @@ pub(crate) fn init() {
|
||||
IRQ_LIST.call_once(|| list);
|
||||
}
|
||||
|
||||
pub(crate) fn enable_interrupts() {
|
||||
pub(crate) fn enable_local() {
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
pub(crate) fn disable_local() {
|
||||
x86_64::instructions::interrupts::disable();
|
||||
}
|
||||
|
||||
pub(crate) fn is_local_enabled() -> bool {
|
||||
x86_64::instructions::interrupts::are_enabled()
|
||||
}
|
||||
|
@ -1,8 +1,100 @@
|
||||
//! CPU.
|
||||
|
||||
use crate::trap::disable_local;
|
||||
use core::cell::UnsafeCell;
|
||||
use core::ops::Deref;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")]{
|
||||
pub use trapframe::GeneralRegs;
|
||||
pub use crate::arch::x86::cpu::*;
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines a CPU-local variable.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use crate::cpu_local;
|
||||
/// use core::cell::RefCell;
|
||||
///
|
||||
/// cpu_local! {
|
||||
/// static FOO: RefCell<u32> = RefCell::new(1);
|
||||
///
|
||||
/// #[allow(unused)]
|
||||
/// pub static BAR: RefCell<f32> = RefCell::new(1.0);
|
||||
/// }
|
||||
/// CpuLocal::borrow_with(&FOO, |val| {
|
||||
/// println!("FOO VAL: {:?}", *val);
|
||||
/// })
|
||||
///
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! cpu_local {
|
||||
// empty
|
||||
() => {};
|
||||
|
||||
// multiple declarations
|
||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => {
|
||||
$(#[$attr])* $vis static $name: CpuLocal<$t> = unsafe { CpuLocal::new($init) };
|
||||
crate::cpu_local!($($rest)*);
|
||||
};
|
||||
|
||||
// single declaration
|
||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
|
||||
// TODO: reimplement cpu-local variable to support multi-core
|
||||
$(#[$attr])* $vis static $name: CpuLocal<$t> = CpuLocal::new($init);
|
||||
);
|
||||
}
|
||||
|
||||
/// CPU-local objects.
|
||||
///
|
||||
/// A CPU-local object only gives you immutable references to the underlying value.
|
||||
/// To mutate the value, one can use atomic values (e.g., `AtomicU32`) or internally mutable
|
||||
/// objects (e.g., `RefCell`).
|
||||
///
|
||||
/// The `CpuLocal<T: Sync>` can be used directly.
|
||||
/// Otherwise, the `CpuLocal<T>` must be used through `CpuLocal::borrow_with`.
|
||||
///
|
||||
/// TODO: re-implement `CpuLocal`
|
||||
pub struct CpuLocal<T>(UnsafeCell<T>);
|
||||
|
||||
// Safety. At any given time, only one task can access the inner value T of a cpu-local variable.
|
||||
unsafe impl<T> Sync for CpuLocal<T> {}
|
||||
|
||||
impl<T> CpuLocal<T> {
|
||||
/// Initialize CPU-local object
|
||||
/// Developer cannot construct a valid CpuLocal object arbitrarily
|
||||
pub const unsafe fn new(val: T) -> Self {
|
||||
Self(UnsafeCell::new(val))
|
||||
}
|
||||
|
||||
/// Borrow an immutable reference to the underlying value and feed it to a closure.
|
||||
///
|
||||
/// During the execution of the closure, local IRQs are disabled. This ensures that
|
||||
/// the CPU-local object is only accessed by the current task or IRQ handler.
|
||||
/// As local IRQs are disabled, one should keep the closure as short as possible.
|
||||
pub fn borrow_with<U, F: FnOnce(&T) -> U>(this: &Self, f: F) -> U {
|
||||
// FIXME: implement disable preemption
|
||||
// Disable interrupts when accessing cpu-local variable
|
||||
let _guard = disable_local();
|
||||
// Safety. Now that the local IRQs are disabled, this CPU-local object can only be
|
||||
// accessed by the current task/thread. So it is safe to get its immutable reference
|
||||
// regardless of whether `T` implements `Sync` or not.
|
||||
let val_ref = unsafe { this.do_borrow() };
|
||||
f(val_ref)
|
||||
}
|
||||
|
||||
unsafe fn do_borrow(&self) -> &T {
|
||||
&*self.0.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Sync> Deref for CpuLocal<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.0.get() }
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ pub mod user;
|
||||
mod util;
|
||||
pub mod vm;
|
||||
|
||||
pub use self::cpu::CpuLocal;
|
||||
pub use self::error::Error;
|
||||
pub use self::prelude::Result;
|
||||
use alloc::vec::Vec;
|
||||
|
@ -1,95 +0,0 @@
|
||||
use super::percpu::PerCpu;
|
||||
use crate::cpu_local;
|
||||
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
use x86_64::instructions::interrupts;
|
||||
|
||||
/// Disable all IRQs on the current CPU (i.e., locally).
|
||||
///
|
||||
/// This function returns a guard object, which will automatically enable local IRQs again when
|
||||
/// it is dropped. This function works correctly even when it is called in a _nested_ way.
|
||||
/// The local IRQs shall only be re-enabled when the most outer guard is dropped.
|
||||
///
|
||||
/// This function can play nicely with `SpinLock` as the type uses this function internally.
|
||||
/// One can invoke this function even after acquiring a spin lock. And the reversed order is also ok.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ``rust
|
||||
/// use jinux_frame::irq;
|
||||
///
|
||||
/// {
|
||||
/// let _ = irq::disable_local();
|
||||
/// todo!("do something when irqs are disabled");
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn disable_local() -> DisabledLocalIrqGuard {
|
||||
DisabledLocalIrqGuard::new()
|
||||
}
|
||||
|
||||
/// A guard for disabled local IRQs.
|
||||
pub struct DisabledLocalIrqGuard {
|
||||
// Having a private field prevents user from constructing values of this type directly.
|
||||
private: (),
|
||||
}
|
||||
|
||||
impl !Send for DisabledLocalIrqGuard {}
|
||||
|
||||
cpu_local! {
|
||||
static IRQ_OFF_COUNT: IrqInfo = IrqInfo::new();
|
||||
}
|
||||
|
||||
impl DisabledLocalIrqGuard {
|
||||
fn new() -> Self {
|
||||
IRQ_OFF_COUNT.borrow().inc();
|
||||
Self { private: () }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DisabledLocalIrqGuard {
|
||||
fn drop(&mut self) {
|
||||
IRQ_OFF_COUNT.borrow().dec();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct IrqInfo {
|
||||
// number of interrupt counterpart
|
||||
off_num: AtomicU32,
|
||||
// interrupt state before calling dec()/inc()
|
||||
interrupt_enable: AtomicBool,
|
||||
}
|
||||
|
||||
impl IrqInfo {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
off_num: AtomicU32::new(0),
|
||||
interrupt_enable: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn inc(&self) {
|
||||
let enabled = interrupts::are_enabled();
|
||||
let off_num = self.off_num.load(Ordering::Relaxed);
|
||||
if off_num == 0 {
|
||||
self.interrupt_enable.store(enabled, Ordering::Relaxed);
|
||||
}
|
||||
if enabled {
|
||||
interrupts::disable();
|
||||
}
|
||||
self.off_num.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn dec(&self) {
|
||||
let off_num = self.off_num.load(Ordering::Relaxed);
|
||||
|
||||
if off_num < 1 {
|
||||
// disable_interrupt/inc() should be called before enable_interrupt/dec()
|
||||
panic!("The enable_interrupt and disable_interrupt are the counterpart");
|
||||
}
|
||||
let update_num = self.off_num.fetch_sub(1, Ordering::Relaxed) - 1;
|
||||
if update_num == 0 && self.interrupt_enable.load(Ordering::Relaxed) {
|
||||
interrupts::enable();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
mod atomic_bits;
|
||||
mod mutex;
|
||||
mod rcu;
|
||||
mod spin;
|
||||
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::spin::{SpinLock, SpinLockGuard};
|
||||
pub use self::wait::WaitQueue;
|
||||
|
60
src/framework/jinux-frame/src/sync/mutex.rs
Normal file
60
src/framework/jinux-frame/src/sync/mutex.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use super::spin::{SpinLock, SpinLockGuard};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
use core::fmt;
|
||||
|
||||
pub struct Mutex<T> {
|
||||
inner: SpinLock<T>,
|
||||
}
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
#[inline(always)]
|
||||
pub const fn new(val: T) -> Self {
|
||||
Self {
|
||||
inner: SpinLock::new(val),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> MutexGuard<T> {
|
||||
MutexGuard {
|
||||
lock: self.inner.lock(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for Mutex<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> Send for Mutex<T> {}
|
||||
unsafe impl<T: Send> Sync for Mutex<T> {}
|
||||
|
||||
pub struct MutexGuard<'a, T> {
|
||||
lock: SpinLockGuard<'a, T>,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for MutexGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
self.lock.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> DerefMut for MutexGuard<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.lock.deref_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> !Send for MutexGuard<'a, T> {}
|
||||
|
||||
unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
|
@ -1,96 +0,0 @@
|
||||
use crate::sync::disable_local;
|
||||
use core::cell::UnsafeCell;
|
||||
|
||||
/// Defines a CPU-local variable.
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use crate::cpu_local;
|
||||
/// use core::cell::RefCell;
|
||||
/// {
|
||||
/// cpu_local! {
|
||||
/// static FOO: RefCell<u32> = RefCell::new(1);
|
||||
///
|
||||
/// #[allow(unused)]
|
||||
/// pub static BAR: RefCell<f32> = RefCell::new(1.0);
|
||||
/// }
|
||||
///
|
||||
/// FOO.borrow_with(|val| {
|
||||
/// println!("FOO VAL: {:?}", *val);
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! cpu_local {
|
||||
// empty
|
||||
() => {};
|
||||
|
||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => {
|
||||
$(#[$attr])* $vis static $name: PerCpu<$t> = PerCpu::new(const $init);
|
||||
crate::cpu_local!($($rest)*);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => (
|
||||
$(#[$attr])* $vis static $name: PerCpu<$t> = PerCpu::new(const $init);
|
||||
);
|
||||
|
||||
// multiple declarations
|
||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => {
|
||||
$(#[$attr])* $vis static $name: PerCpu<$t> = PerCpu::new($init);
|
||||
crate::cpu_local!($($rest)*);
|
||||
};
|
||||
|
||||
// single declaration
|
||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
|
||||
// TODO: reimplement per-cpu variable to support multi-core
|
||||
$(#[$attr])* $vis static $name: PerCpu<$t> = PerCpu::new($init);
|
||||
);
|
||||
}
|
||||
|
||||
/// Per-CPU objects.
|
||||
///
|
||||
/// A per-CPU object only gives you immutable references to the underlying value.
|
||||
/// To mutate the value, one can use atomic values (e.g., `AtomicU32`) or internally mutable
|
||||
/// objects (e.g., `RefCell`).
|
||||
///
|
||||
/// TODO: reimplement PerCpu inner UnsafeCell with access function as thread_local! macro,
|
||||
/// because different CPUs access static per-cpu variables in different positions.
|
||||
pub struct PerCpu<T>(UnsafeCell<T>);
|
||||
// safety
|
||||
unsafe impl<T> Sync for PerCpu<T> {}
|
||||
|
||||
impl<T> PerCpu<T> {
|
||||
/// Initialize per-CPU object
|
||||
/// unsafe
|
||||
pub const fn new(val: T) -> Self {
|
||||
Self(UnsafeCell::new(val))
|
||||
}
|
||||
/// Borrow an immutable reference to the underlying value and feed it to a closure.
|
||||
///
|
||||
/// During the execution of the closure, local IRQs are disabled. This ensures that
|
||||
/// the per-CPU object is only accessed by the current task or IRQ handler.
|
||||
/// As local IRQs are disabled, one should keep the closure as short as possible.
|
||||
pub fn borrow_with<U, F: FnOnce(&T) -> U>(&self, f: F) -> U {
|
||||
// FIXME: implement disable preemption
|
||||
// Disable interrupts when accessing per-cpu variable
|
||||
let _guard = disable_local();
|
||||
// Safety. Now that the local IRQs are disabled, this per-CPU object can only be
|
||||
// accessed by the current task/thread. So it is safe to get its immutable reference
|
||||
// regardless of whether `T` implements `Sync` or not.
|
||||
let val_ref = unsafe { self.do_borrow() };
|
||||
f(val_ref)
|
||||
}
|
||||
|
||||
unsafe fn do_borrow(&self) -> &T {
|
||||
&*self.0.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Sync> PerCpu<T> {
|
||||
/// Gets an immutable reference to the value inside the per-CPU object.
|
||||
pub fn borrow(&self) -> &T {
|
||||
// Safety. Since the value of `T` is `Sync`, it is ok for multiple tasks or IRQ handlers
|
||||
// executing on the current CPU to have immutable references.
|
||||
unsafe { self.do_borrow() }
|
||||
}
|
||||
}
|
@ -1,13 +1,10 @@
|
||||
use core::cell::UnsafeCell;
|
||||
use core::sync::atomic::Ordering;
|
||||
use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::atomic::AtomicBool,
|
||||
};
|
||||
|
||||
use crate::sync::disable_local;
|
||||
use crate::sync::irq::DisabledLocalIrqGuard;
|
||||
use core::fmt;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use crate::trap::disable_local;
|
||||
use crate::trap::DisabledLocalIrqGuard;
|
||||
|
||||
/// A spin lock.
|
||||
pub struct SpinLock<T> {
|
||||
@ -31,21 +28,35 @@ impl<T> SpinLock<T> {
|
||||
pub fn lock(&self) -> SpinLockGuard<T> {
|
||||
// FIXME: add disable_preemption
|
||||
let guard = disable_local();
|
||||
self.access_lock();
|
||||
self.acquire_lock();
|
||||
SpinLockGuard {
|
||||
lock: &self,
|
||||
irq_guard: guard,
|
||||
}
|
||||
}
|
||||
|
||||
/// Try Acquire the spin lock immedidately.
|
||||
pub fn try_lock(&self) -> Option<SpinLockGuard<T>> {
|
||||
// FIXME: add disable_preemption
|
||||
let irq_guard = disable_local();
|
||||
if self.try_acquire_lock() {
|
||||
let lock_guard = SpinLockGuard {
|
||||
lock: &self,
|
||||
irq_guard,
|
||||
};
|
||||
return Some(lock_guard);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Access the spin lock, otherwise busy waiting
|
||||
fn access_lock(&self) {
|
||||
while !self.try_access_lock() {
|
||||
fn acquire_lock(&self) {
|
||||
while !self.try_acquire_lock() {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
|
||||
fn try_access_lock(&self) -> bool {
|
||||
fn try_acquire_lock(&self) -> bool {
|
||||
self.lock
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_ok()
|
||||
@ -98,7 +109,6 @@ impl<'a, T: fmt::Debug> fmt::Debug for SpinLockGuard<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
// SpinLockGuard cannot be sent between tasks/threads
|
||||
impl<'a, T> !Send for SpinLockGuard<'a, T> {}
|
||||
|
||||
// Safety. SpinLockGuard can be shared between tasks/threads in same CPU.
|
||||
|
@ -1,10 +1,13 @@
|
||||
use crate::arch::irq;
|
||||
use crate::arch::irq::{IRQ_LIST, NOT_USING_IRQ};
|
||||
use crate::cpu::CpuLocal;
|
||||
use crate::cpu_local;
|
||||
use crate::util::recycle_allocator::RecycleAllocator;
|
||||
use crate::{prelude::*, Error};
|
||||
|
||||
use crate::util::recycle_allocator::RecycleAllocator;
|
||||
use core::fmt::Debug;
|
||||
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering::Relaxed};
|
||||
use spin::{Mutex, MutexGuard};
|
||||
// use crate::sync::{Mutex, MutexGuard};
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
pub fn allocate_irq() -> Result<IrqAllocateHandle> {
|
||||
@ -167,3 +170,88 @@ impl Drop for IrqCallbackHandle {
|
||||
ID_ALLOCATOR.lock().dealloc(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable all IRQs on the current CPU (i.e., locally).
|
||||
///
|
||||
/// This function returns a guard object, which will automatically enable local IRQs again when
|
||||
/// it is dropped. This function works correctly even when it is called in a _nested_ way.
|
||||
/// The local IRQs shall only be re-enabled when the most outer guard is dropped.
|
||||
///
|
||||
/// This function can play nicely with `SpinLock` as the type uses this function internally.
|
||||
/// One can invoke this function even after acquiring a spin lock. And the reversed order is also ok.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ``rust
|
||||
/// use jinux_frame::irq;
|
||||
///
|
||||
/// {
|
||||
/// let _ = irq::disable_local();
|
||||
/// todo!("do something when irqs are disabled");
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn disable_local() -> DisabledLocalIrqGuard {
|
||||
DisabledLocalIrqGuard::new()
|
||||
}
|
||||
|
||||
/// A guard for disabled local IRQs.
|
||||
pub struct DisabledLocalIrqGuard {
|
||||
// Having a private field prevents user from constructing values of this type directly.
|
||||
private: (),
|
||||
}
|
||||
|
||||
impl !Send for DisabledLocalIrqGuard {}
|
||||
|
||||
cpu_local! {
|
||||
static IRQ_OFF_COUNT: IrqInfo = IrqInfo::new();
|
||||
}
|
||||
|
||||
impl DisabledLocalIrqGuard {
|
||||
fn new() -> Self {
|
||||
IRQ_OFF_COUNT.inc();
|
||||
Self { private: () }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DisabledLocalIrqGuard {
|
||||
fn drop(&mut self) {
|
||||
IRQ_OFF_COUNT.dec();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct IrqInfo {
|
||||
// interrupt disabling level
|
||||
level: AtomicU32,
|
||||
// interrupt state before calling dec()/inc()
|
||||
is_irq_enabled: AtomicBool,
|
||||
}
|
||||
|
||||
impl IrqInfo {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
level: AtomicU32::new(0),
|
||||
is_irq_enabled: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn inc(&self) {
|
||||
let enabled = irq::is_local_enabled();
|
||||
let level = self.level.load(Relaxed);
|
||||
if level == 0 {
|
||||
self.is_irq_enabled.store(enabled, Relaxed);
|
||||
}
|
||||
if enabled {
|
||||
irq::disable_local();
|
||||
}
|
||||
self.level.fetch_add(1, Relaxed);
|
||||
}
|
||||
|
||||
fn dec(&self) {
|
||||
let level = self.level.fetch_sub(1, Relaxed) - 1;
|
||||
if level == 0 && self.is_irq_enabled.load(Relaxed) {
|
||||
irq::enable_local();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ mod handler;
|
||||
mod irq;
|
||||
|
||||
pub(crate) use self::handler::call_irq_callback_functions;
|
||||
pub use self::irq::{allocate_irq, IrqAllocateHandle};
|
||||
pub use self::irq::{allocate_irq, disable_local, DisabledLocalIrqGuard, IrqAllocateHandle};
|
||||
pub(crate) use self::irq::{allocate_target_irq, IrqCallbackHandle, IrqLine};
|
||||
pub use trapframe::TrapFrame;
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::prelude::*;
|
||||
use alloc::string::String;
|
||||
use core::time::Duration;
|
||||
use spin::MutexGuard;
|
||||
|
||||
use super::{InodeMode, InodeType, Metadata, Vnode, NAME_MAX};
|
||||
|
||||
|
@ -15,11 +15,12 @@ pub(crate) use alloc::vec::Vec;
|
||||
pub(crate) use bitflags::bitflags;
|
||||
pub(crate) use core::ffi::CStr;
|
||||
pub(crate) use jinux_frame::config::PAGE_SIZE;
|
||||
pub(crate) use jinux_frame::sync::{Mutex, MutexGuard};
|
||||
pub(crate) use jinux_frame::vm::Vaddr;
|
||||
pub(crate) use jinux_frame::{print, println};
|
||||
pub(crate) use log::{debug, error, info, trace, warn};
|
||||
pub(crate) use pod::Pod;
|
||||
pub(crate) use spin::{Mutex, RwLock};
|
||||
pub(crate) use spin::RwLock;
|
||||
|
||||
/// return current process
|
||||
#[macro_export]
|
||||
|
@ -15,7 +15,6 @@ mod static_cap;
|
||||
|
||||
pub use options::{VmoChildOptions, VmoOptions};
|
||||
pub use pager::Pager;
|
||||
use spin::Mutex;
|
||||
|
||||
/// Virtual Memory Objects (VMOs) are a type of capability that represents a
|
||||
/// range of memory pages.
|
||||
|
Reference in New Issue
Block a user