aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2020-03-25 12:21:59 +0100
committerCorinna Vinschen <corinna@vinschen.de>2020-03-25 12:22:26 +0100
commit082f2513c721e942d0fd563c4dc9117eee3513ab (patch)
treed5880196454f365cda946dcb768d7e2e238025da
parent2a4b1de773e6159ea8197b6fc3f7e4845479b476 (diff)
downloadnewlib-082f2513c721e942d0fd563c4dc9117eee3513ab.zip
newlib-082f2513c721e942d0fd563c4dc9117eee3513ab.tar.gz
newlib-082f2513c721e942d0fd563c4dc9117eee3513ab.tar.bz2
Cygwin: serial: read: if VMIN > 0, wait for VMIN chars in inbound queue
Per termios, read waits for MIN chars even if the number of requested bytes is less. This requires to add WaitCommEvent to wait non-busily for MIN chars prior to calling ReadFile, so, reintroduce it. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r--winsup/cygwin/fhandler_serial.cc38
1 files changed, 26 insertions, 12 deletions
diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc
index b6d1e4f..1750a9f 100644
--- a/winsup/cygwin/fhandler_serial.cc
+++ b/winsup/cygwin/fhandler_serial.cc
@@ -34,19 +34,20 @@ void __reg3
fhandler_serial::raw_read (void *ptr, size_t& ulen)
{
OVERLAPPED ov = { 0 };
- DWORD io_err;
+ DWORD io_err, event;
COMSTAT st;
DWORD bytes_to_read, read_bytes;
ssize_t tot = 0;
+ bool wait_for_vmin, ret;
if (ulen > SSIZE_MAX)
ulen = SSIZE_MAX;
if (ulen == 0)
return;
- /* If VMIN > 0 in blocking mode, we have to read at least VMIN chars,
- otherwise we're in polling mode and there's no minimum chars. */
- ssize_t minchars = (!is_nonblocking () && vmin_) ? MIN (vmin_, ulen) : 0;
+ /* If VMIN > 0 in blocking mode, we have to wait for at least VMIN chars.
+ Otherwise we're in polling mode and there's no minimum chars. */
+ ssize_t minchars = is_nonblocking () ? 0 : vmin_;
debug_printf ("ulen %ld, vmin_ %u, vtime_ %u", ulen, vmin_, vtime_);
@@ -54,6 +55,8 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen)
do
{
+ wait_for_vmin = false;
+
/* First check if chars are already in the inbound queue. */
if (!ClearCommError (get_handle (), &io_err, &st))
goto err;
@@ -82,14 +85,22 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen)
and don't wait. */
if (st.cbInQue && st.cbInQue >= minchars)
bytes_to_read = MIN (st.cbInQue, bytes_to_read);
+ /* Otherwise, if VMIN > 0, VTIME == 0, we have to wait until
+ VMIN bytes are available in the inbound queue. */
+ else if (minchars && !vtime_)
+ wait_for_vmin = true;
}
ResetEvent (ov.hEvent);
- if (!ReadFile (get_handle (), ptr, bytes_to_read, &read_bytes, &ov))
+ if (wait_for_vmin)
+ ret = WaitCommEvent (get_handle (), &event, &ov);
+ else
+ ret = ReadFile (get_handle (), ptr, bytes_to_read, &read_bytes, &ov);
+ if (!ret)
{
if (GetLastError () != ERROR_IO_PENDING)
goto err;
- if (is_nonblocking ())
+ if (!wait_for_vmin && is_nonblocking ())
{
CancelIo (get_handle ());
if (!GetOverlappedResult (get_handle (), &ov, &read_bytes,
@@ -134,12 +145,15 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen)
}
}
}
- tot += read_bytes;
- ptr = (void *) ((caddr_t) ptr + read_bytes);
- ulen -= read_bytes;
- minchars -= read_bytes;
- debug_printf ("vtime_ %u, vmin_ %u, read_bytes %u, tot %D",
- vtime_, vmin_, read_bytes, tot);
+ if (!wait_for_vmin)
+ {
+ tot += read_bytes;
+ ptr = (void *) ((caddr_t) ptr + read_bytes);
+ ulen -= read_bytes;
+ minchars -= read_bytes;
+ debug_printf ("vtime_ %u, vmin_ %u, read_bytes %u, tot %D",
+ vtime_, vmin_, read_bytes, tot);
+ }
continue;
err: