2024-10-26 12:55:06 +08:00

74 lines
2.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! tty刷新内核线程
use alloc::{string::ToString, sync::Arc};
use kdepends::thingbuf::StaticThingBuf;
use crate::{
arch::CurrentIrqArch,
driver::tty::virtual_terminal::vc_manager,
exception::InterruptArch,
process::{
kthread::{KernelThreadClosure, KernelThreadMechanism},
ProcessControlBlock, ProcessManager,
},
sched::{schedule, SchedMode},
};
/// 用于缓存键盘输入的缓冲区
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() {
// 如果缓冲区为空,就休眠
let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::mark_sleep(true).expect("TTY_REFRESH_THREAD can not mark sleep");
schedule(SchedMode::SM_NONE);
}
let to_dequeue = core::cmp::min(KEYBUF.len(), TO_DEQUEUE_MAX);
if to_dequeue == 0 {
continue;
}
let mut data = [0u8; TO_DEQUEUE_MAX];
for item in data.iter_mut().take(to_dequeue) {
*item = KEYBUF.pop().unwrap();
}
if let Some(cur_vc) = vc_manager().current_vc() {
let _ = cur_vc
.port()
.receive_buf(&data[0..to_dequeue], &[], to_dequeue);
} else {
// 这里由于stdio未初始化所以无法找到port
// TODO: 考虑改用双端队列,能够将丢失的输入插回
}
}
}
/// 发送数据到tty刷新线程
pub fn send_to_tty_refresh_thread(data: &[u8]) {
if unsafe { TTY_REFRESH_THREAD.is_none() } {
return;
}
for item in data {
KEYBUF.push(*item).ok();
}
let _ = ProcessManager::wakeup(unsafe { TTY_REFRESH_THREAD.as_ref().unwrap() });
}