mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 04:56:30 +00:00
fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 (#592)
fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 1.修正psmouse 日志 2. 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 3. 由于调度器设计问题,load balance会由于时序问题导致错误.因此暂时只启用单核.
This commit is contained in:
@ -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(());
|
||||
}
|
||||
|
66
kernel/src/driver/tty/kthread.rs
Normal file
66
kernel/src/driver/tty/kthread.rs
Normal 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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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<TtyFlag>,
|
||||
/// 在初始化时即确定不会更改,所以这里不用加锁
|
||||
index: usize,
|
||||
count: RwLock<usize>,
|
||||
count: AtomicUsize,
|
||||
/// 窗口大小
|
||||
window_size: RwLock<WindowSize>,
|
||||
/// 读等待队列
|
||||
@ -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]
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<dyn TtyPort> {
|
||||
TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct TtyPortData {
|
||||
|
@ -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");
|
||||
|
@ -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<dyn TtyPort> {
|
||||
TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
|
||||
send_to_tty_refresh_thread(&[ch]);
|
||||
}
|
||||
|
||||
/// @brief 处理Prtsc按下事件
|
||||
|
@ -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注册进程
|
||||
|
@ -87,9 +87,9 @@ impl KernelThreadPcbPrivate {
|
||||
#[allow(dead_code)]
|
||||
pub enum KernelThreadClosure {
|
||||
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>, ())),
|
||||
StaticEmptyClosure((&'static dyn Fn() -> i32, ())),
|
||||
StaticEmptyClosure((&'static fn() -> i32, ())),
|
||||
IrqThread(
|
||||
(
|
||||
&'static dyn Fn(Arc<IrqAction>) -> 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<Pid, SystemError> =
|
||||
Self::__inner_create(&info, CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL);
|
||||
|
||||
let result: Result<Pid, SystemError> = Self::__inner_create(
|
||||
&info,
|
||||
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
|
||||
);
|
||||
if result.is_err() {
|
||||
// 创建失败
|
||||
info.created
|
||||
|
@ -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:?}"));
|
||||
|
@ -63,8 +63,8 @@ pub fn get_cpu_loads(cpu_id: ProcessorId) -> u32 {
|
||||
}
|
||||
// 负载均衡
|
||||
pub fn loads_balance(pcb: Arc<ProcessControlBlock>) {
|
||||
// 对pcb的迁移情况进行调整
|
||||
|
||||
// FIXME: 由于目前负载均衡是直接添加到目标CPU的队列中,导致会由于时序问题导致进程在两个CPU上都存在。
|
||||
// 在调度子系统重写/改进之前,暂时只设置进程在0号CPU上运行
|
||||
// 由于调度器问题,暂时不进行负载均衡,见issue: https://github.com/DragonOS-Community/DragonOS/issues/571
|
||||
let min_loads_cpu_id = ProcessorId::new(0);
|
||||
|
||||
|
Reference in New Issue
Block a user