1 //! tty刷新内核线程
2
3 use alloc::{string::ToString, sync::Arc};
4 use kdepends::thingbuf::StaticThingBuf;
5
6 use crate::{
7 arch::CurrentIrqArch,
8 driver::tty::virtual_terminal::virtual_console::CURRENT_VCNUM,
9 exception::InterruptArch,
10 process::{
11 kthread::{KernelThreadClosure, KernelThreadMechanism},
12 ProcessControlBlock, ProcessManager,
13 },
14 sched::{schedule, SchedMode},
15 };
16
17 use super::tty_port::current_tty_port;
18
19 /// 用于缓存键盘输入的缓冲区
20 static KEYBUF: StaticThingBuf<u8, 512> = StaticThingBuf::new();
21
22 static mut TTY_REFRESH_THREAD: Option<Arc<ProcessControlBlock>> = None;
23
tty_flush_thread_init()24 pub(super) fn tty_flush_thread_init() {
25 let closure =
26 KernelThreadClosure::StaticEmptyClosure((&(tty_refresh_thread as fn() -> i32), ()));
27 let pcb = KernelThreadMechanism::create_and_run(closure, "tty_refresh".to_string())
28 .ok_or("")
29 .expect("create tty_refresh thread failed");
30 unsafe {
31 TTY_REFRESH_THREAD = Some(pcb);
32 }
33 }
34
tty_refresh_thread() -> i3235 fn tty_refresh_thread() -> i32 {
36 const TO_DEQUEUE_MAX: usize = 256;
37 loop {
38 if KEYBUF.is_empty() {
39 // 如果缓冲区为空,就休眠
40 let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
41 ProcessManager::mark_sleep(true).expect("TTY_REFRESH_THREAD can not mark sleep");
42 schedule(SchedMode::SM_NONE);
43 }
44
45 let to_dequeue = core::cmp::min(KEYBUF.len(), TO_DEQUEUE_MAX);
46 if to_dequeue == 0 {
47 continue;
48 }
49 let mut data = [0u8; TO_DEQUEUE_MAX];
50 for item in data.iter_mut().take(to_dequeue) {
51 *item = KEYBUF.pop().unwrap();
52 }
53
54 if CURRENT_VCNUM.load(core::sync::atomic::Ordering::SeqCst) != -1 {
55 let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue);
56 } else {
57 // 这里由于stdio未初始化,所以无法找到port
58 // TODO: 考虑改用双端队列,能够将丢失的输入插回
59 }
60 }
61 }
62
63 /// 发送数据到tty刷新线程
send_to_tty_refresh_thread(data: &[u8])64 pub fn send_to_tty_refresh_thread(data: &[u8]) {
65 for item in data {
66 KEYBUF.push(*item).ok();
67 }
68 let _ = ProcessManager::wakeup(unsafe { TTY_REFRESH_THREAD.as_ref().unwrap() });
69 }
70