Browse Source

fix terminal subsystem, print syscall debug info conditionally

greatbridf 4 months ago
parent
commit
c6d416043e

+ 4 - 0
Cargo.toml

@@ -13,6 +13,10 @@ itertools = { version = "0.13.0", default-features = false }
 lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
 spin = "0.9.8"
 
+[features]
+default = []
+debug_syscall = []
+
 [build-dependencies]
 bindgen = "0.70.1"
 

+ 0 - 10
src/driver/serial.rs

@@ -121,16 +121,6 @@ impl TerminalDevice for Serial {
         loop {
             // If we poll the status and get the corresponding bit, we should handle the action.
             let status = self.line_status.read();
-
-            // We should receive a byte and commit that to the line.
-            if status & 0x01 != 0 {
-                let ch = self.tx_rx.read();
-
-                if let Some(terminal) = self.terminal.as_ref() {
-                    terminal.commit_char(ch);
-                }
-            }
-
             if status & 0x20 != 0 {
                 self.tx_rx.write(ch);
                 return;

+ 17 - 13
src/kernel/syscall.rs

@@ -114,22 +114,26 @@ macro_rules! syscall32_call {
                 MapArgumentImpl::map_arg(arg_register!(${index()}, $is));
         )*
 
-        println_info!(
-            "tid{}: {}({}) => {{",
-            Thread::current().tid,
-            stringify!($handler),
-            format_expand!($($arg, $arg),*),
-        );
+        if cfg!(feature = "debug_syscall") {
+            println_info!(
+                "tid{}: {}({}) => {{",
+                Thread::current().tid,
+                stringify!($handler),
+                format_expand!($($arg, $arg),*),
+            );
+        }
 
         let result = $handler($($arg),*);
 
-        println_info!(
-            "tid{}: {}({}) => }} = {:x?}",
-            Thread::current().tid,
-            stringify!($handler),
-            format_expand!($($arg, $arg),*),
-            result
-        );
+        if cfg!(feature = "debug_syscall") {
+            println_info!(
+                "tid{}: {}({}) => }} = {:x?}",
+                Thread::current().tid,
+                stringify!($handler),
+                format_expand!($($arg, $arg),*),
+                result
+            );
+        }
 
         match result {
             Ok(val) => MapReturnValue::map_ret(val),

+ 5 - 4
src/kernel/syscall/file_rw.rs

@@ -328,14 +328,15 @@ struct UserPollFd {
     revents: u16,
 }
 
-fn do_poll(fds: *mut UserPollFd, nfds: u32, timeout: u32) -> KResult<u32> {
+fn do_poll(fds: *mut UserPollFd, nfds: u32, _timeout: u32) -> KResult<u32> {
     match nfds {
         0 => Ok(0),
         2.. => unimplemented!("Poll with {} fds", nfds),
         1 => {
-            if timeout != u32::MAX {
-                unimplemented!("Poll with timeout {}", timeout);
-            }
+            // TODO!!: Poll with timeout
+            // if timeout != u32::MAX {
+            //     unimplemented!("Poll with timeout {}", timeout);
+            // }
             let fds = UserPointerMut::new(fds)?;
             let mut fd = fds.read()?;
 

+ 0 - 1
src/kernel/task/scheduler.rs

@@ -166,7 +166,6 @@ impl Scheduler {
     }
 
     pub fn schedule_noreturn() -> ! {
-        println_debug!("Scheduler::schedule_noreturn()");
         preempt::disable();
         Self::schedule();
         panic!("Scheduler::schedule_noreturn(): Should never return")

+ 55 - 51
src/kernel/terminal.rs

@@ -1,5 +1,3 @@
-use core::iter::repeat;
-
 use alloc::{
     collections::vec_deque::VecDeque,
     sync::{Arc, Weak},
@@ -42,6 +40,7 @@ const VEOL2: usize = 16;
 /* c_iflag bits */
 
 bitflags! {
+    #[derive(Debug)]
     pub struct TermioIFlags: u16 {
         /// Ignore break condition
         const IGNBRK = 0x0001;
@@ -70,6 +69,7 @@ bitflags! {
         const IUTF8 = 0x4000;
     }
 
+    #[derive(Debug)]
     pub struct TermioOFlags: u16 {
         /// Perform output processing
         const OPOST = 0x0001;
@@ -84,6 +84,7 @@ bitflags! {
 }
 
 bitflags! {
+    #[derive(Debug)]
     pub struct TermioLFlags: u16 {
         const ISIG = 0x0001;
         const ICANON = 0x0002;
@@ -113,6 +114,7 @@ const HUPCL: u32 = 0x00000400;
 
 const N_TTY: u8 = 0;
 
+#[derive(Debug)]
 pub struct Termios {
     iflag: TermioIFlags,
     oflag: TermioOFlags,
@@ -323,10 +325,10 @@ impl Termios {
 
     fn get_user(&self) -> UserTermios {
         UserTermios {
-            iflag: self.iflag.bits() as u16,
-            oflag: self.oflag.bits() as u16,
-            cflag: self.cflag as u16,
-            lflag: self.lflag.bits() as u16,
+            iflag: self.iflag.bits() as u32,
+            oflag: self.oflag.bits() as u32,
+            cflag: self.cflag,
+            lflag: self.lflag.bits() as u32,
             line: self.line,
             cc: self.cc,
         }
@@ -362,10 +364,10 @@ pub struct UserWindowSize {
 #[repr(C)]
 #[derive(Debug, Clone, Copy)]
 pub struct UserTermios {
-    iflag: u16,
-    oflag: u16,
-    cflag: u16,
-    lflag: u16,
+    iflag: u32,
+    oflag: u32,
+    cflag: u32,
+    lflag: u32,
     line: u8,
     cc: [u8; NCCS],
 }
@@ -390,7 +392,7 @@ impl Terminal {
             inner: Spin::new(TerminalInner {
                 termio: Termios::new_standard(),
                 session: Weak::new(),
-                buffer: repeat(0).take(BUFFER_SIZE).collect(),
+                buffer: VecDeque::with_capacity(BUFFER_SIZE),
             }),
             cv: CondVar::new(),
             device,
@@ -463,9 +465,9 @@ impl Terminal {
             self.echo_char(inner, ch);
         }
 
-        // If ICANON is set, we notify all waiting processes.
-        // If ICANON is not set but we have a new line, there are data ready, we notify as well.
-        if ch == b'\n' || inner.termio.icanon() {
+        // If ICANON is not set, we notify all waiting processes.
+        // If ICANON is set but we have a new line, there are data ready, we notify as well.
+        if ch == b'\n' || !inner.termio.icanon() {
             self.cv.notify_all();
         }
     }
@@ -532,9 +534,11 @@ impl Terminal {
     }
 
     pub fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
-        'block: {
+        let mut tmp_buffer = [0u8; 32];
+
+        let data = 'block: {
             if buffer.available() == 0 {
-                break 'block;
+                break 'block &tmp_buffer[..0];
             }
 
             let mut inner = self.inner.lock_irq();
@@ -547,38 +551,37 @@ impl Terminal {
             }
 
             if inner.buffer.is_empty() {
-                break 'block;
+                break 'block &tmp_buffer[..0];
             }
 
-            if !inner.termio.icanon() {
-                let ch = inner.buffer.pop_front().unwrap();
-                buffer.fill(&[ch])?.allow_partial();
-                break 'block;
+            let length = if inner.termio.icanon() {
+                // Canonical mode, return data until we see a newline.
+                // TODO!!: We should wait if we don't see one.
+                inner
+                    .buffer
+                    .iter()
+                    .position(|&ch| ch == b'\n')
+                    .map(|pos| pos + 1)
+                    .unwrap_or(inner.buffer.len())
+            } else {
+                buffer.available().min(inner.buffer.len())
+            };
+
+            // TODO!!!!!!: Change this. We need to loop until we've got enough data.
+            let length = length.min(tmp_buffer.len());
+
+            for (ch, r) in inner
+                .buffer
+                .drain(..length)
+                .zip(tmp_buffer.iter_mut().take(length))
+            {
+                *r = ch;
             }
 
-            // Canonical mode, return data until we see a newline.
-            let length = inner
-                .buffer
-                .iter()
-                .position(|&ch| ch == b'\n')
-                .map(|pos| pos + 1)
-                .unwrap_or(inner.buffer.len());
-
-            let (first, second) = inner.buffer.as_slices();
-            let first_data = first
-                .split_at_checked(length)
-                .map_or(first, |(data, _)| data);
-            let second_data = second
-                .split_at_checked(length - first_data.len())
-                .map_or(second, |(data, _)| data);
-
-            buffer.fill(first_data)?.allow_partial();
-            buffer.fill(second_data)?.allow_partial();
-
-            inner.buffer.drain(..buffer.wrote());
-        }
+            &tmp_buffer[..length]
+        };
 
-        Ok(buffer.wrote())
+        buffer.fill(data).map(|result| result.allow_partial())
     }
 
     pub fn ioctl(&self, request: TerminalIORequest) -> KResult<()> {
@@ -595,9 +598,10 @@ impl Terminal {
                 }
             }
             TerminalIORequest::SetProcessGroup(pgid) => {
+                let pgid = pgid.read()?;
+
                 let inner = self.inner.lock();
                 let session = inner.session.upgrade();
-                let pgid = pgid.read()?;
 
                 if let Some(session) = session {
                     session.set_foreground_pgid(pgid)
@@ -617,18 +621,18 @@ impl Terminal {
                 ptr.write(window_size)
             }
             TerminalIORequest::GetTermios(ptr) => {
-                let inner = self.inner.lock();
-                ptr.write(inner.termio.get_user())
+                let termios = self.inner.lock().termio.get_user();
+                ptr.write(termios)
             }
             TerminalIORequest::SetTermios(ptr) => {
-                let mut inner = self.inner.lock();
                 let user_termios = ptr.read()?;
+                let mut inner = self.inner.lock();
 
                 // TODO: We ignore unknown bits for now.
-                inner.termio.iflag = TermioIFlags::from_bits_truncate(user_termios.iflag);
-                inner.termio.oflag = TermioOFlags::from_bits_truncate(user_termios.oflag);
-                inner.termio.lflag = TermioLFlags::from_bits_truncate(user_termios.lflag);
-                inner.termio.cflag = user_termios.cflag as u32;
+                inner.termio.iflag = TermioIFlags::from_bits_truncate(user_termios.iflag as u16);
+                inner.termio.oflag = TermioOFlags::from_bits_truncate(user_termios.oflag as u16);
+                inner.termio.lflag = TermioLFlags::from_bits_truncate(user_termios.lflag as u16);
+                inner.termio.cflag = user_termios.cflag;
                 inner.termio.line = user_termios.line;
                 inner.termio.cc = user_termios.cc;
 

+ 1 - 0
src/kernel/user/dataflow.rs

@@ -44,6 +44,7 @@ impl<'a, T: Copy, const CONST: bool> UserPointer<'a, T, CONST> {
         Self::new(vaddr as *mut T)
     }
 
+    /// # Might Sleep
     pub fn read(&self) -> KResult<T> {
         let mut value = core::mem::MaybeUninit::<T>::uninit();
         self.pointer

+ 2 - 2
src/kernel/vfs/file.rs

@@ -41,7 +41,7 @@ pub struct PipeInner {
 }
 
 pub struct Pipe {
-    inner: Spin<PipeInner>,
+    inner: Mutex<PipeInner>,
     cv_read: CondVar,
     cv_write: CondVar,
 }
@@ -100,7 +100,7 @@ impl Pipe {
 
     pub fn new() -> Arc<Self> {
         Arc::new(Self {
-            inner: Spin::new(PipeInner {
+            inner: Mutex::new(PipeInner {
                 buffer: VecDeque::with_capacity(Self::PIPE_SIZE),
                 read_closed: false,
                 write_closed: false,

+ 2 - 3
src/kernel/vfs/filearray.rs

@@ -240,7 +240,8 @@ impl FileArray {
         }
     }
 
-    pub fn open_console(&self) -> KResult<()> {
+    /// Only used for init process.
+    pub fn open_console(&self) {
         let mut inner = self.inner.lock();
         let (stdin, stdout, stderr) = (inner.next_fd(), inner.next_fd(), inner.next_fd());
 
@@ -259,8 +260,6 @@ impl FileArray {
             O_CLOEXEC as u64,
             TerminalFile::new(CONSOLE.lock_irq().get_terminal().unwrap()),
         );
-
-        Ok(())
     }
 }