From 52bcb59e9286def2b66d766f6bf6f46745795ec8 Mon Sep 17 00:00:00 2001 From: GnoCiYeH Date: Mon, 11 Mar 2024 15:13:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84Tty=E7=9A=84RawMode=20(#577)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 完善rowmode,改掉一部分bug * 增加两个ansi拓展功能功能,以及标记部分函数nerve inline * 修改do_signal和其他中断上下文锁未关中断,以及拓展tty功能,修改tty几个算法bug * 修改两个锁 * 修改syscall_64 * update --- kernel/src/arch/x86_64/asm/entry.S | 3 + kernel/src/arch/x86_64/ipc/signal.rs | 5 +- kernel/src/driver/tty/termios.rs | 137 +++++++------- kernel/src/driver/tty/tty_core.rs | 27 ++- kernel/src/driver/tty/tty_device.rs | 33 +++- kernel/src/driver/tty/tty_job_control.rs | 12 +- kernel/src/driver/tty/tty_ldisc/mod.rs | 2 +- kernel/src/driver/tty/tty_ldisc/ntty.rs | 138 ++++++++++---- kernel/src/driver/tty/virtual_terminal/mod.rs | 119 ++++++------ .../tty/virtual_terminal/virtual_console.rs | 56 ++++-- .../fbdev/base/fbcon/framebuffer_console.rs | 29 ++- kernel/src/driver/video/fbdev/base/mod.rs | 4 +- kernel/src/driver/video/fbdev/vesafb.rs | 171 ++++++++++++------ kernel/src/filesystem/vfs/file.rs | 13 +- kernel/src/filesystem/vfs/mount.rs | 5 + kernel/src/ipc/signal.rs | 18 +- kernel/src/libs/printk.c | 2 +- kernel/src/libs/rwlock.rs | 17 ++ kernel/src/net/event_poll/mod.rs | 4 +- kernel/src/process/fork.rs | 16 +- kernel/src/process/mod.rs | 32 ++-- kernel/src/process/syscall.rs | 8 +- 22 files changed, 561 insertions(+), 290 deletions(-) diff --git a/kernel/src/arch/x86_64/asm/entry.S b/kernel/src/arch/x86_64/asm/entry.S index 7b7c5758..f61d7472 100644 --- a/kernel/src/arch/x86_64/asm/entry.S +++ b/kernel/src/arch/x86_64/asm/entry.S @@ -327,6 +327,7 @@ ENTRY(ignore_int) ENTRY(syscall_64) // 切换用户栈和内核栈 + cli swapgs movq %rsp, %gs:0x8 movq %gs:0x0, %rsp @@ -372,10 +373,12 @@ ENTRY(syscall_64) movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数 + sti callq *%rdx //调用服务程序 // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数 movq %rsp, %rdi + callq do_signal cli diff --git a/kernel/src/arch/x86_64/ipc/signal.rs b/kernel/src/arch/x86_64/ipc/signal.rs index d798ec1c..af23d152 100644 --- a/kernel/src/arch/x86_64/ipc/signal.rs +++ b/kernel/src/arch/x86_64/ipc/signal.rs @@ -415,7 +415,8 @@ pub struct X86_64SignalArch; impl SignalArch for X86_64SignalArch { unsafe fn do_signal(frame: &mut TrapFrame) { let pcb = ProcessManager::current_pcb(); - let siginfo = pcb.try_siginfo(5); + + let siginfo = pcb.try_siginfo_irqsave(5); if unlikely(siginfo.is_none()) { return; @@ -437,7 +438,7 @@ impl SignalArch for X86_64SignalArch { let sig_block: SigSet = siginfo_read_guard.sig_block().clone(); drop(siginfo_read_guard); - let sig_guard = pcb.try_sig_struct_irq(5); + let sig_guard = pcb.try_sig_struct_irqsave(5); if unlikely(sig_guard.is_none()) { return; } diff --git a/kernel/src/driver/tty/termios.rs b/kernel/src/driver/tty/termios.rs index 67809648..5dd8b406 100644 --- a/kernel/src/driver/tty/termios.rs +++ b/kernel/src/driver/tty/termios.rs @@ -140,12 +140,12 @@ bitflags! { /// termios输入特性 pub struct InputMode: u32 { /// 如果设置了该标志,表示启用软件流控制。 - const IXON = 0x0200; + const IXON = 0x0400; /// 如果设置了该标志,表示启用输入流控制。 - const IXOFF = 0x0400; + const IXOFF = 0x1000; /// Map Uppercase to Lowercase on Input 将大写转换为小写 /// 表示不区分大小写 - const IUCLC = 0x1000; + const IUCLC = 0x0200; /// 如果设置了该标志,表示当输入队列满时,产生一个响铃信号。 const IMAXBEL = 0x2000; /// 如果设置了该标志,表示输入数据被视为 UTF-8 编码。 @@ -176,46 +176,44 @@ bitflags! { /// termios输出特性 pub struct OutputMode: u32 { /// 在输出时将换行符替换\r\n - const ONLCR = 0x00002; + const ONLCR = 0x00004; /// Map Lowercase to Uppercase on Output 输出字符时将小写字母映射为大写字母 - const OLCUC = 0x00004; + const OLCUC = 0x00002; /// 与NL协同 配置换行符的处理方式 - const NLDLY = 0x00300; + const NLDLY = 0x00100; const NL0 = 0x00000; // 不延迟换行 const NL1 = 0x00100; // 延迟换行(输出回车后等待一段时间再输出换行) - const NL2 = 0x00200; // NL2 和 NL3保留,暂未使用 - const NL3 = 0x00300; /// 配置水平制表符的处理方式 - const TABDLY = 0x00c00; + const TABDLY = 0x01800; const TAB0 = 0x00000; // 不延迟水平制表符 - const TAB1 = 0x00400; // 在输出水平制表符时,延迟到下一个设置的水平制表符位置 - const TAB2 = 0x00800; // 在输出水平制表符时,延迟到下一个设置的 8 的倍数的位置 - const TAB3 = 0x00c00; // TAB3 和 XTABS(与 TAB3 等效)保留,暂未使用 - const XTABS = 0x00c00; + const TAB1 = 0x00800; // 在输出水平制表符时,延迟到下一个设置的水平制表符位置 + const TAB2 = 0x01000; // 在输出水平制表符时,延迟到下一个设置的 8 的倍数的位置 + const TAB3 = 0x01800; // TAB3 和 XTABS(与 TAB3 等效)保留,暂未使用 + const XTABS = 0x01800; /// 配置回车符的处理方式 - const CRDLY = 0x03000; + const CRDLY = 0x00600; const CR0 = 0x00000; // 不延迟回车 - const CR1 = 0x01000; // 延迟回车(输出回车后等待一段时间再输出换行) - const CR2 = 0x02000; // CR2 和 CR3保留,暂未使用 - const CR3 = 0x03000; + const CR1 = 0x02000; // 延迟回车(输出回车后等待一段时间再输出换行) + const CR2 = 0x04000; // CR2 和 CR3保留,暂未使用 + const CR3 = 0x06000; /// 配置换页符(form feed)的处理方式 - const FFDLY = 0x04000; + const FFDLY = 0x08000; const FF0 = 0x00000; // 不延迟换页 - const FF1 = 0x04000; // 延迟换页 + const FF1 = 0x08000; // 延迟换页 /// 配置退格符(backspace)的处理方式 - const BSDLY = 0x08000; + const BSDLY = 0x02000; const BS0 = 0x00000; // 不延迟退格 - const BS1 = 0x08000; // 延迟退格 + const BS1 = 0x02000; // 延迟退格 /// 配置垂直制表符(vertical tab)的处理方式 - const VTDLY = 0x10000; + const VTDLY = 0x04000; const VT0 = 0x00000; // 不延迟垂直制表符 - const VT1 = 0x10000; // 延迟垂直制表符 + const VT1 = 0x04000; // 延迟垂直制表符 /// 表示执行输出处理,即启用输出处理函数 const OPOST = 0x01; @@ -234,13 +232,14 @@ bitflags! { /// 配置终端设备的基本特性和控制参数 pub struct ControlMode: u32 { /// Baud Rate Mask 指定波特率的掩码 - const CBAUD = 0x000000ff; + const CBAUD = 0x0000100f; /// Extra Baud Bits 指定更高的波特率位 - const CBAUDEX = 0x00000000; + const CBAUDEX = 0x00001000; /// Custom Baud Rate 指定自定义波特率 如果设置了 BOTHER,则通过以下位来设置自定义的波特率值 - const BOTHER = 0x0000001f; + const BOTHER = 0x00001000; - const B0 = 0x00000000; + /* Common CBAUD rates */ + const B0 = 0x00000000; /* hang up */ const B50 = 0x00000001; const B75 = 0x00000002; const B110 = 0x00000003; @@ -257,43 +256,43 @@ bitflags! { const B19200 = 0x0000000e; const B38400 = 0x0000000f; - const B57600 = 0x00000010; - const B115200 = 0x00000011; - const B230400 = 0x00000012; - const B460800 = 0x00000013; - const B500000 = 0x00000014; - const B576000 = 0x00000015; - const B921600 = 0x00000016; - const B1000000 = 0x00000017; - const B1152000 = 0x00000018; - const B1500000 = 0x00000019; - const B2000000 = 0x0000001a; - const B2500000 = 0x0000001b; - const B3000000 = 0x0000001c; - const B3500000 = 0x0000001d; - const B4000000 = 0x0000001e; + const B57600 = 0x00001001; + const B115200 = 0x00001002; + const B230400 = 0x00001003; + const B460800 = 0x00001004; + const B500000 = 0x00001005; + const B576000 = 0x00001006; + const B921600 = 0x00001007; + const B1000000 = 0x00001008; + const B1152000 = 0x00001009; + const B1500000 = 0x0000100a; + const B2000000 = 0x0000100b; + const B2500000 = 0x0000100c; + const B3000000 = 0x0000100d; + const B3500000 = 0x0000100e; + const B4000000 = 0x0000100f; /// 指定字符大小的掩码 以下位为特定字符大小 - const CSIZE = 0x00000300; + const CSIZE = 0x00000030; const CS5 = 0x00000000; - const CS6 = 0x00000100; - const CS7 = 0x00000200; - const CS8 = 0x00000300; + const CS6 = 0x00000010; + const CS7 = 0x00000020; + const CS8 = 0x00000030; /// Stop Bit Select 表示使用两个停止位;否则,表示使用一个停止位 - const CSTOPB = 0x00000400; + const CSTOPB = 0x00000040; /// 表示启用接收器。如果未设置,则禁用接收器。 - const CREAD = 0x00000800; + const CREAD = 0x00000080; /// 表示启用奇偶校验。如果未设置,则禁用奇偶校验。 - const PARENB = 0x00001000; + const PARENB = 0x00000100; /// 表示启用奇校验。如果未设置,则表示启用偶校验。 - const PARODD = 0x00002000; + const PARODD = 0x00000200; /// 表示在终端设备被关闭时挂断线路(执行挂断操作) - const HUPCL = 0x00004000; + const HUPCL = 0x00000400; /// 表示忽略调制解调器的状态(DCD、DSR、CTS 等) - const CLOCAL = 0x00008000; + const CLOCAL = 0x00000800; /// 指定输入波特率的掩码 - const CIBAUD = 0x00ff0000; + const CIBAUD = 0x100f0000; const ADDRB = 0x20000000; } @@ -301,37 +300,37 @@ bitflags! { /// 配置终端设备的本地模式(local mode)或控制输入处理的行为 pub struct LocalMode: u32 { /// 启用中断字符(Ctrl-C、Ctrl-Z) - const ISIG = 0x00000080; + const ISIG = 0x00001; /// 表示启用规范模式,即启用行缓冲和回显。在规范模式下,输入被缓冲,并且只有在输入回车符时才会传递给应用程序。 - const ICANON = 0x00000100; + const ICANON = 0x00002; /// 表示启用大写模式,即输入输出都将被转换为大写。 - const XCASE = 0x00004000; + const XCASE = 0x00004; /// 表示启用回显(显示用户输入的字符) - const ECHO = 0x00000008; + const ECHO = 0x00008; /// 表示在回显时将擦除的字符用 backspace 和空格字符显示。 - const ECHOE = 0x00000002; + const ECHOE = 0x00010; /// 表示在回显时将换行符后的字符用空格字符显示。 - const ECHOK = 0x00000004; + const ECHOK = 0x00020; /// 表示在回显时将换行符显示为换行和回车符。 - const ECHONL = 0x00000010; + const ECHONL = 0x00040; /// 表示在收到中断(Ctrl-C)和退出(Ctrl-\)字符后,不清空输入和输出缓冲区。 - const NOFLSH = 0x80000000; + const NOFLSH = 0x00080; /// 表示在后台进程尝试写入终端时,发送停止信号(Ctrl-S) - const TOSTOP = 0x00400000; + const TOSTOP = 0x00100; /// 表示在回显时,显示控制字符为 ^ 加字符。 - const ECHOCTL= 0x00000040; + const ECHOCTL= 0x00200; /// 表示在回显时显示带有 # 的换行符(为了与 echo -n 命令兼容)。 - const ECHOPRT= 0x00000020; + const ECHOPRT= 0x00400; /// 表示在回显时将 KILL 字符(Ctrl-U)用空格字符显示。 - const ECHOKE = 0x00000001; + const ECHOKE = 0x00800; /// 表示输出正在被冲刷(flush),通常是由于输入/输出流的状态变化。 - const FLUSHO = 0x00800000; + const FLUSHO = 0x01000; /// 表示在规范模式下,存在需要重新打印的字符。 - const PENDIN = 0x20000000; + const PENDIN = 0x04000; /// 表示启用实现定义的输入处理。 - const IEXTEN = 0x00000400; + const IEXTEN = 0x08000; /// 表示启用扩展的处理函数 - const EXTPROC= 0x10000000; + const EXTPROC= 0x10000; } pub struct TtySetTermiosOpt: u8 { diff --git a/kernel/src/driver/tty/tty_core.rs b/kernel/src/driver/tty/tty_core.rs index 8b415837..46bcd3a2 100644 --- a/kernel/src/driver/tty/tty_core.rs +++ b/kernel/src/driver/tty/tty_core.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, sync::atomic::AtomicBool}; -use alloc::{string::String, sync::Arc, vec::Vec}; +use alloc::{collections::LinkedList, string::String, sync::Arc, vec::Vec}; use system_error::SystemError; use crate::{ @@ -11,7 +11,7 @@ use crate::{ wait_queue::EventWaitQueue, }, mm::VirtAddr, - net::event_poll::EPollEventType, + net::event_poll::{EPollEventType, EPollItem}, process::Pid, syscall::user_access::{UserBufferReader, UserBufferWriter}, }; @@ -53,6 +53,7 @@ impl TtyCore { closing: AtomicBool::new(false), flow: SpinLock::new(TtyFlowState::default()), link: None, + epitems: SpinLock::new(LinkedList::new()), }; return Arc::new(Self { @@ -159,6 +160,13 @@ impl TtyCore { user_writer.copy_one_to_user(&termios, 0)?; return Ok(0); } + TtyIoctlCmd::TCSETS => { + return TtyCore::core_set_termios( + real_tty, + VirtAddr::new(arg), + TtySetTermiosOpt::TERMIOS_OLD, + ); + } TtyIoctlCmd::TCSETSW => { return TtyCore::core_set_termios( real_tty, @@ -213,9 +221,7 @@ impl TtyCore { let mut termios = tty.core().termios_write(); let old_termios = termios.clone(); - *termios = new_termios; - let tmp = termios.control_mode; termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB; @@ -300,6 +306,8 @@ pub struct TtyCoreData { flow: SpinLock, /// 链接tty link: Option>, + /// epitems + epitems: SpinLock>>, } impl TtyCoreData { @@ -335,17 +343,17 @@ impl TtyCoreData { #[inline] pub fn termios(&self) -> RwLockReadGuard<'_, Termios> { - self.termios.read() + self.termios.read_irqsave() } #[inline] pub fn termios_write(&self) -> RwLockWriteGuard { - self.termios.write() + self.termios.write_irqsave() } #[inline] pub fn set_termios(&self, termios: Termios) { - let mut termios_guard = self.termios.write(); + let mut termios_guard = self.termios.write_irqsave(); *termios_guard = termios; } @@ -394,6 +402,11 @@ impl TtyCoreData { pub fn link(&self) -> Option> { self.link.clone() } + + #[inline] + pub fn add_epitem(&self, epitem: Arc) { + self.epitems.lock().push_back(epitem) + } } /// TTY 核心接口,不同的tty需要各自实现这个trait diff --git a/kernel/src/driver/tty/tty_device.rs b/kernel/src/driver/tty/tty_device.rs index b6b97c28..392c8088 100644 --- a/kernel/src/driver/tty/tty_device.rs +++ b/kernel/src/driver/tty/tty_device.rs @@ -30,8 +30,9 @@ use crate::{ init::initcall::INITCALL_DEVICE, libs::rwlock::RwLock, mm::VirtAddr, + net::event_poll::{EPollItem, EventPoll}, process::ProcessManager, - syscall::user_access::UserBufferWriter, + syscall::user_access::{UserBufferReader, UserBufferWriter}, }; use super::{ @@ -131,7 +132,7 @@ impl IndexNode for TtyDevice { && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster)) { let pcb = ProcessManager::current_pcb(); - let pcb_tty = pcb.sig_info().tty(); + let pcb_tty = pcb.sig_info_irqsave().tty(); if pcb_tty.is_none() && tty.core().contorl_info_irqsave().session.is_none() { TtyJobCtrlManager::proc_set_tty(tty); } @@ -210,7 +211,7 @@ impl IndexNode for TtyDevice { // 将数据从buf拷贝到writebuf - let ret = ld.write(tty.clone(), buf, size, mode)?; + let ret = ld.write(tty.clone(), &buf[written..], size, mode)?; written += ret; count -= ret; @@ -219,7 +220,7 @@ impl IndexNode for TtyDevice { break; } - if pcb.sig_info().sig_pending().has_pending() { + if pcb.sig_info_irqsave().sig_pending().has_pending() { return Err(SystemError::ERESTARTSYS); } } @@ -273,6 +274,20 @@ impl IndexNode for TtyDevice { todo!() } } + EventPoll::ADD_EPOLLITEM => { + let _ = UserBufferReader::new( + arg as *const Arc, + core::mem::size_of::>(), + false, + )?; + let epitem = unsafe { &*(arg as *const Arc) }; + + let core = tty.core(); + + core.add_epitem(epitem.clone()); + + return Ok(0); + } _ => {} } @@ -319,6 +334,16 @@ impl IndexNode for TtyDevice { Ok(0) } + + fn poll(&self, private_data: &FilePrivateData) -> Result { + let (tty, _) = if let FilePrivateData::Tty(tty_priv) = private_data { + (tty_priv.tty.clone(), tty_priv.mode) + } else { + return Err(SystemError::EIO); + }; + + tty.ldisc().poll(tty) + } } impl DeviceINode for TtyDevice { diff --git a/kernel/src/driver/tty/tty_job_control.rs b/kernel/src/driver/tty/tty_job_control.rs index 9387ea23..39e1335f 100644 --- a/kernel/src/driver/tty/tty_job_control.rs +++ b/kernel/src/driver/tty/tty_job_control.rs @@ -34,7 +34,9 @@ impl TtyJobCtrlManager { pub fn tty_check_change(tty: Arc, sig: Signal) -> Result<(), SystemError> { let pcb = ProcessManager::current_pcb(); - if pcb.sig_info().tty().is_none() || !Arc::ptr_eq(&pcb.sig_info().tty().unwrap(), &tty) { + if pcb.sig_info_irqsave().tty().is_none() + || !Arc::ptr_eq(&pcb.sig_info_irqsave().tty().unwrap(), &tty) + { return Ok(()); } @@ -91,8 +93,8 @@ impl TtyJobCtrlManager { let mut ctrl = tty.core().contorl_info_irqsave(); - if current.sig_info().tty().is_none() - || !Arc::ptr_eq(¤t.sig_info().tty().clone().unwrap(), &tty) + if current.sig_info_irqsave().tty().is_none() + || !Arc::ptr_eq(¤t.sig_info_irqsave().tty().clone().unwrap(), &tty) || ctrl.session.is_none() || ctrl.session.unwrap() != current.pid() { @@ -106,8 +108,8 @@ impl TtyJobCtrlManager { TtyIoctlCmd::TIOCGPGRP => { let current = ProcessManager::current_pcb(); - if current.sig_info().tty().is_some() - && !Arc::ptr_eq(¤t.sig_info().tty().unwrap(), &tty) + if current.sig_info_irqsave().tty().is_some() + && !Arc::ptr_eq(¤t.sig_info_irqsave().tty().unwrap(), &tty) { return Err(SystemError::ENOTTY); } diff --git a/kernel/src/driver/tty/tty_ldisc/mod.rs b/kernel/src/driver/tty/tty_ldisc/mod.rs index 722a0d61..8f3d0475 100644 --- a/kernel/src/driver/tty/tty_ldisc/mod.rs +++ b/kernel/src/driver/tty/tty_ldisc/mod.rs @@ -48,7 +48,7 @@ pub trait TtyLineDiscipline: Sync + Send + Debug { /// - old: 之前的termios,如果为None则表示第一次设置 fn set_termios(&self, tty: Arc, old: Option) -> Result<(), SystemError>; - fn poll(&self, tty: Arc) -> Result<(), SystemError>; + fn poll(&self, tty: Arc) -> Result; fn hangup(&self, tty: Arc) -> Result<(), SystemError>; /// ## 接收数据 diff --git a/kernel/src/driver/tty/tty_ldisc/ntty.rs b/kernel/src/driver/tty/tty_ldisc/ntty.rs index 57495add..98007e1a 100644 --- a/kernel/src/driver/tty/tty_ldisc/ntty.rs +++ b/kernel/src/driver/tty/tty_ldisc/ntty.rs @@ -1,3 +1,4 @@ +use core::intrinsics::likely; use core::ops::BitXor; use bitmap::{traits::BitMapOps, StaticBitmap}; @@ -249,11 +250,10 @@ impl NTtyData { || termios.local_mode.contains(LocalMode::IEXTEN); let look_ahead = self.lookahead_count.min(count); - if self.real_raw { - todo!("tty real raw mode todo"); + self.receive_buf_real_raw(buf, count); } else if self.raw || (termios.local_mode.contains(LocalMode::EXTPROC) && !preops) { - todo!("tty raw mode todo"); + self.receive_buf_raw(buf, flags, count); } else if tty.core().is_closing() && !termios.local_mode.contains(LocalMode::EXTPROC) { todo!() } else { @@ -282,7 +282,47 @@ impl NTtyData { if self.read_cnt() > 0 { tty.core() .read_wq() - .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64); + .wakeup_any((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64); + } + } + + fn receive_buf_real_raw(&mut self, buf: &[u8], mut count: usize) { + let mut head = ntty_buf_mask(self.read_head); + let mut n = count.min(NTTY_BUFSIZE - head); + + // 假如有一部分在队列头部,则这部分是拷贝尾部部分 + self.read_buf[head..(head + n)].copy_from_slice(&buf[0..n]); + self.read_head += n; + count -= n; + let offset = n; + + // 假如有一部分在队列头部,则这部分是拷贝头部部分 + head = ntty_buf_mask(self.read_head); + n = count.min(NTTY_BUFSIZE - head); + self.read_buf[head..(head + n)].copy_from_slice(&buf[offset..(offset + n)]); + self.read_head += n; + } + + fn receive_buf_raw(&mut self, buf: &[u8], flags: Option<&[u8]>, mut count: usize) { + // TTY_NORMAL 目前这部分未做,所以先占位置而不做抽象 + let mut flag = 1; + let mut f_offset = 0; + let mut c_offset = 0; + while count != 0 { + if flags.is_some() { + flag = flags.as_ref().unwrap()[f_offset]; + f_offset += 1; + } + + if likely(flag == 1) { + self.read_buf[self.read_head] = buf[c_offset]; + c_offset += 1; + self.read_head += 1; + } else { + todo!() + } + + count -= 1; } } @@ -364,6 +404,7 @@ impl NTtyData { } } + #[inline(never)] pub fn receive_special_char(&mut self, mut c: u8, tty: Arc, lookahead_done: bool) { let is_flow_ctrl = self.is_flow_ctrl_char(tty.clone(), c, lookahead_done); let termios = tty.core().termios(); @@ -467,9 +508,9 @@ impl NTtyData { self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; self.canon_head = self.read_head; - tty.core() - .read_wq() - .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64); + tty.core().read_wq().wakeup_any( + (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64, + ); return; } @@ -480,9 +521,9 @@ impl NTtyData { self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; self.canon_head = self.read_head; - tty.core() - .read_wq() - .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64); + tty.core().read_wq().wakeup_any( + (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64, + ); return; } @@ -508,9 +549,9 @@ impl NTtyData { self.read_buf[ntty_buf_mask(self.read_head)] = c; self.read_head += 1; self.canon_head = self.read_head; - tty.core() - .read_wq() - .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64); + tty.core().read_wq().wakeup_any( + (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64, + ); return; } } @@ -540,6 +581,7 @@ impl NTtyData { } /// ## ntty默认eraser function + #[inline(never)] fn eraser(&mut self, mut c: u8, termios: &RwLockReadGuard) { if self.read_head == self.canon_head { return; @@ -907,7 +949,7 @@ impl NTtyData { // 有一部分数据在头部,则先拷贝后面部分,再拷贝头部 // TODO: tty审计? to[0..size].copy_from_slice(&self.read_buf[tail..(tail + size)]); - to[size..].copy_from_slice(&self.read_buf[(tail + size)..(*n + tail)]); + to[size..(*n)].copy_from_slice(&self.read_buf[0..(*n - size)]); } else { to[..*n].copy_from_slice(&self.read_buf[tail..(tail + *n)]) } @@ -975,7 +1017,7 @@ impl NTtyData { let size = if tail + n > NTTY_BUFSIZE { NTTY_BUFSIZE } else { - tail + *nr + tail + n }; // 找到eol的坐标 @@ -1088,7 +1130,7 @@ impl NTtyData { let tail = self.read_tail & (NTTY_BUFSIZE - 1); // 计算出可读的字符数 - let mut n = (NTTY_BUFSIZE - tail).min(self.read_tail); + let mut n = (NTTY_BUFSIZE - tail).min(head - self.read_tail); n = n.min(*nr); if n > 0 { @@ -1209,6 +1251,7 @@ impl NTtyData { } } + #[inline(never)] pub fn echoes(&mut self, tty: Arc) -> Result { let mut space = tty.write_room(tty.core()); let ospace = space; @@ -1519,6 +1562,7 @@ impl TtyLineDiscipline for NTtyLinediscipline { Ok(()) } + #[inline(never)] fn read( &self, tty: Arc, @@ -1555,7 +1599,7 @@ impl TtyLineDiscipline for NTtyLinediscipline { return Ok(len - nr); } } else { - if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? { + if ldata.copy_from_read_buf(termios, buf, &mut nr, &mut offset)? { return Ok(len - nr); } } @@ -1610,7 +1654,7 @@ impl TtyLineDiscipline for NTtyLinediscipline { } if ProcessManager::current_pcb() - .sig_info() + .sig_info_irqsave() .sig_pending() .has_pending() { @@ -1666,6 +1710,7 @@ impl TtyLineDiscipline for NTtyLinediscipline { ret } + #[inline(never)] fn write( &self, tty: Arc, @@ -1687,7 +1732,7 @@ impl TtyLineDiscipline for NTtyLinediscipline { // drop(ldata); let mut offset = 0; loop { - if pcb.sig_info().sig_pending().has_pending() { + if pcb.sig_info_irqsave().sig_pending().has_pending() { return Err(SystemError::ERESTARTSYS); } if core.flags().contains(TtyFlag::HUPPED) { @@ -1818,6 +1863,7 @@ impl TtyLineDiscipline for NTtyLinediscipline { } } + #[inline(never)] fn set_termios( &self, tty: Arc, @@ -1829,14 +1875,13 @@ impl TtyLineDiscipline for NTtyLinediscipline { let contorl_chars = termios.control_characters; // 第一次设置或者规范模式 (ICANON) 或者扩展处理 (EXTPROC) 标志发生变化 - if old.is_none() - || (old.is_some() - && old - .unwrap() - .local_mode - .bitxor(termios.local_mode) - .contains(LocalMode::ICANON | LocalMode::EXTPROC)) - { + let mut spec_mode_changed = false; + if old.is_some() { + let local_mode = old.clone().unwrap().local_mode.bitxor(termios.local_mode); + spec_mode_changed = + local_mode.contains(LocalMode::ICANON) || local_mode.contains(LocalMode::EXTPROC); + } + if old.is_none() || spec_mode_changed { // 重置read_flags ldata.read_flags.set_all(false); @@ -1859,10 +1904,8 @@ impl TtyLineDiscipline for NTtyLinediscipline { ldata.lnext = false; } - // 设置规范模式 - if termios.local_mode.contains(LocalMode::ICANON) { - ldata.icanon = true; - } + // 设置模式 + ldata.icanon = termios.local_mode.contains(LocalMode::ICANON); // 设置回显 if termios.local_mode.contains(LocalMode::ECHO) { @@ -1984,8 +2027,37 @@ impl TtyLineDiscipline for NTtyLinediscipline { Ok(()) } - fn poll(&self, _tty: Arc) -> Result<(), system_error::SystemError> { - todo!() + fn poll(&self, tty: Arc) -> Result { + let core = tty.core(); + let ldata = self.disc_data(); + + let mut event = EPollEventType::empty(); + if ldata.input_available(core.termios(), true) { + event.insert(EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM) + } + + if core.contorl_info_irqsave().packet { + let link = core.link(); + if link.is_some() && link.unwrap().core().contorl_info_irqsave().pktstatus != 0 { + event.insert( + EPollEventType::EPOLLPRI + | EPollEventType::EPOLLIN + | EPollEventType::EPOLLRDNORM, + ); + } + } + + if core.flags().contains(TtyFlag::OTHER_CLOSED) { + event.insert(EPollEventType::EPOLLHUP); + } + + if core.driver().driver_funcs().chars_in_buffer() < 256 + && core.driver().driver_funcs().write_room(core) > 0 + { + event.insert(EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM); + } + + Ok(event.bits() as usize) } fn hangup(&self, _tty: Arc) -> Result<(), system_error::SystemError> { diff --git a/kernel/src/driver/tty/virtual_terminal/mod.rs b/kernel/src/driver/tty/virtual_terminal/mod.rs index 011d4129..b92aeb06 100644 --- a/kernel/src/driver/tty/virtual_terminal/mod.rs +++ b/kernel/src/driver/tty/virtual_terminal/mod.rs @@ -102,62 +102,8 @@ impl TtyConsoleDriverInner { console: Arc::new(BlittingFbConsole::new()?), }) } -} -impl TtyOperation for TtyConsoleDriverInner { - fn install(&self, _driver: Arc, tty: Arc) -> Result<(), SystemError> { - let tty_core = tty.core(); - let mut vc_data = VIRT_CONSOLES[tty_core.index()].lock(); - - self.console.con_init(&mut vc_data, true)?; - if vc_data.complement_mask == 0 { - vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 }; - } - vc_data.s_complement_mask = vc_data.complement_mask; - // vc_data.bytes_per_row = vc_data.cols << 1; - vc_data.index = tty_core.index(); - vc_data.bottom = vc_data.rows; - vc_data.set_driver_funcs(Arc::downgrade( - &(self.console.clone() as Arc), - )); - - // todo: unicode字符集处理? - - if vc_data.cols > VC_MAXCOL || vc_data.rows > VC_MAXROW { - return Err(SystemError::EINVAL); - } - - vc_data.init(None, None, true); - vc_data.update_attr(); - - let window_size = tty_core.window_size_upgradeable(); - if window_size.col == 0 && window_size.row == 0 { - let mut window_size = window_size.upgrade(); - window_size.col = vc_data.cols as u16; - window_size.row = vc_data.rows as u16; - } - - if vc_data.utf { - tty_core.termios_write().input_mode.insert(InputMode::IUTF8); - } else { - tty_core.termios_write().input_mode.remove(InputMode::IUTF8); - } - - // 加入sysfs? - - Ok(()) - } - - fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { - Ok(()) - } - - fn write_room(&self, _tty: &TtyCoreData) -> usize { - 32768 - } - - /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894 - fn write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result { + fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result { // 关闭中断 let mut vc_data = tty.vc_data_irqsave(); @@ -204,7 +150,70 @@ impl TtyOperation for TtyConsoleDriverInner { // TODO: notify update return Ok(offset); } +} +impl TtyOperation for TtyConsoleDriverInner { + fn install(&self, _driver: Arc, tty: Arc) -> Result<(), SystemError> { + let tty_core = tty.core(); + let mut vc_data = VIRT_CONSOLES[tty_core.index()].lock(); + + self.console.con_init(&mut vc_data, true)?; + if vc_data.complement_mask == 0 { + vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 }; + } + vc_data.s_complement_mask = vc_data.complement_mask; + // vc_data.bytes_per_row = vc_data.cols << 1; + vc_data.index = tty_core.index(); + vc_data.bottom = vc_data.rows; + vc_data.set_driver_funcs(Arc::downgrade( + &(self.console.clone() as Arc), + )); + + // todo: unicode字符集处理? + + if vc_data.cols > VC_MAXCOL || vc_data.rows > VC_MAXROW { + return Err(SystemError::EINVAL); + } + + vc_data.init(None, None, true); + vc_data.update_attr(); + + let window_size = tty_core.window_size_upgradeable(); + if window_size.col == 0 && window_size.row == 0 { + let mut window_size = window_size.upgrade(); + window_size.col = vc_data.cols as u16; + window_size.row = vc_data.rows as u16; + kerror!("window_size {:?}", *window_size); + } + + if vc_data.utf { + tty_core.termios_write().input_mode.insert(InputMode::IUTF8); + } else { + tty_core.termios_write().input_mode.remove(InputMode::IUTF8); + } + + // 加入sysfs? + + Ok(()) + } + + fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { + Ok(()) + } + + fn write_room(&self, _tty: &TtyCoreData) -> usize { + 32768 + } + + /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894 + #[inline(never)] + fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result { + let ret = self.do_write(tty, buf, nr); + self.flush_chars(tty); + ret + } + + #[inline(never)] fn flush_chars(&self, tty: &TtyCoreData) { let mut vc_data = tty.vc_data_irqsave(); vc_data.set_cursor(); diff --git a/kernel/src/driver/tty/virtual_terminal/virtual_console.rs b/kernel/src/driver/tty/virtual_terminal/virtual_console.rs index 0e7ecdd9..5746326e 100644 --- a/kernel/src/driver/tty/virtual_terminal/virtual_console.rs +++ b/kernel/src/driver/tty/virtual_terminal/virtual_console.rs @@ -7,7 +7,10 @@ use alloc::{ use bitmap::{traits::BitMapOps, StaticBitmap}; use crate::{ - driver::tty::{console::ConsoleSwitch, ConsoleFont, KDMode}, + driver::{ + serial::serial8250::send_to_default_serial8250_port, + tty::{console::ConsoleSwitch, ConsoleFont, KDMode}, + }, libs::{font::FontDesc, rwlock::RwLock}, process::Pid, }; @@ -140,6 +143,7 @@ pub struct VirtualConsoleData { } impl VirtualConsoleData { + #[inline(never)] pub fn new(num: usize) -> Self { Self { state: VirtualConsoleInfo::new(0, 0), @@ -264,7 +268,8 @@ impl VirtualConsoleData { self.pid = None; self.vc_state = VirtualConsoleState::ESnormal; self.reset_palette(); - self.cursor_type = VcCursor::CUR_UNDERLINE; + // self.cursor_type = VcCursor::CUR_UNDERLINE; + self.cursor_type = VcCursor::CUR_BLOCK; self.default_attr(); self.update_attr(); @@ -567,10 +572,10 @@ impl VirtualConsoleData { let min_y; if self.origin_mode { min_y = self.top; - max_y = self.bottom; + max_y = self.bottom - 1; } else { min_y = 0; - max_y = self.rows; + max_y = self.rows - 1; } if y < min_y as i32 { @@ -596,9 +601,10 @@ impl VirtualConsoleData { return; } - if self - .driver_funcs() - .con_scroll(self, self.top, self.bottom, dir, nr) + if self.is_visible() + && self + .driver_funcs() + .con_scroll(self, self.top, self.bottom, dir, nr) { // 如果成功 return; @@ -733,6 +739,7 @@ impl VirtualConsoleData { } } + #[inline(never)] fn do_getpars(&mut self, c: char) { if c == ';' && self.npar < (NPAR - 1) as u32 { self.npar += 1; @@ -789,9 +796,11 @@ impl VirtualConsoleData { 'n' => { if self.private == Vt102_OP::EPecma { if self.par[0] == 5 { - kwarn!("tty status report todo"); + send_to_default_serial8250_port("tty status report todo".as_bytes()); + panic!(); } else if self.par[0] == 6 { - kwarn!("tty cursor report todo"); + send_to_default_serial8250_port("tty cursor report todo".as_bytes()); + panic!(); } } return; @@ -847,7 +856,7 @@ impl VirtualConsoleData { self.par[0] += 1; } self.gotoxy( - (self.state.x - self.par[0] as usize) as i32, + self.state.x as i32 - self.par[0] as i32, self.state.y as i32, ); return; @@ -863,7 +872,7 @@ impl VirtualConsoleData { if self.par[0] == 0 { self.par[0] += 1; } - self.gotoxy(0, (self.state.y - self.par[0] as usize) as i32); + self.gotoxy(0, self.state.y as i32 - self.par[0] as i32); return; } 'd' => { @@ -874,6 +883,7 @@ impl VirtualConsoleData { return; } 'H' | 'f' => { + // MOVETO if self.par[0] != 0 { self.par[0] -= 1; } @@ -900,6 +910,18 @@ impl VirtualConsoleData { 'P' => { todo!("csi_P todo"); } + + // 非ANSI标准,为ANSI拓展 + 'S' => { + self.scroll(ScrollDir::Up, self.par[0] as usize); + return; + } + + 'T' => { + self.scroll(ScrollDir::Down, self.par[0] as usize); + return; + } + 'c' => { if self.par[0] == 0 { kwarn!("respone ID todo"); @@ -957,6 +979,7 @@ impl VirtualConsoleData { } /// ## 处理Control Sequence Introducer(控制序列引导符) m字符 + #[inline(never)] fn csi_m(&mut self) { let mut i = 0; loop { @@ -1236,6 +1259,7 @@ impl VirtualConsoleData { } /// ## 处理终端控制字符 + #[inline(never)] pub(super) fn do_control(&mut self, ch: u32) { // 首先检查是否处于 ANSI 控制字符串状态 if self.vc_state.is_ansi_control_string() && ch >= 8 && ch <= 13 { @@ -1512,6 +1536,7 @@ impl VirtualConsoleData { } } + #[inline(never)] pub(super) fn console_write_normal( &mut self, mut tc: u32, @@ -1641,11 +1666,10 @@ impl VirtualConsoleData { fn do_update_region(&self, mut start: usize, mut count: usize) { let ret = self.driver_funcs().con_getxy(self, start); let (mut x, mut y) = if ret.is_err() { - let offset = start / 2; - (offset % self.cols, offset / self.cols) + (start % self.cols, start / self.cols) } else { - let (tmp_start, tmp_x, tmp_y) = ret.unwrap(); - start = tmp_start; + let (_, tmp_x, tmp_y) = ret.unwrap(); + // start = tmp_start; (tmp_x, tmp_y) }; @@ -1697,6 +1721,8 @@ impl VirtualConsoleData { let ret = self.driver_funcs().con_getxy(self, start); if ret.is_ok() { start = ret.unwrap().0; + } else { + return; } } } diff --git a/kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs b/kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs index 744f6430..d225c1c2 100644 --- a/kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs +++ b/kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs @@ -391,6 +391,7 @@ impl ConsoleSwitch for BlittingFbConsole { Ok(()) } + #[inline(never)] fn con_scroll( &self, vc_data: &mut VirtualConsoleData, @@ -504,7 +505,30 @@ impl ConsoleSwitch for BlittingFbConsole { } match scroll_mode { - ScrollMode::Move => todo!(), + ScrollMode::Move => { + let start = top * vc_data.cols; + let end = bottom * vc_data.cols; + vc_data.screen_buf[start..end].rotate_right(count * vc_data.cols); + + let _ = self.bmove( + vc_data, + top as i32, + 0, + top as i32 + count as i32, + 0, + (bottom - top - count) as u32, + vc_data.cols as u32, + ); + + let _ = self.con_clear(vc_data, top, 0, count, vc_data.cols); + + let offset = vc_data.cols * count; + for i in vc_data.screen_buf[start..(start + offset)].iter_mut() { + *i = vc_data.erase_char; + } + + return true; + } ScrollMode::PanMove => todo!(), ScrollMode::WrapMove => todo!(), ScrollMode::Redraw => { @@ -554,7 +578,8 @@ impl FrameBufferConsole for BlittingFbConsole { sy * vc_data.font.height as i32, ); - self.fb().fb_copyarea(area) + self.fb().fb_copyarea(area); + Ok(()) } fn clear( diff --git a/kernel/src/driver/video/fbdev/base/mod.rs b/kernel/src/driver/video/fbdev/base/mod.rs index 3d1ad818..e3025080 100644 --- a/kernel/src/driver/video/fbdev/base/mod.rs +++ b/kernel/src/driver/video/fbdev/base/mod.rs @@ -408,9 +408,7 @@ pub trait FrameBufferOps { } /// 将数据从一处复制到另一处。 - fn fb_copyarea(&self, _data: CopyAreaData) -> Result<(), SystemError> { - Err(SystemError::ENOSYS) - } + fn fb_copyarea(&self, _data: CopyAreaData); /// 将帧缓冲区的内容映射到用户空间。 fn fb_mmap(&self, _vma: &Arc) -> Result<(), SystemError> { diff --git a/kernel/src/driver/video/fbdev/vesafb.rs b/kernel/src/driver/video/fbdev/vesafb.rs index 13d312fc..f718f71c 100644 --- a/kernel/src/driver/video/fbdev/vesafb.rs +++ b/kernel/src/driver/video/fbdev/vesafb.rs @@ -418,86 +418,138 @@ impl FrameBufferOps for VesaFb { Ok(()) } - fn fb_copyarea(&self, data: super::base::CopyAreaData) -> Result<(), SystemError> { + #[inline(never)] + fn fb_copyarea(&self, data: super::base::CopyAreaData) { let bp = boot_params().read(); - let base = bp.screen_info.lfb_virt_base.ok_or(SystemError::ENODEV)?; + let base = bp.screen_info.lfb_virt_base.unwrap(); let var = self.current_fb_var(); - if data.sx < 0 - || data.sy < 0 - || data.sx as u32 > var.xres - || data.sx as u32 + data.width > var.xres - || data.sy as u32 > var.yres - || data.sy as u32 + data.height > var.yres + // 原区域或者目标区域全在屏幕外,则直接返回 + if data.sx > var.xres as i32 + || data.sy > var.yres as i32 + || data.dx > var.xres as i32 + || data.dy > var.yres as i32 + || (data.sx + data.width as i32) < 0 + || (data.sy + data.height as i32) < 0 + || (data.dx + data.width as i32) < 0 + || (data.dy + data.height as i32) < 0 { - return Err(SystemError::EINVAL); + return; } + // 求两个矩形可视范围交集 + let (s_visiable_x, s_w) = if data.sx < 0 { + (0, (data.width - ((-data.sx) as u32)).min(var.xres)) + } else { + let w = if data.sx as u32 + data.width > var.xres { + var.xres - data.sx as u32 + } else { + data.width + }; + + (data.sx, w) + }; + let (s_visiable_y, s_h) = if data.sy < 0 { + (0, (data.height - ((-data.sy) as u32).min(var.yres))) + } else { + let h = if data.sy as u32 + data.height > var.yres { + var.yres - data.sy as u32 + } else { + data.height + }; + + (data.sy, h) + }; + + let (d_visiable_x, d_w) = if data.dx < 0 { + (0, (data.width - ((-data.dx) as u32)).min(var.xres)) + } else { + let w = if data.dx as u32 + data.width > var.xres { + var.xres - data.dx as u32 + } else { + data.width + }; + + (data.dx, w) + }; + let (d_visiable_y, d_h) = if data.dy < 0 { + (0, (data.height - ((-data.dy) as u32).min(var.yres))) + } else { + let h = if data.dy as u32 + data.height > var.yres { + var.yres - data.dy as u32 + } else { + data.height + }; + + (data.dy, h) + }; + + // 可视范围无交集 + if !(d_h + s_h > data.height && s_w + d_w > data.width) { + return; + } + + // 可视区域左上角相对于矩形的坐标 + let s_relative_x = s_visiable_x - data.sx; + let s_relative_y = s_visiable_y - data.sy; + let d_relative_x = d_visiable_x - data.dx; + let d_relative_y = d_visiable_y - data.dy; + + let visiable_x = s_relative_x.max(d_relative_x); + let visiable_y = s_relative_y.max(d_relative_y); + let visiable_h = d_h + s_h - data.height; + let visiable_w = d_w + s_w - data.width; + + let s_real_x = (visiable_x + data.sx) as u32; + let s_real_y = (visiable_y + data.sy) as u32; + let d_real_x = (visiable_x + data.dx) as u32; + let d_real_y = (visiable_y + data.dy) as u32; + let bytes_per_pixel = var.bits_per_pixel >> 3; let bytes_per_line = var.xres * bytes_per_pixel; - let sy = data.sy as u32; - let sx = data.sx as u32; + let src = + base + VirtAddr::new((s_real_y * bytes_per_line + s_real_x * bytes_per_pixel) as usize); - let dst = { - let mut dst = base; - if data.dy < 0 { - dst -= VirtAddr::new((((-data.dy) as u32) * bytes_per_line) as usize); - } else { - dst += VirtAddr::new(((data.dy as u32) * bytes_per_line) as usize); - } + let dst = + base + VirtAddr::new((d_real_y * bytes_per_line + d_real_x * bytes_per_pixel) as usize); - if data.dx > 0 && (data.dx as u32) < var.xres { - dst += VirtAddr::new(((data.dx as u32) * bytes_per_pixel) as usize); - } - - dst - }; - let src = base + VirtAddr::new((sy * bytes_per_line + sx * bytes_per_pixel) as usize); + let size = (visiable_h * visiable_w) as usize; match bytes_per_pixel { 4 => { // 32bpp let mut dst = dst.as_ptr::(); let mut src = src.as_ptr::(); + let line_offset = var.xres as usize; - for y in 0..data.height as usize { - if (data.dy + y as i32) < 0 || (data.dy + y as i32) > var.yres as i32 { - unsafe { - // core::ptr::copy(src, dst, data.width as usize); - src = src.add(var.xres as usize); - dst = dst.add(var.xres as usize); + if s_real_x > d_real_x { + // 如果src在dst下方,则可以直接拷贝不会出现指针覆盖 + unsafe { + for _ in 0..visiable_h { + core::ptr::copy(src, dst, visiable_w as usize); + src = src.add(line_offset); + dst = dst.add(visiable_w as usize); } - continue; } - if data.dx < 0 { - if ((-data.dx) as u32) < data.width { - unsafe { - core::ptr::copy( - src.add((-data.dx) as usize), - dst, - (data.width as usize) - (-data.dx) as usize, - ); - src = src.add(var.xres as usize); - dst = dst.add(var.xres as usize); - } + } else { + let mut tmp: Vec = Vec::with_capacity(size); + tmp.resize(size, 0); + let mut tmp_ptr = tmp.as_mut_ptr(); + + // 这里是一个可以优化的点,现在为了避免指针拷贝时覆盖,统一先拷贝进入buf再拷贝到dst + unsafe { + for _ in 0..visiable_h { + core::ptr::copy(src, tmp_ptr, visiable_w as usize); + src = src.add(line_offset); + tmp_ptr = tmp_ptr.add(visiable_w as usize); } - } else if data.dx as u32 + data.width > var.xres { - if (data.dx as u32) < var.xres { - unsafe { - core::ptr::copy(src, dst, (var.xres - data.dx as u32) as usize); - src = src.add(var.xres as usize); - dst = dst.add(var.xres as usize); - } - } - } else { - for i in 0..data.width as usize { - unsafe { *(dst.add(i)) = *(src.add(i)) } - } - unsafe { - // core::ptr::copy(src, dst, data.width as usize); - src = src.add(var.xres as usize); - dst = dst.add(var.xres as usize); + + tmp_ptr = tmp_ptr.sub(size); + for _ in 0..visiable_h { + core::ptr::copy(tmp_ptr, dst, visiable_w as usize); + dst = dst.add(line_offset); + tmp_ptr = tmp_ptr.add(visiable_w as usize); } } } @@ -506,7 +558,6 @@ impl FrameBufferOps for VesaFb { todo!() } } - Ok(()) } } diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 791962db..cf62990b 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -484,7 +484,18 @@ impl File { let inode = self.inode.downcast_ref::().unwrap(); return inode.inner().lock().add_epoll(epitem); } - _ => return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP), + _ => { + let r = self.inode.ioctl( + EventPoll::ADD_EPOLLITEM, + &epitem as *const Arc as usize, + &self.private_data, + ); + if r.is_err() { + return Err(SystemError::ENOSYS); + } + + Ok(()) + } } } diff --git a/kernel/src/filesystem/vfs/mount.rs b/kernel/src/filesystem/vfs/mount.rs index 908800ab..b38d76ea 100644 --- a/kernel/src/filesystem/vfs/mount.rs +++ b/kernel/src/filesystem/vfs/mount.rs @@ -369,6 +369,11 @@ impl IndexNode for MountFSInode { fn special_node(&self) -> Option { self.inner_inode.special_node() } + + #[inline] + fn poll(&self, private_data: &FilePrivateData) -> Result { + self.inner_inode.poll(private_data) + } } impl FileSystem for MountFS { diff --git a/kernel/src/ipc/signal.rs b/kernel/src/ipc/signal.rs index 28b53096..212981fc 100644 --- a/kernel/src/ipc/signal.rs +++ b/kernel/src/ipc/signal.rs @@ -86,7 +86,7 @@ impl Signal { return Err(SystemError::EINVAL); } // kdebug!("force send={}", force_send); - let pcb_info = pcb.sig_info(); + let pcb_info = pcb.sig_info_irqsave(); let pending = if matches!(pt, PidType::PID) { pcb_info.sig_shared_pending() } else { @@ -189,7 +189,11 @@ impl Signal { #[inline] fn wants_signal(&self, pcb: Arc) -> bool { // 如果改进程屏蔽了这个signal,则不能接收 - if pcb.sig_info().sig_block().contains(self.clone().into()) { + if pcb + .sig_info_irqsave() + .sig_block() + .contains(self.clone().into()) + { return false; } @@ -209,7 +213,7 @@ impl Signal { // todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项 // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true - if pcb.sig_info().sig_pending().signal().bits() == 0 { + if pcb.sig_info_irqsave().sig_pending().signal().bits() == 0 { return true; } else { return false; @@ -263,7 +267,11 @@ impl Signal { } // 一个被阻塞了的信号肯定是要被处理的 - if pcb.sig_info().sig_block().contains(self.into_sigset()) { + if pcb + .sig_info_irqsave() + .sig_block() + .contains(self.into_sigset()) + { return true; } return !pcb.sig_struct().handlers[self.clone() as usize - 1].is_ignore(); @@ -430,7 +438,7 @@ pub fn set_current_sig_blocked(new_set: &mut SigSet) { 如果当前pcb的sig_blocked和新的相等,那么就不用改变它。 请注意,一个进程的sig_blocked字段不能被其他进程修改! */ - if pcb.sig_info().sig_block().eq(new_set) { + if pcb.sig_info_irqsave().sig_block().eq(new_set) { return; } diff --git a/kernel/src/libs/printk.c b/kernel/src/libs/printk.c index 2db0c4bc..9d45e3ac 100644 --- a/kernel/src/libs/printk.c +++ b/kernel/src/libs/printk.c @@ -599,7 +599,7 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. io_mfence(); va_list args; va_start(args, fmt); - char buf[4096]; // vsprintf()的缓冲区 + static char buf[4096]; // vsprintf()的缓冲区 int len = vsprintf(buf, fmt, args); va_end(args); diff --git a/kernel/src/libs/rwlock.rs b/kernel/src/libs/rwlock.rs index ac1bfbf1..1bdfdb42 100644 --- a/kernel/src/libs/rwlock.rs +++ b/kernel/src/libs/rwlock.rs @@ -218,6 +218,23 @@ impl RwLock { return r; } //当架构为arm时,有些代码需要作出调整compare_exchange=>compare_exchange_weak + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] + #[allow(dead_code)] + #[inline] + pub fn try_write_irqsave(&self) -> Option> { + ProcessManager::preempt_disable(); + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + let r = self.inner_try_write().map(|mut g| { + g.irq_guard = Some(irq_guard); + g + }); + if r.is_none() { + ProcessManager::preempt_enable(); + } + + return r; + } + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] #[allow(dead_code)] fn inner_try_write(&self) -> Option> { diff --git a/kernel/src/net/event_poll/mod.rs b/kernel/src/net/event_poll/mod.rs index a7bc88fc..6c37c09b 100644 --- a/kernel/src/net/event_poll/mod.rs +++ b/kernel/src/net/event_poll/mod.rs @@ -52,6 +52,8 @@ pub struct EventPoll { impl EventPoll { pub const EP_MAX_EVENTS: u32 = INT32_MAX / (core::mem::size_of::() as u32); + /// 用于获取inode中的epitem队列 + pub const ADD_EPOLLITEM: u32 = 0x7965; pub fn new() -> Self { Self { epoll_wq: WaitQueue::INIT, @@ -462,7 +464,7 @@ impl EventPoll { } // 如果有未处理的信号则返回错误 - if current_pcb.sig_info().sig_pending().signal().bits() != 0 { + if current_pcb.sig_info_irqsave().sig_pending().signal().bits() != 0 { return Err(SystemError::EINTR); } diff --git a/kernel/src/process/fork.rs b/kernel/src/process/fork.rs index 133c3e05..6caad3e7 100644 --- a/kernel/src/process/fork.rs +++ b/kernel/src/process/fork.rs @@ -363,12 +363,12 @@ impl ProcessManager { // 设置clear_child_tid,在线程结束时将其置0以通知父进程 if clone_flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) { - pcb.thread.write().clear_child_tid = Some(clone_args.child_tid); + pcb.thread.write_irqsave().clear_child_tid = Some(clone_args.child_tid); } // 设置child_tid,意味着子线程能够知道自己的id if clone_flags.contains(CloneFlags::CLONE_CHILD_SETTID) { - pcb.thread.write().set_child_tid = Some(clone_args.child_tid); + pcb.thread.write_irqsave().set_child_tid = Some(clone_args.child_tid); } // 将子进程/线程的id存储在用户态传进的地址中 @@ -424,13 +424,14 @@ impl ProcessManager { // 设置线程组id、组长 if clone_flags.contains(CloneFlags::CLONE_THREAD) { - pcb.thread.write().group_leader = current_pcb.thread.read().group_leader.clone(); + pcb.thread.write_irqsave().group_leader = + current_pcb.thread.read_irqsave().group_leader.clone(); unsafe { let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock; (*ptr).tgid = current_pcb.tgid; } } else { - pcb.thread.write().group_leader = Arc::downgrade(&pcb); + pcb.thread.write_irqsave().group_leader = Arc::downgrade(&pcb); unsafe { let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock; (*ptr).tgid = pcb.tgid; @@ -439,12 +440,13 @@ impl ProcessManager { // CLONE_PARENT re-uses the old parent if clone_flags.contains(CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD) { - *pcb.real_parent_pcb.write() = current_pcb.real_parent_pcb.read().clone(); + *pcb.real_parent_pcb.write_irqsave() = + current_pcb.real_parent_pcb.read_irqsave().clone(); if clone_flags.contains(CloneFlags::CLONE_THREAD) { pcb.exit_signal.store(Signal::INVALID, Ordering::SeqCst); } else { - let leader = current_pcb.thread.read().group_leader(); + let leader = current_pcb.thread.read_irqsave().group_leader(); if unlikely(leader.is_none()) { panic!( "fork: Failed to get leader of current process, current pid: [{:?}]", @@ -459,7 +461,7 @@ impl ProcessManager { } } else { // 新创建的进程,设置其父进程为当前进程 - *pcb.real_parent_pcb.write() = Arc::downgrade(¤t_pcb); + *pcb.real_parent_pcb.write_irqsave() = Arc::downgrade(¤t_pcb); pcb.exit_signal .store(clone_args.exit_signal, Ordering::SeqCst); } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 5a2bedea..8defbf11 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -311,7 +311,7 @@ impl ProcessManager { .adopt_childen() .unwrap_or_else(|e| panic!("adopte_childen failed: error: {e:?}")) }; - let r = current.parent_pcb.read().upgrade(); + let r = current.parent_pcb.read_irqsave().upgrade(); if r.is_none() { return; } @@ -344,7 +344,7 @@ impl ProcessManager { pcb.wait_queue.wakeup(Some(ProcessState::Blocked(true))); // 进行进程退出后的工作 - let thread = pcb.thread.write(); + let thread = pcb.thread.write_irqsave(); if let Some(addr) = thread.set_child_tid { unsafe { clear_user(addr, core::mem::size_of::()).expect("clear tid failed") }; } @@ -668,7 +668,7 @@ impl ProcessControlBlock { // 将当前pcb加入父进程的子进程哈希表中 if pcb.pid() > Pid(1) { - if let Some(ppcb_arc) = pcb.parent_pcb.read().upgrade() { + if let Some(ppcb_arc) = pcb.parent_pcb.read_irqsave().upgrade() { let mut children = ppcb_arc.children.write_irqsave(); children.push(pcb.pid()); } else { @@ -718,7 +718,7 @@ impl ProcessControlBlock { /// 否则会导致死锁 #[inline(always)] pub fn basic(&self) -> RwLockReadGuard { - return self.basic.read(); + return self.basic.read_irqsave(); } #[inline(always)] @@ -841,17 +841,13 @@ impl ProcessControlBlock { return name; } - pub fn sig_info(&self) -> RwLockReadGuard { - self.sig_info.read() - } - pub fn sig_info_irqsave(&self) -> RwLockReadGuard { self.sig_info.read_irqsave() } - pub fn try_siginfo(&self, times: u8) -> Option> { + pub fn try_siginfo_irqsave(&self, times: u8) -> Option> { for _ in 0..times { - if let Some(r) = self.sig_info.try_read() { + if let Some(r) = self.sig_info.try_read_irqsave() { return Some(r); } } @@ -865,7 +861,7 @@ impl ProcessControlBlock { pub fn try_siginfo_mut(&self, times: u8) -> Option> { for _ in 0..times { - if let Some(r) = self.sig_info.try_write() { + if let Some(r) = self.sig_info.try_write_irqsave() { return Some(r); } } @@ -874,10 +870,10 @@ impl ProcessControlBlock { } pub fn sig_struct(&self) -> SpinLockGuard { - self.sig_struct.lock() + self.sig_struct.lock_irqsave() } - pub fn try_sig_struct_irq(&self, times: u8) -> Option> { + pub fn try_sig_struct_irqsave(&self, times: u8) -> Option> { for _ in 0..times { if let Ok(r) = self.sig_struct.try_lock_irqsave() { return Some(r); @@ -894,13 +890,19 @@ impl ProcessControlBlock { impl Drop for ProcessControlBlock { fn drop(&mut self) { + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + // kdebug!("drop: {:?}", self.pid); // 在ProcFS中,解除进程的注册 procfs_unregister_pid(self.pid()) .unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}")); - if let Some(ppcb) = self.parent_pcb.read().upgrade() { - ppcb.children.write().retain(|pid| *pid != self.pid()); + if let Some(ppcb) = self.parent_pcb.read_irqsave().upgrade() { + ppcb.children + .write_irqsave() + .retain(|pid| *pid != self.pid()); } + + drop(irq_guard); } } diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index ba7c20b3..4ad8d745 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -202,11 +202,11 @@ impl Syscall { }); if flags.contains(CloneFlags::CLONE_VFORK) { - pcb.thread.write().vfork_done = Some(vfork.clone()); + pcb.thread.write_irqsave().vfork_done = Some(vfork.clone()); } - if pcb.thread.read().set_child_tid.is_some() { - let addr = pcb.thread.read().set_child_tid.unwrap(); + if pcb.thread.read_irqsave().set_child_tid.is_some() { + let addr = pcb.thread.read_irqsave().set_child_tid.unwrap(); let mut writer = UserBufferWriter::new(addr.as_ptr::(), core::mem::size_of::(), true)?; writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?; @@ -234,7 +234,7 @@ impl Syscall { .map_err(|_| SystemError::EFAULT)?; let pcb = ProcessManager::current_pcb(); - pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr)); + pcb.thread.write_irqsave().clear_child_tid = Some(VirtAddr::new(ptr)); Ok(pcb.pid.0) }