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 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 35 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刷新线程 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