From 96675e61cd22ee08503f80c76533fd5db83f26aa Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Tue, 13 Feb 2024 00:16:49 +0100 Subject: [PATCH] Kernel/TTY: Support non-blocking reads with termios VMIN == 0 In a TTY's non-canonical mode, data availability can be configured by setting VMIN and VTIME to determine the minimum amount of bytes to read and the timeout between bytes, respectively. Some ports (such as SRB2) set VMIN to 0 which effectively makes reading a TTY such as stdin a non-blocking read. We didn't support this, causing ports to hang as soon as they try to read stdin without any data available. Add a very duct-tapey implementation for the case where VMIN == 0 by overwriting the TTY's description's blocking status; 3 FIXMEs are included to make sure we clean this up some day. --- Kernel/Devices/TTY/TTY.cpp | 11 ++++++++--- Kernel/Devices/TTY/TTY.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Kernel/Devices/TTY/TTY.cpp b/Kernel/Devices/TTY/TTY.cpp index b0e1cf9dc5..cc53748148 100644 --- a/Kernel/Devices/TTY/TTY.cpp +++ b/Kernel/Devices/TTY/TTY.cpp @@ -373,7 +373,7 @@ void TTY::flush_input() evaluate_block_conditions(); } -ErrorOr TTY::set_termios(termios const& t) +ErrorOr TTY::set_termios(OpenFileDescription& description, termios const& t) { ErrorOr rc; m_termios = t; @@ -463,10 +463,15 @@ ErrorOr TTY::set_termios(termios const& t) } } + // FIXME: decouple VMIN/VTIME support from the description's blocking status + // FIXME: support VMIN > 1 where we should block until VMIN characters are available + // FIXME: implement support for VTIME as an interbyte timeout + description.set_blocking(in_canonical_mode() || m_termios.c_cc[VMIN] > 0); + return rc; } -ErrorOr TTY::ioctl(OpenFileDescription&, unsigned request, Userspace arg) +ErrorOr TTY::ioctl(OpenFileDescription& description, unsigned request, Userspace arg) { auto& current_process = Process::current(); TRY(current_process.require_promise(Pledge::tty)); @@ -520,7 +525,7 @@ ErrorOr TTY::ioctl(OpenFileDescription&, unsigned request, Userspace(arg); auto termios = TRY(copy_typed_from_user(user_termios)); - auto rc = set_termios(termios); + auto rc = set_termios(description, termios); if (request == TCSETSF) flush_input(); return rc; diff --git a/Kernel/Devices/TTY/TTY.h b/Kernel/Devices/TTY/TTY.h index c6e004b000..57c54d77d4 100644 --- a/Kernel/Devices/TTY/TTY.h +++ b/Kernel/Devices/TTY/TTY.h @@ -37,7 +37,6 @@ public: return 0; } - ErrorOr set_termios(termios const&); bool should_generate_signals() const { return (m_termios.c_lflag & ISIG) == ISIG; } bool should_flush_on_signal() const { return (m_termios.c_lflag & NOFLSH) != NOFLSH; } bool should_echo_input() const { return (m_termios.c_lflag & ECHO) == ECHO; } @@ -78,6 +77,7 @@ private: virtual bool is_tty() const final override { return true; } virtual void echo(u8) = 0; + ErrorOr set_termios(OpenFileDescription&, termios const&); template void process_output(u8, Functor put_char);