[newlib-cygwin/cygwin-3_6-branch] Cygwin: console: Improve the performance of peek_console
Takashi Yano
tyan0@sourceware.org
Mon Sep 28 13:00:49 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=c5c907edd90e47c9afb61f553a41a3733a71b75e
commit c5c907edd90e47c9afb61f553a41a3733a71b75e
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date: Fri Sep 4 08:40:45 2026 +0900
Cygwin: console: Improve the performance of peek_console
Previously, peek_console() used PeekConsoleInput() to confirm whether
the console input buffer has some input records. However, this need
attaching to the console if the process does not attach to the console.
To reduce that overhead, this patch uses WaitForSingleObject() with
console input handle instead. WaitForSingleObject() works without
attaching to the console, so this simplifies the peek_console()
code.
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Co-authored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
(cherry picked from commit 15420f9d0023c29dc0baef37b1dfc5384307f54a)
Diff:
---
winsup/cygwin/fhandler/console.cc | 27 ++++++++++++++++++++++++++-
winsup/cygwin/local_includes/fhandler.h | 3 ++-
winsup/cygwin/select.cc | 33 ++++++++++++++++++++++-----------
3 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index 0e462ebc4..b5cd992d9 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -1353,6 +1353,7 @@ wait_retry:
if (res)
goto wait_retry;
}
+ __seterrno ();
goto err;
}
@@ -1365,6 +1366,7 @@ wait_retry:
{
case input_error:
release_input_mutex ();
+ /* errno is already set in process_input_message() */
goto err;
case input_processing:
release_input_mutex ();
@@ -1379,9 +1381,28 @@ wait_retry:
if (global_sigs[get_ttyp ()->last_sig].sa_flags & SA_RESTART)
continue;
goto sig_exit;
+ case input_empty:
+ /* Reaches here when the input buffer is empty even though
+ the input handle is signalled. */
+ release_input_mutex ();
+ if (is_nonblocking ())
+ {
+ if (copied_chars)
+ {
+ fix_input_mode_if_necessary (); /* for win32_input_mode */
+ buflen = copied_chars;
+ return;
+ }
+ set_sig_errno (EAGAIN);
+ buflen = (size_t) -1;
+ return;
+ }
+ cygwait (40);
+ continue;
default:
/* Should not come here */
release_input_mutex ();
+ __seterrno ();
goto err;
}
}
@@ -1409,7 +1430,6 @@ wait_retry:
return;
err:
- __seterrno ();
buflen = (size_t) -1;
return;
@@ -1436,10 +1456,12 @@ fhandler_console::process_input_message (size_t len)
DWORD resume_pid = attach_console (con.owner);
BOOL r =
PeekConsoleInputW (get_handle (), input_rec, INREC_SIZE, &total_read);
+ DWORD error = GetLastError ();
detach_console (resume_pid, con.owner);
release_attach_mutex ();
if (!r)
{
+ __seterrno_from_win_error (error);
termios_printf ("PeekConsoleInput failed, %E");
return input_error;
}
@@ -1451,6 +1473,9 @@ fhandler_console::process_input_message (size_t len)
if (::input_ready && (len == 0 || (get_ttyp ()->ti.c_lflag & ICANON)))
return input_ok;
+ if (total_read == 0)
+ return input_empty;
+
for (i = 0; i < total_read; i ++)
{
DWORD nread = 1;
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index 465ca2dc3..3be174675 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -2192,7 +2192,8 @@ public:
input_processing = 0,
input_ok = 1,
input_signalled = 2,
- input_winch = 3
+ input_winch = 3,
+ input_empty = 4,
};
typedef cons_handle_set_t handle_set_t;
HANDLE thread_sync_event;
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index e0bd1726f..7c14800fd 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1149,8 +1149,6 @@ peek_console (select_record *me, bool)
return 1;
}
- INPUT_RECORD irec;
- DWORD events_read;
HANDLE h;
set_handle_or_return_if_not_open (h, me);
@@ -1161,29 +1159,42 @@ peek_console (select_record *me, bool)
else
{
fh->acquire_input_mutex (mutex_timeout);
- acquire_attach_mutex (mutex_timeout);
- DWORD resume_pid = fh->attach_console (fh->get_owner ());
- BOOL r = PeekConsoleInputW (h, &irec, 1, &events_read);
- fh->detach_console (resume_pid, fh->get_owner ());
- release_attach_mutex ();
- if (!r || !events_read)
+ if (WaitForSingleObject (h, 0) != WAIT_OBJECT_0)
{
fh->release_input_mutex ();
break;
}
}
fhandler_console::input_states ret = fh->process_input_message (0);
+ if (ret == fhandler_console::input_error)
+ me->thread_errno = get_errno ();
fh->release_input_mutex ();
fh->fix_input_mode_if_necessary (); /* for win32_input_mode */
- if (ret == fhandler_console::input_winch
- && global_sigs[SIGWINCH].sa_handler != SIG_IGN
- && global_sigs[SIGWINCH].sa_handler != SIG_DFL)
+ switch (ret)
{
+ case fhandler_console::input_processing:
+ case fhandler_console::input_ok:
+ break;
+ case fhandler_console::input_winch:
+ if (global_sigs[SIGWINCH].sa_handler != SIG_IGN
+ && global_sigs[SIGWINCH].sa_handler != SIG_DFL)
+ {
+ set_sig_errno (EINTR);
+ return -1;
+ }
+ break;
+ case fhandler_console::input_signalled:
set_sig_errno (EINTR);
return -1;
+ case fhandler_console::input_error:
+ /* thread_errno is already set */
+ return -1;
+ case fhandler_console::input_empty:
+ goto out;
}
}
+out:
if (fh->input_ready () || fh->get_cons_readahead_valid ())
return me->read_ready = true;
More information about the Cygwin-cvs
mailing list