fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 (#592)

fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染
1.修正psmouse 日志
2. 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染
3. 由于调度器设计问题,load balance会由于时序问题导致错误.因此暂时只启用单核.
This commit is contained in:
LoGin
2024-03-12 16:32:33 +08:00
committed by GitHub
parent 818a64c776
commit 59fdb447ee
12 changed files with 114 additions and 38 deletions

View File

@ -276,9 +276,10 @@ impl SerioDriver for Ps2MouseDriver {
#[unified_init(INITCALL_DEVICE)] #[unified_init(INITCALL_DEVICE)]
fn ps2_mouse_driver_init() -> Result<(), SystemError> { fn ps2_mouse_driver_init() -> Result<(), SystemError> {
kdebug!("Ps2_mouse_drive initing..."); kdebug!("Ps2_mouse_drive initializing...");
let driver = Ps2MouseDriver::new(); let driver = Ps2MouseDriver::new();
serio_driver_manager().register(driver.clone())?; serio_driver_manager().register(driver.clone())?;
unsafe { PS2_MOUSE_DRIVER = Some(driver) }; unsafe { PS2_MOUSE_DRIVER = Some(driver) };
kdebug!("Ps2_mouse_drive initialized!");
return Ok(()); return Ok(());
} }

View File

@ -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<u8, 512> = StaticThingBuf::new();
static mut TTY_REFRESH_THREAD: Option<Arc<ProcessControlBlock>> = 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();
}
}

View File

@ -1,6 +1,7 @@
use alloc::vec::Vec; use alloc::vec::Vec;
pub mod console; pub mod console;
pub mod kthread;
pub mod termios; pub mod termios;
pub mod tty_core; pub mod tty_core;
pub mod tty_device; pub mod tty_device;

View File

@ -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 alloc::{collections::LinkedList, string::String, sync::Arc, vec::Vec};
use system_error::SystemError; use system_error::SystemError;
@ -43,7 +46,7 @@ impl TtyCore {
termios: RwLock::new(termios), termios: RwLock::new(termios),
name, name,
flags: RwLock::new(TtyFlag::empty()), flags: RwLock::new(TtyFlag::empty()),
count: RwLock::new(0), count: AtomicUsize::new(0),
window_size: RwLock::new(WindowSize::default()), window_size: RwLock::new(WindowSize::default()),
read_wq: EventWaitQueue::new(), read_wq: EventWaitQueue::new(),
write_wq: EventWaitQueue::new(), write_wq: EventWaitQueue::new(),
@ -129,7 +132,7 @@ impl TtyCore {
} }
pub fn tty_wakeup(&self) { 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()); let _ = self.ldisc().write_wakeup(self.core());
} }
@ -289,7 +292,7 @@ pub struct TtyCoreData {
flags: RwLock<TtyFlag>, flags: RwLock<TtyFlag>,
/// 在初始化时即确定不会更改,所以这里不用加锁 /// 在初始化时即确定不会更改,所以这里不用加锁
index: usize, index: usize,
count: RwLock<usize>, count: AtomicUsize,
/// 窗口大小 /// 窗口大小
window_size: RwLock<WindowSize>, window_size: RwLock<WindowSize>,
/// 读等待队列 /// 读等待队列
@ -338,7 +341,7 @@ impl TtyCoreData {
#[inline] #[inline]
pub fn flags(&self) -> TtyFlag { pub fn flags(&self) -> TtyFlag {
self.flags.read().clone() self.flags.read_irqsave().clone()
} }
#[inline] #[inline]
@ -353,14 +356,14 @@ impl TtyCoreData {
#[inline] #[inline]
pub fn set_termios(&self, termios: Termios) { 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; *termios_guard = termios;
} }
#[inline] #[inline]
pub fn add_count(&self) { pub fn add_count(&self) {
let mut guard = self.count.write(); self.count
*guard += 1; .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
} }
#[inline] #[inline]

View File

@ -36,6 +36,7 @@ use crate::{
}; };
use super::{ use super::{
kthread::tty_flush_thread_init,
termios::WindowSize, termios::WindowSize,
tty_core::{TtyCore, TtyFlag, TtyIoctlCmd}, tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation}, tty_driver::{TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
@ -528,5 +529,7 @@ pub fn tty_init() -> Result<(), SystemError> {
devfs_register(console.name, console)?; devfs_register(console.name, console)?;
serial_init()?; serial_init()?;
tty_flush_thread_init();
return vty_init(); return vty_init();
} }

View File

@ -1,4 +1,4 @@
use core::fmt::Debug; use core::{fmt::Debug, sync::atomic::Ordering};
use alloc::{ use alloc::{
sync::{Arc, Weak}, sync::{Arc, Weak},
@ -12,7 +12,7 @@ use crate::{
libs::spinlock::{SpinLock, SpinLockGuard}, 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; const TTY_PORT_BUFSIZE: usize = 4096;
@ -27,6 +27,12 @@ lazy_static! {
}; };
} }
/// 获取当前tty port
#[inline]
pub fn current_tty_port() -> Arc<dyn TtyPort> {
TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub struct TtyPortData { pub struct TtyPortData {

View File

@ -27,9 +27,8 @@ pub fn initial_kernel_thread() -> i32 {
} }
fn kernel_init() -> Result<(), SystemError> { fn kernel_init() -> Result<(), SystemError> {
kenrel_init_freeable()?;
KernelThreadMechanism::init_stage2(); KernelThreadMechanism::init_stage2();
kenrel_init_freeable()?;
// 由于目前加锁,速度过慢,所以先不开启双缓冲 // 由于目前加锁,速度过慢,所以先不开启双缓冲
// scm_enable_double_buffer().expect("Failed to enable double buffer"); // scm_enable_double_buffer().expect("Failed to enable double buffer");

View File

@ -1,11 +1,4 @@
use core::sync::atomic::Ordering; use crate::driver::tty::kthread::send_to_tty_refresh_thread;
use alloc::sync::Arc;
use crate::driver::tty::{
tty_port::{TtyPort, TTY_PORTS},
virtual_terminal::virtual_console::CURRENT_VCNUM,
};
#[allow(dead_code)] #[allow(dead_code)]
pub const NUM_SCAN_CODES: u8 = 0x80; pub const NUM_SCAN_CODES: u8 = 0x80;
@ -360,12 +353,7 @@ impl TypeOneFSMState {
#[inline(always)] #[inline(always)]
fn emit(ch: u8) { fn emit(ch: u8) {
// 发送到tty // 发送到tty
let _ = Self::current_port().receive_buf(&[ch], &[], 1); send_to_tty_refresh_thread(&[ch]);
}
#[inline]
fn current_port() -> Arc<dyn TtyPort> {
TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
} }
/// @brief 处理Prtsc按下事件 /// @brief 处理Prtsc按下事件

View File

@ -165,8 +165,15 @@ impl ProcessManager {
let mut args = KernelCloneArgs::new(); let mut args = KernelCloneArgs::new();
args.flags = clone_flags; args.flags = clone_flags;
args.exit_signal = Signal::SIGCHLD; args.exit_signal = Signal::SIGCHLD;
Self::copy_process(&current_pcb, &pcb, args, current_trapframe).map_err(|e| {
Self::copy_process(&current_pcb, &pcb, args, current_trapframe)?; kerror!(
"fork: Failed to copy process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(),
pcb.pid(),
e
);
e
})?;
ProcessManager::add_pcb(pcb.clone()); ProcessManager::add_pcb(pcb.clone());
// 向procfs注册进程 // 向procfs注册进程

View File

@ -87,9 +87,9 @@ impl KernelThreadPcbPrivate {
#[allow(dead_code)] #[allow(dead_code)]
pub enum KernelThreadClosure { pub enum KernelThreadClosure {
UsizeClosure((Box<dyn Fn(usize) -> i32 + Send + Sync>, usize)), UsizeClosure((Box<dyn Fn(usize) -> i32 + Send + Sync>, usize)),
StaticUsizeClosure((&'static dyn Fn(usize) -> i32, usize)), StaticUsizeClosure((&'static fn(usize) -> i32, usize)),
EmptyClosure((Box<dyn Fn() -> i32 + Send + Sync>, ())), EmptyClosure((Box<dyn Fn() -> i32 + Send + Sync>, ())),
StaticEmptyClosure((&'static dyn Fn() -> i32, ())), StaticEmptyClosure((&'static fn() -> i32, ())),
IrqThread( IrqThread(
( (
&'static dyn Fn(Arc<IrqAction>) -> Result<(), SystemError>, &'static dyn Fn(Arc<IrqAction>) -> Result<(), SystemError>,
@ -311,7 +311,7 @@ impl KernelThreadMechanism {
unsafe { unsafe {
KTHREAD_DAEMON_PCB.replace(pcb); 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 /// A daemon thread which creates other kernel threads
#[inline(never)]
fn kthread_daemon() -> i32 { fn kthread_daemon() -> i32 {
let current_pcb = ProcessManager::current_pcb(); let current_pcb = ProcessManager::current_pcb();
kdebug!("kthread_daemon: pid: {:?}", current_pcb.pid()); kdebug!("kthread_daemon: pid: {:?}", current_pcb.pid());
@ -454,9 +455,10 @@ impl KernelThreadMechanism {
drop(list); drop(list);
// create a new kernel thread // create a new kernel thread
let result: Result<Pid, SystemError> = let result: Result<Pid, SystemError> = Self::__inner_create(
Self::__inner_create(&info, CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL); &info,
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
);
if result.is_err() { if result.is_err() {
// 创建失败 // 创建失败
info.created info.created

View File

@ -439,6 +439,7 @@ impl ProcessManager {
/// 上下文切换的钩子函数,当这个函数return的时候,将会发生上下文切换 /// 上下文切换的钩子函数,当这个函数return的时候,将会发生上下文切换
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[inline(never)]
pub unsafe extern "sysv64" fn switch_finish_hook() { pub unsafe extern "sysv64" fn switch_finish_hook() {
ProcessManager::switch_finish_hook(); ProcessManager::switch_finish_hook();
} }
@ -891,7 +892,6 @@ impl ProcessControlBlock {
impl Drop for ProcessControlBlock { impl Drop for ProcessControlBlock {
fn drop(&mut self) { fn drop(&mut self) {
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
// kdebug!("drop: {:?}", self.pid);
// 在ProcFS中,解除进程的注册 // 在ProcFS中,解除进程的注册
procfs_unregister_pid(self.pid()) procfs_unregister_pid(self.pid())
.unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}")); .unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}"));

View File

@ -63,8 +63,8 @@ pub fn get_cpu_loads(cpu_id: ProcessorId) -> u32 {
} }
// 负载均衡 // 负载均衡
pub fn loads_balance(pcb: Arc<ProcessControlBlock>) { pub fn loads_balance(pcb: Arc<ProcessControlBlock>) {
// 对pcb的迁移情况进行调整 // FIXME: 由于目前负载均衡是直接添加到目标CPU的队列中导致会由于时序问题导致进程在两个CPU上都存在。
// 在调度子系统重写/改进之前暂时只设置进程在0号CPU上运行
// 由于调度器问题暂时不进行负载均衡见issue: https://github.com/DragonOS-Community/DragonOS/issues/571 // 由于调度器问题暂时不进行负载均衡见issue: https://github.com/DragonOS-Community/DragonOS/issues/571
let min_loads_cpu_id = ProcessorId::new(0); let min_loads_cpu_id = ProcessorId::new(0);