Skip to content

Commit

Permalink
fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染 (#592)
Browse files Browse the repository at this point in the history
fix: 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染
1.修正psmouse 日志
2. 键盘中断上下文不再直接操作tty,而是由专门的kthread来渲染
3. 由于调度器设计问题,load balance会由于时序问题导致错误.因此暂时只启用单核.
  • Loading branch information
fslongjin committed Mar 12, 2024
1 parent 818a64c commit 59fdb44
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 38 deletions.
3 changes: 2 additions & 1 deletion kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 66 additions & 0 deletions kernel/src/driver/tty/kthread.rs
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions kernel/src/driver/tty/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
19 changes: 11 additions & 8 deletions kernel/src/driver/tty/tty_core.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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());
}

Expand Down Expand Up @@ -289,7 +292,7 @@ pub struct TtyCoreData {
flags: RwLock<TtyFlag>,
/// 在初始化时即确定不会更改,所以这里不用加锁
index: usize,
count: RwLock<usize>,
count: AtomicUsize,
/// 窗口大小
window_size: RwLock<WindowSize>,
/// 读等待队列
Expand Down Expand Up @@ -338,7 +341,7 @@ impl TtyCoreData {

#[inline]
pub fn flags(&self) -> TtyFlag {
self.flags.read().clone()
self.flags.read_irqsave().clone()
}

#[inline]
Expand All @@ -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]
Expand Down
3 changes: 3 additions & 0 deletions kernel/src/driver/tty/tty_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -528,5 +529,7 @@ pub fn tty_init() -> Result<(), SystemError> {
devfs_register(console.name, console)?;

serial_init()?;

tty_flush_thread_init();
return vty_init();
}
10 changes: 8 additions & 2 deletions kernel/src/driver/tty/tty_port.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::fmt::Debug;
use core::{fmt::Debug, sync::atomic::Ordering};

use alloc::{
sync::{Arc, Weak},
Expand All @@ -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;

Expand All @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions kernel/src/init/initial_kthread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
16 changes: 2 additions & 14 deletions kernel/src/libs/keyboard_parser.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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按下事件
Expand Down
11 changes: 9 additions & 2 deletions kernel/src/process/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,15 @@ impl ProcessManager {
let mut args = KernelCloneArgs::new();
args.flags = clone_flags;
args.exit_signal = Signal::SIGCHLD;

Self::copy_process(&current_pcb, &pcb, args, current_trapframe)?;
Self::copy_process(&current_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注册进程
Expand Down
14 changes: 8 additions & 6 deletions kernel/src/process/kthread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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");
});
}

Expand Down Expand Up @@ -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());
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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:?}"));
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/sched/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 59fdb44

Please sign in to comment.