mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Add in_interrupt
and refactor line discipline
This commit is contained in:
parent
e0d7b140ce
commit
22c2cebdec
@ -39,14 +39,14 @@ macro_rules! cpu_local {
|
|||||||
|
|
||||||
// multiple declarations
|
// multiple declarations
|
||||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => {
|
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => {
|
||||||
$(#[$attr])* $vis static $name: CpuLocal<$t> = unsafe { CpuLocal::new($init) };
|
$(#[$attr])* $vis static $name: $crate::CpuLocal<$t> = unsafe { $crate::CpuLocal::new($init) };
|
||||||
$crate::cpu_local!($($rest)*);
|
$crate::cpu_local!($($rest)*);
|
||||||
};
|
};
|
||||||
|
|
||||||
// single declaration
|
// single declaration
|
||||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
|
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
|
||||||
// TODO: reimplement cpu-local variable to support multi-core
|
// TODO: reimplement cpu-local variable to support multi-core
|
||||||
$(#[$attr])* $vis static $name: CpuLocal<$t> = CpuLocal::new($init);
|
$(#[$attr])* $vis static $name: $crate::CpuLocal<$t> = $crate::CpuLocal::new($init);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use core::sync::atomic::AtomicUsize;
|
|||||||
|
|
||||||
use crate::cpu_local;
|
use crate::cpu_local;
|
||||||
use crate::sync::Mutex;
|
use crate::sync::Mutex;
|
||||||
use crate::{cpu::CpuLocal, trap::disable_local};
|
use crate::trap::disable_local;
|
||||||
|
|
||||||
use core::sync::atomic::Ordering::Relaxed;
|
use core::sync::atomic::Ordering::Relaxed;
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use crate::{arch::irq::IRQ_LIST, cpu::CpuException};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use crate::{arch::irq::IRQ_LIST, cpu::CpuException, cpu_local};
|
||||||
|
|
||||||
#[cfg(feature = "intel_tdx")]
|
#[cfg(feature = "intel_tdx")]
|
||||||
use crate::arch::tdx_guest::{handle_virtual_exception, TdxTrapFrame};
|
use crate::arch::tdx_guest::{handle_virtual_exception, TdxTrapFrame};
|
||||||
@ -71,6 +73,12 @@ extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
|
pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
|
||||||
|
// For x86 CPUs, interrupts are not re-entrant. Local interrupts will be disabled when
|
||||||
|
// an interrupt handler is called (Unless interrupts are re-enabled in an interrupt handler).
|
||||||
|
//
|
||||||
|
// FIXME: For arch that supports re-entrant interrupts, we may need to record nested level here.
|
||||||
|
IN_INTERRUPT_CONTEXT.store(true, Ordering::Release);
|
||||||
|
|
||||||
let irq_line = IRQ_LIST.get().unwrap().get(trap_frame.trap_num).unwrap();
|
let irq_line = IRQ_LIST.get().unwrap().get(trap_frame.trap_num).unwrap();
|
||||||
let callback_functions = irq_line.callback_list();
|
let callback_functions = irq_line.callback_list();
|
||||||
for callback_function in callback_functions.iter() {
|
for callback_function in callback_functions.iter() {
|
||||||
@ -79,4 +87,18 @@ pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
|
|||||||
if !CpuException::is_cpu_exception(trap_frame.trap_num as u16) {
|
if !CpuException::is_cpu_exception(trap_frame.trap_num as u16) {
|
||||||
crate::arch::interrupts_ack();
|
crate::arch::interrupts_ack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IN_INTERRUPT_CONTEXT.store(false, Ordering::Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_local! {
|
||||||
|
static IN_INTERRUPT_CONTEXT: AtomicBool = AtomicBool::new(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether we are in the interrupt context.
|
||||||
|
///
|
||||||
|
/// FIXME: Here only hardware irq is taken into account. According to linux implementation, if
|
||||||
|
/// we are in softirq context, or bottom half is disabled, this function also returns true.
|
||||||
|
pub fn in_interrupt_context() -> bool {
|
||||||
|
IN_INTERRUPT_CONTEXT.load(Ordering::Acquire)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ mod irq;
|
|||||||
|
|
||||||
pub(crate) use self::handler::call_irq_callback_functions;
|
pub(crate) use self::handler::call_irq_callback_functions;
|
||||||
pub use self::irq::{disable_local, DisabledLocalIrqGuard, IrqCallbackFunction, IrqLine};
|
pub use self::irq::{disable_local, DisabledLocalIrqGuard, IrqCallbackFunction, IrqLine};
|
||||||
|
pub use handler::in_interrupt_context;
|
||||||
pub use trapframe::TrapFrame;
|
pub use trapframe::TrapFrame;
|
||||||
|
|
||||||
pub(crate) fn init() {
|
pub(crate) fn init() {
|
||||||
|
@ -8,7 +8,7 @@ use crate::process::signal::{Pollee, Poller};
|
|||||||
use crate::thread::work_queue::work_item::WorkItem;
|
use crate::thread::work_queue::work_item::WorkItem;
|
||||||
use crate::thread::work_queue::{submit_work_item, WorkPriority};
|
use crate::thread::work_queue::{submit_work_item, WorkPriority};
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
use aster_frame::trap::disable_local;
|
use aster_frame::trap::{disable_local, in_interrupt_context};
|
||||||
use ringbuf::{ring_buffer::RbBase, Rb, StaticRb};
|
use ringbuf::{ring_buffer::RbBase, Rb, StaticRb};
|
||||||
|
|
||||||
use super::termio::{KernelTermios, WinSize, CC_C_CHAR};
|
use super::termio::{KernelTermios, WinSize, CC_C_CHAR};
|
||||||
@ -122,7 +122,7 @@ impl LineDiscipline {
|
|||||||
// Raw mode
|
// Raw mode
|
||||||
if !termios.is_canonical_mode() {
|
if !termios.is_canonical_mode() {
|
||||||
self.read_buffer.lock_irq_disabled().push_overwrite(ch);
|
self.read_buffer.lock_irq_disabled().push_overwrite(ch);
|
||||||
self.update_readable_state_deferred();
|
self.update_readable_state();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ impl LineDiscipline {
|
|||||||
self.current_line.lock_irq_disabled().push_char(ch);
|
self.current_line.lock_irq_disabled().push_char(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_readable_state_deferred();
|
self.update_readable_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn may_send_signal(&self, termios: &KernelTermios, ch: u8) -> bool {
|
fn may_send_signal(&self, termios: &KernelTermios, ch: u8) -> bool {
|
||||||
@ -169,14 +169,31 @@ impl LineDiscipline {
|
|||||||
ch if ch == *termios.get_special_char(CC_C_CHAR::VQUIT) => KernelSignal::new(SIGQUIT),
|
ch if ch == *termios.get_special_char(CC_C_CHAR::VQUIT) => KernelSignal::new(SIGQUIT),
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
// `kernel_signal()` may cause sleep, so only construct parameters here.
|
|
||||||
self.work_item_para.lock_irq_disabled().kernel_signal = Some(signal);
|
if in_interrupt_context() {
|
||||||
|
// `kernel_signal()` may cause sleep, so only construct parameters here.
|
||||||
|
self.work_item_para.lock_irq_disabled().kernel_signal = Some(signal);
|
||||||
|
} else {
|
||||||
|
(self.send_signal)(signal);
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_readable_state(&self) {
|
pub fn update_readable_state(&self) {
|
||||||
let buffer = self.read_buffer.lock_irq_disabled();
|
let buffer = self.read_buffer.lock_irq_disabled();
|
||||||
|
|
||||||
|
if in_interrupt_context() {
|
||||||
|
// Add/Del events may sleep, so only construct parameters here.
|
||||||
|
if !buffer.is_empty() {
|
||||||
|
self.work_item_para.lock_irq_disabled().pollee_type = Some(PolleeType::Add);
|
||||||
|
} else {
|
||||||
|
self.work_item_para.lock_irq_disabled().pollee_type = Some(PolleeType::Del);
|
||||||
|
}
|
||||||
|
submit_work_item(self.work_item.clone(), WorkPriority::High);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if !buffer.is_empty() {
|
if !buffer.is_empty() {
|
||||||
self.pollee.add_events(IoEvents::IN);
|
self.pollee.add_events(IoEvents::IN);
|
||||||
} else {
|
} else {
|
||||||
@ -184,17 +201,6 @@ impl LineDiscipline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_readable_state_deferred(&self) {
|
|
||||||
let buffer = self.read_buffer.lock_irq_disabled();
|
|
||||||
// add/del events may sleep, so only construct parameters here.
|
|
||||||
if !buffer.is_empty() {
|
|
||||||
self.work_item_para.lock_irq_disabled().pollee_type = Some(PolleeType::Add);
|
|
||||||
} else {
|
|
||||||
self.work_item_para.lock_irq_disabled().pollee_type = Some(PolleeType::Del);
|
|
||||||
}
|
|
||||||
submit_work_item(self.work_item.clone(), WorkPriority::High);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// include all operations that may cause sleep, and processes by a work queue.
|
/// include all operations that may cause sleep, and processes by a work queue.
|
||||||
fn update_readable_state_after(&self) {
|
fn update_readable_state_after(&self) {
|
||||||
if let Some(signal) = self.work_item_para.lock_irq_disabled().kernel_signal.take() {
|
if let Some(signal) = self.work_item_para.lock_irq_disabled().kernel_signal.take() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user