From d28f0db41935e5767d37155e17d0fa0ef3f35927 Mon Sep 17 00:00:00 2001 From: Chuandong Li Date: Sun, 8 Oct 2023 16:04:18 +0000 Subject: [PATCH] Refactor tty driver using the work queue --- services/libs/jinux-std/src/device/pty/pty.rs | 2 +- .../src/device/tty/line_discipline.rs | 92 +++++++++++++++---- services/libs/jinux-std/src/device/tty/mod.rs | 2 +- 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/services/libs/jinux-std/src/device/pty/pty.rs b/services/libs/jinux-std/src/device/pty/pty.rs index b55462dd7..e2829a8f9 100644 --- a/services/libs/jinux-std/src/device/pty/pty.rs +++ b/services/libs/jinux-std/src/device/pty/pty.rs @@ -19,7 +19,7 @@ const BUFFER_CAPACITY: usize = 4096; pub struct PtyMaster { ptmx: Arc, index: u32, - output: LineDiscipline, + output: Arc, input: SpinLock>, /// The state of input buffer pollee: Pollee, diff --git a/services/libs/jinux-std/src/device/tty/line_discipline.rs b/services/libs/jinux-std/src/device/tty/line_discipline.rs index 208cc3ffd..c2106601a 100644 --- a/services/libs/jinux-std/src/device/tty/line_discipline.rs +++ b/services/libs/jinux-std/src/device/tty/line_discipline.rs @@ -1,6 +1,8 @@ use crate::fs::utils::{IoEvents, Pollee, Poller}; use crate::process::signal::constants::{SIGINT, SIGQUIT}; use crate::process::ProcessGroup; +use crate::thread::work_queue::work_item::WorkItem; +use crate::thread::work_queue::{submit_work_item, WorkPriority}; use crate::{ prelude::*, process::{signal::signals::kernel::KernelSignal, Pgid}, @@ -29,6 +31,10 @@ pub struct LineDiscipline { winsize: SpinLock, /// Pollee pollee: Pollee, + /// work item + work_item: Arc, + /// Parameters used by a work item. + work_item_para: Arc>, } #[derive(Default)] @@ -67,23 +73,27 @@ impl CurrentLine { } } -impl Default for LineDiscipline { - fn default() -> Self { - Self::new() - } -} - impl LineDiscipline { /// Create a new line discipline - pub fn new() -> Self { - 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()), - } + pub fn new() -> Arc { + Arc::new_cyclic(|line_ref: &Weak| { + let line_discipline = line_ref.clone(); + let work_item = Arc::new(WorkItem::new(Box::new(move || { + if let Some(line_discipline) = line_discipline.upgrade() { + line_discipline.update_readable_state_after(); + } + }))); + 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. @@ -157,17 +167,40 @@ impl LineDiscipline { } _ => return, }; - // FIXME: kernel_signal may sleep - foreground.kernel_signal(signal); + // `kernel_signal()` may cause sleep, so only construct parameters here. + self.work_item_para.lock_irq_disabled().kernel_signal = Some(signal); } fn update_readable_state(&self) { 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() { - self.pollee.add_events(IoEvents::IN); + self.work_item_para.lock_irq_disabled().pollee_type = Some(PolleeType::Add); } 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 { item == *termios.get_special_char(CC_C_CHAR::VEOF) } + +enum PolleeType { + Add, + Del, +} + +struct LineDisciplineWorkPara { + kernel_signal: Option, + pollee_type: Option, +} + +impl LineDisciplineWorkPara { + fn new() -> Self { + Self { + kernel_signal: None, + pollee_type: None, + } + } +} diff --git a/services/libs/jinux-std/src/device/tty/mod.rs b/services/libs/jinux-std/src/device/tty/mod.rs index 729d4868a..a71749244 100644 --- a/services/libs/jinux-std/src/device/tty/mod.rs +++ b/services/libs/jinux-std/src/device/tty/mod.rs @@ -25,7 +25,7 @@ pub struct Tty { /// tty_name name: CString, /// line discipline - ldisc: LineDiscipline, + ldisc: Arc, /// driver driver: SpinLock>, }