mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 07:03:22 +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)]
|
#[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(());
|
||||||
}
|
}
|
||||||
|
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;
|
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;
|
||||||
|
@ -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]
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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");
|
||||||
|
@ -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按下事件
|
||||||
|
@ -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(¤t_pcb, &pcb, args, current_trapframe).map_err(|e| {
|
||||||
Self::copy_process(¤t_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注册进程
|
||||||
|
@ -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
|
||||||
|
@ -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:?}"));
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user