From 59fdb447ee4f7b53b1d9c56ec1442aa8c597ac2b Mon Sep 17 00:00:00 2001 From: LoGin Date: Tue, 12 Mar 2024 16:32:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=94=AE=E7=9B=98=E4=B8=AD=E6=96=AD?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E6=96=87=E4=B8=8D=E5=86=8D=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E6=93=8D=E4=BD=9Ctty,=E8=80=8C=E6=98=AF=E7=94=B1=E4=B8=93?= =?UTF-8?q?=E9=97=A8=E7=9A=84kthread=E6=9D=A5=E6=B8=B2=E6=9F=93=20(#592)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 1.修正psmouse 日志 2. 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 3. 由于调度器设计问题,load balance会由于时序问题导致错误.因此暂时只启用单核. --- .../driver/input/ps2_mouse/ps_mouse_driver.rs | 3 +- kernel/src/driver/tty/kthread.rs | 66 +++++++++++++++++++ kernel/src/driver/tty/mod.rs | 1 + kernel/src/driver/tty/tty_core.rs | 19 +++--- kernel/src/driver/tty/tty_device.rs | 3 + kernel/src/driver/tty/tty_port.rs | 10 ++- kernel/src/init/initial_kthread.rs | 3 +- kernel/src/libs/keyboard_parser.rs | 16 +---- kernel/src/process/fork.rs | 11 +++- kernel/src/process/kthread.rs | 14 ++-- kernel/src/process/mod.rs | 2 +- kernel/src/sched/core.rs | 4 +- 12 files changed, 114 insertions(+), 38 deletions(-) create mode 100644 kernel/src/driver/tty/kthread.rs diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs index 4321d2cbb..a9b76c338 100644 --- a/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs @@ -276,9 +276,10 @@ impl SerioDriver for Ps2MouseDriver { #[unified_init(INITCALL_DEVICE)] fn ps2_mouse_driver_init() -> Result<(), SystemError> { - kdebug!("Ps2_mouse_drive initing..."); + kdebug!("Ps2_mouse_drive initializing..."); let driver = Ps2MouseDriver::new(); serio_driver_manager().register(driver.clone())?; unsafe { PS2_MOUSE_DRIVER = Some(driver) }; + kdebug!("Ps2_mouse_drive initialized!"); return Ok(()); } diff --git a/kernel/src/driver/tty/kthread.rs b/kernel/src/driver/tty/kthread.rs new file mode 100644 index 000000000..1e506939a --- /dev/null +++ b/kernel/src/driver/tty/kthread.rs @@ -0,0 +1,66 @@ +//! tty刷新内核线程 + +use alloc::{string::ToString, sync::Arc}; +use kdepends::thingbuf::StaticThingBuf; + +use crate::{ + arch::sched::sched, + process::{ + kthread::{KernelThreadClosure, KernelThreadMechanism}, + ProcessControlBlock, ProcessFlags, + }, +}; + +use super::tty_port::current_tty_port; + +/// 用于缓存键盘输入的缓冲区 +static KEYBUF: StaticThingBuf = StaticThingBuf::new(); + +static mut TTY_REFRESH_THREAD: Option> = None; + +pub(super) fn tty_flush_thread_init() { + let closure = + KernelThreadClosure::StaticEmptyClosure((&(tty_refresh_thread as fn() -> i32), ())); + let pcb = KernelThreadMechanism::create_and_run(closure, "tty_refresh".to_string()) + .ok_or("") + .expect("create tty_refresh thread failed"); + unsafe { + TTY_REFRESH_THREAD = Some(pcb); + } +} + +fn tty_refresh_thread() -> i32 { + const TO_DEQUEUE_MAX: usize = 256; + loop { + if KEYBUF.is_empty() { + // 如果缓冲区为空,就休眠 + unsafe { + TTY_REFRESH_THREAD + .as_ref() + .unwrap() + .flags() + .insert(ProcessFlags::NEED_SCHEDULE) + }; + + sched(); + } + + let to_dequeue = core::cmp::min(KEYBUF.len(), TO_DEQUEUE_MAX); + if to_dequeue == 0 { + continue; + } + let mut data = [0u8; TO_DEQUEUE_MAX]; + for i in 0..to_dequeue { + data[i] = KEYBUF.pop().unwrap(); + } + + let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue); + } +} + +/// 发送数据到tty刷新线程 +pub fn send_to_tty_refresh_thread(data: &[u8]) { + for i in 0..data.len() { + KEYBUF.push(data[i]).ok(); + } +} diff --git a/kernel/src/driver/tty/mod.rs b/kernel/src/driver/tty/mod.rs index 662a1d105..9bd9ac08e 100644 --- a/kernel/src/driver/tty/mod.rs +++ b/kernel/src/driver/tty/mod.rs @@ -1,6 +1,7 @@ use alloc::vec::Vec; pub mod console; +pub mod kthread; pub mod termios; pub mod tty_core; pub mod tty_device; diff --git a/kernel/src/driver/tty/tty_core.rs b/kernel/src/driver/tty/tty_core.rs index 46bcd3a28..cb3513800 100644 --- a/kernel/src/driver/tty/tty_core.rs +++ b/kernel/src/driver/tty/tty_core.rs @@ -1,4 +1,7 @@ -use core::{fmt::Debug, sync::atomic::AtomicBool}; +use core::{ + fmt::Debug, + sync::atomic::{AtomicBool, AtomicUsize}, +}; use alloc::{collections::LinkedList, string::String, sync::Arc, vec::Vec}; use system_error::SystemError; @@ -43,7 +46,7 @@ impl TtyCore { termios: RwLock::new(termios), name, flags: RwLock::new(TtyFlag::empty()), - count: RwLock::new(0), + count: AtomicUsize::new(0), window_size: RwLock::new(WindowSize::default()), read_wq: EventWaitQueue::new(), write_wq: EventWaitQueue::new(), @@ -129,7 +132,7 @@ impl TtyCore { } pub fn tty_wakeup(&self) { - if self.core.flags.read().contains(TtyFlag::DO_WRITE_WAKEUP) { + if self.core.flags().contains(TtyFlag::DO_WRITE_WAKEUP) { let _ = self.ldisc().write_wakeup(self.core()); } @@ -289,7 +292,7 @@ pub struct TtyCoreData { flags: RwLock, /// 在初始化时即确定不会更改,所以这里不用加锁 index: usize, - count: RwLock, + count: AtomicUsize, /// 窗口大小 window_size: RwLock, /// 读等待队列 @@ -338,7 +341,7 @@ impl TtyCoreData { #[inline] pub fn flags(&self) -> TtyFlag { - self.flags.read().clone() + self.flags.read_irqsave().clone() } #[inline] @@ -353,14 +356,14 @@ impl TtyCoreData { #[inline] pub fn set_termios(&self, termios: Termios) { - let mut termios_guard = self.termios.write_irqsave(); + let mut termios_guard = self.termios_write(); *termios_guard = termios; } #[inline] pub fn add_count(&self) { - let mut guard = self.count.write(); - *guard += 1; + self.count + .fetch_add(1, core::sync::atomic::Ordering::SeqCst); } #[inline] diff --git a/kernel/src/driver/tty/tty_device.rs b/kernel/src/driver/tty/tty_device.rs index 392c80886..4e7913604 100644 --- a/kernel/src/driver/tty/tty_device.rs +++ b/kernel/src/driver/tty/tty_device.rs @@ -36,6 +36,7 @@ use crate::{ }; use super::{ + kthread::tty_flush_thread_init, termios::WindowSize, tty_core::{TtyCore, TtyFlag, TtyIoctlCmd}, tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation}, @@ -528,5 +529,7 @@ pub fn tty_init() -> Result<(), SystemError> { devfs_register(console.name, console)?; serial_init()?; + + tty_flush_thread_init(); return vty_init(); } diff --git a/kernel/src/driver/tty/tty_port.rs b/kernel/src/driver/tty/tty_port.rs index a3e1e675a..31ed9766c 100644 --- a/kernel/src/driver/tty/tty_port.rs +++ b/kernel/src/driver/tty/tty_port.rs @@ -1,4 +1,4 @@ -use core::fmt::Debug; +use core::{fmt::Debug, sync::atomic::Ordering}; use alloc::{ sync::{Arc, Weak}, @@ -12,7 +12,7 @@ use crate::{ libs::spinlock::{SpinLock, SpinLockGuard}, }; -use super::tty_core::TtyCore; +use super::{tty_core::TtyCore, virtual_terminal::virtual_console::CURRENT_VCNUM}; const TTY_PORT_BUFSIZE: usize = 4096; @@ -27,6 +27,12 @@ lazy_static! { }; } +/// 获取当前tty port +#[inline] +pub fn current_tty_port() -> Arc { + TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone() +} + #[allow(dead_code)] #[derive(Debug)] pub struct TtyPortData { diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index 51ab73edb..3e4136bc7 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/kernel/src/init/initial_kthread.rs @@ -27,9 +27,8 @@ pub fn initial_kernel_thread() -> i32 { } fn kernel_init() -> Result<(), SystemError> { - kenrel_init_freeable()?; - KernelThreadMechanism::init_stage2(); + kenrel_init_freeable()?; // 由于目前加锁,速度过慢,所以先不开启双缓冲 // scm_enable_double_buffer().expect("Failed to enable double buffer"); diff --git a/kernel/src/libs/keyboard_parser.rs b/kernel/src/libs/keyboard_parser.rs index 00ecf974d..2d149eb9d 100644 --- a/kernel/src/libs/keyboard_parser.rs +++ b/kernel/src/libs/keyboard_parser.rs @@ -1,11 +1,4 @@ -use core::sync::atomic::Ordering; - -use alloc::sync::Arc; - -use crate::driver::tty::{ - tty_port::{TtyPort, TTY_PORTS}, - virtual_terminal::virtual_console::CURRENT_VCNUM, -}; +use crate::driver::tty::kthread::send_to_tty_refresh_thread; #[allow(dead_code)] pub const NUM_SCAN_CODES: u8 = 0x80; @@ -360,12 +353,7 @@ impl TypeOneFSMState { #[inline(always)] fn emit(ch: u8) { // 发送到tty - let _ = Self::current_port().receive_buf(&[ch], &[], 1); - } - - #[inline] - fn current_port() -> Arc { - TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone() + send_to_tty_refresh_thread(&[ch]); } /// @brief 处理Prtsc按下事件 diff --git a/kernel/src/process/fork.rs b/kernel/src/process/fork.rs index 6caad3e7b..67caceb18 100644 --- a/kernel/src/process/fork.rs +++ b/kernel/src/process/fork.rs @@ -165,8 +165,15 @@ impl ProcessManager { let mut args = KernelCloneArgs::new(); args.flags = clone_flags; args.exit_signal = Signal::SIGCHLD; - - Self::copy_process(¤t_pcb, &pcb, args, current_trapframe)?; + Self::copy_process(¤t_pcb, &pcb, args, current_trapframe).map_err(|e| { + kerror!( + "fork: Failed to copy process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}", + current_pcb.pid(), + pcb.pid(), + e + ); + e + })?; ProcessManager::add_pcb(pcb.clone()); // 向procfs注册进程 diff --git a/kernel/src/process/kthread.rs b/kernel/src/process/kthread.rs index c75a53673..bb1a8b8cd 100644 --- a/kernel/src/process/kthread.rs +++ b/kernel/src/process/kthread.rs @@ -87,9 +87,9 @@ impl KernelThreadPcbPrivate { #[allow(dead_code)] pub enum KernelThreadClosure { UsizeClosure((Box i32 + Send + Sync>, usize)), - StaticUsizeClosure((&'static dyn Fn(usize) -> i32, usize)), + StaticUsizeClosure((&'static fn(usize) -> i32, usize)), EmptyClosure((Box i32 + Send + Sync>, ())), - StaticEmptyClosure((&'static dyn Fn() -> i32, ())), + StaticEmptyClosure((&'static fn() -> i32, ())), IrqThread( ( &'static dyn Fn(Arc) -> Result<(), SystemError>, @@ -311,7 +311,7 @@ impl KernelThreadMechanism { unsafe { KTHREAD_DAEMON_PCB.replace(pcb); } - kinfo!("Initializing kernel thread mechanism stage2 complete"); + kinfo!("Initialize kernel thread mechanism stage2 complete"); }); } @@ -435,6 +435,7 @@ impl KernelThreadMechanism { } /// A daemon thread which creates other kernel threads + #[inline(never)] fn kthread_daemon() -> i32 { let current_pcb = ProcessManager::current_pcb(); kdebug!("kthread_daemon: pid: {:?}", current_pcb.pid()); @@ -454,9 +455,10 @@ impl KernelThreadMechanism { drop(list); // create a new kernel thread - let result: Result = - Self::__inner_create(&info, CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL); - + let result: Result = Self::__inner_create( + &info, + CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL, + ); if result.is_err() { // 创建失败 info.created diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 8defbf113..db92ffb3e 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -439,6 +439,7 @@ impl ProcessManager { /// 上下文切换的钩子函数,当这个函数return的时候,将会发生上下文切换 #[cfg(target_arch = "x86_64")] +#[inline(never)] pub unsafe extern "sysv64" fn switch_finish_hook() { ProcessManager::switch_finish_hook(); } @@ -891,7 +892,6 @@ impl ProcessControlBlock { impl Drop for ProcessControlBlock { fn drop(&mut self) { let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; - // kdebug!("drop: {:?}", self.pid); // 在ProcFS中,解除进程的注册 procfs_unregister_pid(self.pid()) .unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}")); diff --git a/kernel/src/sched/core.rs b/kernel/src/sched/core.rs index a55d38ead..b7ee69596 100644 --- a/kernel/src/sched/core.rs +++ b/kernel/src/sched/core.rs @@ -63,8 +63,8 @@ pub fn get_cpu_loads(cpu_id: ProcessorId) -> u32 { } // 负载均衡 pub fn loads_balance(pcb: Arc) { - // 对pcb的迁移情况进行调整 - + // FIXME: 由于目前负载均衡是直接添加到目标CPU的队列中,导致会由于时序问题导致进程在两个CPU上都存在。 + // 在调度子系统重写/改进之前,暂时只设置进程在0号CPU上运行 // 由于调度器问题,暂时不进行负载均衡,见issue: https://github.com/DragonOS-Community/DragonOS/issues/571 let min_loads_cpu_id = ProcessorId::new(0);