Refactor tty driver using the work queue

This commit is contained in:
Chuandong Li
2023-10-08 16:04:18 +00:00
committed by Tate, Hongliang Tian
parent 7419f6b56b
commit d28f0db419
3 changed files with 74 additions and 22 deletions

View File

@ -19,7 +19,7 @@ const BUFFER_CAPACITY: usize = 4096;
pub struct PtyMaster { pub struct PtyMaster {
ptmx: Arc<dyn Inode>, ptmx: Arc<dyn Inode>,
index: u32, index: u32,
output: LineDiscipline, output: Arc<LineDiscipline>,
input: SpinLock<HeapRb<u8>>, input: SpinLock<HeapRb<u8>>,
/// The state of input buffer /// The state of input buffer
pollee: Pollee, pollee: Pollee,

View File

@ -1,6 +1,8 @@
use crate::fs::utils::{IoEvents, Pollee, Poller}; use crate::fs::utils::{IoEvents, Pollee, Poller};
use crate::process::signal::constants::{SIGINT, SIGQUIT}; use crate::process::signal::constants::{SIGINT, SIGQUIT};
use crate::process::ProcessGroup; use crate::process::ProcessGroup;
use crate::thread::work_queue::work_item::WorkItem;
use crate::thread::work_queue::{submit_work_item, WorkPriority};
use crate::{ use crate::{
prelude::*, prelude::*,
process::{signal::signals::kernel::KernelSignal, Pgid}, process::{signal::signals::kernel::KernelSignal, Pgid},
@ -29,6 +31,10 @@ pub struct LineDiscipline {
winsize: SpinLock<WinSize>, winsize: SpinLock<WinSize>,
/// Pollee /// Pollee
pollee: Pollee, pollee: Pollee,
/// work item
work_item: Arc<WorkItem>,
/// Parameters used by a work item.
work_item_para: Arc<SpinLock<LineDisciplineWorkPara>>,
} }
#[derive(Default)] #[derive(Default)]
@ -67,23 +73,27 @@ impl CurrentLine {
} }
} }
impl Default for LineDiscipline {
fn default() -> Self {
Self::new()
}
}
impl LineDiscipline { impl LineDiscipline {
/// Create a new line discipline /// Create a new line discipline
pub fn new() -> Self { pub fn new() -> Arc<Self> {
Self { Arc::new_cyclic(|line_ref: &Weak<LineDiscipline>| {
current_line: SpinLock::new(CurrentLine::new()), let line_discipline = line_ref.clone();
read_buffer: SpinLock::new(StaticRb::default()), let work_item = Arc::new(WorkItem::new(Box::new(move || {
foreground: SpinLock::new(Weak::new()), if let Some(line_discipline) = line_discipline.upgrade() {
termios: SpinLock::new(KernelTermios::default()), line_discipline.update_readable_state_after();
winsize: SpinLock::new(WinSize::default()), }
pollee: Pollee::new(IoEvents::empty()), })));
} Self {
current_line: SpinLock::new(CurrentLine::new()),
read_buffer: SpinLock::new(StaticRb::default()),
foreground: SpinLock::new(Weak::new()),
termios: SpinLock::new(KernelTermios::default()),
winsize: SpinLock::new(WinSize::default()),
pollee: Pollee::new(IoEvents::empty()),
work_item,
work_item_para: Arc::new(SpinLock::new(LineDisciplineWorkPara::new())),
}
})
} }
/// Push char to line discipline. /// Push char to line discipline.
@ -157,17 +167,40 @@ impl LineDiscipline {
} }
_ => return, _ => return,
}; };
// FIXME: kernel_signal may sleep // `kernel_signal()` may cause sleep, so only construct parameters here.
foreground.kernel_signal(signal); self.work_item_para.lock_irq_disabled().kernel_signal = Some(signal);
} }
fn update_readable_state(&self) { fn update_readable_state(&self) {
let buffer = self.read_buffer.lock_irq_disabled(); let buffer = self.read_buffer.lock_irq_disabled();
// FIXME: add/del events may sleep let pollee = self.pollee.clone();
// add/del events may sleep, so only construct parameters here.
if !buffer.is_empty() { if !buffer.is_empty() {
self.pollee.add_events(IoEvents::IN); self.work_item_para.lock_irq_disabled().pollee_type = Some(PolleeType::Add);
} else { } else {
self.pollee.del_events(IoEvents::IN); 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.
fn update_readable_state_after(&self) {
if let Some(signal) = self.work_item_para.lock_irq_disabled().kernel_signal.take() {
self.foreground
.lock()
.upgrade()
.unwrap()
.kernel_signal(signal)
};
if let Some(pollee_type) = self.work_item_para.lock_irq_disabled().pollee_type.take() {
match pollee_type {
PolleeType::Add => {
self.pollee.add_events(IoEvents::IN);
}
PolleeType::Del => {
self.pollee.del_events(IoEvents::IN);
}
}
} }
} }
@ -393,3 +426,22 @@ fn meet_new_line(item: u8, termios: &KernelTermios) -> bool {
fn should_not_be_read(item: u8, termios: &KernelTermios) -> bool { fn should_not_be_read(item: u8, termios: &KernelTermios) -> bool {
item == *termios.get_special_char(CC_C_CHAR::VEOF) item == *termios.get_special_char(CC_C_CHAR::VEOF)
} }
enum PolleeType {
Add,
Del,
}
struct LineDisciplineWorkPara {
kernel_signal: Option<KernelSignal>,
pollee_type: Option<PolleeType>,
}
impl LineDisciplineWorkPara {
fn new() -> Self {
Self {
kernel_signal: None,
pollee_type: None,
}
}
}

View File

@ -25,7 +25,7 @@ pub struct Tty {
/// tty_name /// tty_name
name: CString, name: CString,
/// line discipline /// line discipline
ldisc: LineDiscipline, ldisc: Arc<LineDiscipline>,
/// driver /// driver
driver: SpinLock<Weak<TtyDriver>>, driver: SpinLock<Weak<TtyDriver>>,
} }