diff options
author | Takashi Yano <takashi.yano@nifty.ne.jp> | 2025-04-09 14:57:54 +0900 |
---|---|---|
committer | Takashi Yano <takashi.yano@nifty.ne.jp> | 2025-04-09 15:11:00 +0900 |
commit | d35cc82b5ec15bb8a5fe0fe11e183d1887992e99 (patch) | |
tree | d1a90d7003a5eef4b837e45f8e36035dbd55bf2d /winsup/cygwin | |
parent | d29943e56dc5e30e219b7da114b0b0c31acd8cbc (diff) | |
download | newlib-main.zip newlib-main.tar.gz newlib-main.tar.bz2 |
Cygwin: termios: Implement tcflow(), tcdrain(), TCXONC, TIOCINQHEADgithub/mastergithub/mainmastermain
Previously, tcflow() and tcdrain() were missing from console and pty.
ioctl() command: TCXONC, TIOCINQ, and TCFLSH were also missing.
Due to this, "stress-ng --pty 1" failed. This patch implements them.
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/fhandler/console.cc | 30 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/pty.cc | 30 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/termios.cc | 31 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/termios.h | 1 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/fhandler.h | 7 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/tty.h | 6 |
6 files changed, 95 insertions, 10 deletions
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index a38487f..c613643 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -509,7 +509,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) case not_signalled_but_done: case done_with_debugger: processed = true; - ttyp->output_stopped = false; + ttyp->output_stopped &= ~BY_VSTOP; if (ti.c_lflag & NOFLSH) goto remove_record; con.num_processed = 0; @@ -1144,6 +1144,15 @@ fhandler_console::read (void *pv, size_t& buflen) push_process_state process_state (PID_TTYIN); + if (get_ttyp ()->input_stopped && is_nonblocking ()) + { + set_errno (EAGAIN); + buflen = (size_t) -1; + return; + } + while (get_ttyp ()->input_stopped) + cygwait (10); + size_t copied_chars = 0; DWORD timeout = is_nonblocking () ? 0 : @@ -2131,6 +2140,7 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) release_output_mutex (); return -1; case FIONREAD: + case TIOCINQ: { DWORD n; int ret = 0; @@ -2183,6 +2193,14 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) return 0; } break; + case TCXONC: + res = this->tcflow ((int)(intptr_t) arg); + release_output_mutex (); + return res; + case TCFLSH: + res = this->tcflush ((int)(intptr_t) arg); + release_output_mutex (); + return res; } release_output_mutex (); @@ -4172,8 +4190,8 @@ fhandler_console::write (const void *vsrc, size_t len) void fhandler_console::doecho (const void *str, DWORD len) { - bool stopped = get_ttyp ()->output_stopped; - get_ttyp ()->output_stopped = false; + int stopped = get_ttyp ()->output_stopped; + get_ttyp ()->output_stopped = 0; write (str, len); get_ttyp ()->output_stopped = stopped; } @@ -4711,3 +4729,9 @@ fhandler_console::cons_mode_on_close () return tty::restore; /* otherwise, restore */ } + +int +fhandler_console::tcdrain () +{ + return 0; +} diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index 3128b92..b882b90 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -1304,6 +1304,15 @@ fhandler_pty_slave::read (void *ptr, size_t& len) push_process_state process_state (PID_TTYIN); + if (get_ttyp ()->input_stopped && is_nonblocking ()) + { + set_errno (EAGAIN); + len = (size_t) -1; + return; + } + while (get_ttyp ()->input_stopped) + cygwait (10); + if (ptr) /* Indicating not tcflush(). */ mask_switch_to_nat_pipe (true, true); @@ -1650,6 +1659,7 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg) retval = this->tcsetpgrp ((pid_t) (intptr_t) arg); goto out; case FIONREAD: + case TIOCINQ: { DWORD n; if (!bytes_available (n)) @@ -1664,6 +1674,12 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg) } } goto out; + case TCXONC: + retval = this->tcflow ((int)(intptr_t) arg); + goto out; + case TCFLSH: + retval = this->tcflush ((int)(intptr_t) arg); + goto out; default: return fhandler_base::ioctl (cmd, arg); } @@ -2342,6 +2358,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) case TIOCSPGRP: return this->tcsetpgrp ((pid_t) (intptr_t) arg); case FIONREAD: + case TIOCINQ: { DWORD n; if (!bytes_available (n)) @@ -2352,6 +2369,10 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) *(int *) arg = (int) n; } break; + case TCXONC: + return this->tcflow ((int)(intptr_t) arg); + case TCFLSH: + return this->tcflush ((int)(intptr_t) arg); default: return fhandler_base::ioctl (cmd, arg); } @@ -4194,3 +4215,12 @@ fhandler_pty_common::resume_from_temporarily_attach (DWORD resume_pid) } release_attach_mutex (); } + +int +fhandler_pty_common::tcdrain () +{ + DWORD n; + while (bytes_available (n) && n > 0) + cygwait (10); + return 0; +} diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc index a3cecdb..19d6220 100644 --- a/winsup/cygwin/fhandler/termios.cc +++ b/winsup/cygwin/fhandler/termios.cc @@ -491,16 +491,16 @@ fhandler_termios::process_stop_start (char c, tty *ttyp) { if (CCEQ (ti.c_cc[VSTOP], c)) { - ttyp->output_stopped = true; + ttyp->output_stopped |= BY_VSTOP; return true; } else if (CCEQ (ti.c_cc[VSTART], c)) { restart_output: - ttyp->output_stopped = false; + ttyp->output_stopped &= ~BY_VSTOP; return true; } - else if ((ti.c_iflag & IXANY) && ttyp->output_stopped) + else if ((ti.c_iflag & IXANY) && (ttyp->output_stopped & BY_VSTOP)) goto restart_output; } if ((ti.c_lflag & ICANON) && (ti.c_lflag & IEXTEN) @@ -540,7 +540,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, fallthrough; case not_signalled_but_done: case done_with_debugger: - get_ttyp ()->output_stopped = false; + get_ttyp ()->output_stopped &= ~BY_VSTOP; continue; case not_signalled_with_nat_reader: disable_eof_key = true; @@ -915,3 +915,26 @@ fhandler_termios::get_console_process_id (DWORD pid, bool match, } return res_pri ?: res; } + +int +fhandler_termios::tcflow (int action) +{ + switch (action) + { + case TCOOFF: + get_ttyp ()->output_stopped |= BY_TCFLOW; + return 0; + case TCOON: + get_ttyp ()->output_stopped = 0; + return 0; + case TCIOFF: + get_ttyp ()->input_stopped |= BY_TCFLOW; + return 0; + case TCION: + get_ttyp ()->input_stopped = 0; + return 0; + default: + set_errno (EINVAL); + return -1; + } +} diff --git a/winsup/cygwin/include/sys/termios.h b/winsup/cygwin/include/sys/termios.h index d1b4a0a..4c03042 100644 --- a/winsup/cygwin/include/sys/termios.h +++ b/winsup/cygwin/include/sys/termios.h @@ -18,6 +18,7 @@ details. */ #define TIOCMBIC 0x5417 #define TIOCMSET 0x5418 #define TIOCINQ 0x541B +#define TCXONC 0x540A #define TIOCSCTTY 0x540E /* TIOCINQ is utilized instead of FIONREAD which has been diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 8c71d84..2177cec 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -1979,6 +1979,7 @@ class fhandler_termios: public fhandler_base virtual off_t lseek (off_t, int); pid_t tcgetsid (); virtual int fstat (struct stat *buf); + int tcflow (int); fhandler_termios (void *) {} @@ -2143,12 +2144,12 @@ class dev_console char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command char *cons_rapoi; bool cursor_key_app_mode; - bool disable_master_thread; + volatile bool disable_master_thread; tty::cons_mode curr_input_mode; tty::cons_mode curr_output_mode; DWORD prev_input_mode; DWORD prev_output_mode; - bool master_thread_suspended; + volatile bool master_thread_suspended; int num_processed; /* Number of input events in the current input buffer already processed by cons_master_thread(). */ @@ -2273,6 +2274,7 @@ private: int tcflush (int); int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); + int tcdrain (); int ioctl (unsigned int cmd, void *); int init (HANDLE, DWORD, mode_t, int64_t = 0); @@ -2391,6 +2393,7 @@ class fhandler_pty_common: public fhandler_termios DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms); void __release_output_mutex (const char *fn, int ln); + int tcdrain (); int close (int flag = -1); off_t lseek (off_t, int); bool bytes_available (DWORD& n); diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h index 2a047d7..a418ab1 100644 --- a/winsup/cygwin/local_includes/tty.h +++ b/winsup/cygwin/local_includes/tty.h @@ -30,6 +30,9 @@ details. */ #define MIN_CTRL_C_SLOP 50 #endif +#define BY_TCFLOW 2 +#define BY_VSTOP 1 + typedef void *HPCON; #include "devices.h" @@ -43,7 +46,8 @@ class tty_min public: pid_t pgid; - bool output_stopped; /* FIXME: Maybe do this with a mutex someday? */ + volatile int output_stopped; /* FIXME: Maybe do this with a mutex someday? */ + volatile int input_stopped; fh_devices ntty; ULONGLONG last_ctrl_c; /* tick count of last ctrl-c */ bool is_console; |