xref: /DragonOS/kernel/src/driver/tty/kthread.rs (revision 911132c4b8ea0e9c49a4e84b9fa1db114102acbb)
1 //! tty刷新内核线程
2 
3 use alloc::{string::ToString, sync::Arc};
4 use kdepends::thingbuf::StaticThingBuf;
5 
6 use crate::{
7     arch::sched::sched,
8     process::{
9         kthread::{KernelThreadClosure, KernelThreadMechanism},
10         ProcessControlBlock, ProcessFlags,
11     },
12 };
13 
14 use super::tty_port::current_tty_port;
15 
16 /// 用于缓存键盘输入的缓冲区
17 static KEYBUF: StaticThingBuf<u8, 512> = StaticThingBuf::new();
18 
19 static mut TTY_REFRESH_THREAD: Option<Arc<ProcessControlBlock>> = None;
20 
21 pub(super) fn tty_flush_thread_init() {
22     let closure =
23         KernelThreadClosure::StaticEmptyClosure((&(tty_refresh_thread as fn() -> i32), ()));
24     let pcb = KernelThreadMechanism::create_and_run(closure, "tty_refresh".to_string())
25         .ok_or("")
26         .expect("create tty_refresh thread failed");
27     unsafe {
28         TTY_REFRESH_THREAD = Some(pcb);
29     }
30 }
31 
32 fn tty_refresh_thread() -> i32 {
33     const TO_DEQUEUE_MAX: usize = 256;
34     loop {
35         if KEYBUF.is_empty() {
36             // 如果缓冲区为空,就休眠
37             unsafe {
38                 TTY_REFRESH_THREAD
39                     .as_ref()
40                     .unwrap()
41                     .flags()
42                     .insert(ProcessFlags::NEED_SCHEDULE)
43             };
44 
45             sched();
46         }
47 
48         let to_dequeue = core::cmp::min(KEYBUF.len(), TO_DEQUEUE_MAX);
49         if to_dequeue == 0 {
50             continue;
51         }
52         let mut data = [0u8; TO_DEQUEUE_MAX];
53         for item in data.iter_mut().take(to_dequeue) {
54             *item = KEYBUF.pop().unwrap();
55         }
56 
57         let _ = current_tty_port().receive_buf(&data[0..to_dequeue], &[], to_dequeue);
58     }
59 }
60 
61 /// 发送数据到tty刷新线程
62 pub fn send_to_tty_refresh_thread(data: &[u8]) {
63     for item in data {
64         KEYBUF.push(*item).ok();
65     }
66 }
67