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