public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
From: Corinna Vinschen <corinna@sourceware.org>
To: cygwin-cvs@sourceware.org
Subject: [newlib-cygwin] Cygwin: serial: read: if VMIN > 0, wait for VMIN chars in inbound queue
Date: Thu, 26 Mar 2020 11:26:56 +0000 (GMT)	[thread overview]
Message-ID: <20200326112656.DD2A7385E01A@sourceware.org> (raw)

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=082f2513c721e942d0fd563c4dc9117eee3513ab

commit 082f2513c721e942d0fd563c4dc9117eee3513ab
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Mar 25 12:21:59 2020 +0100

    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>

Diff:
---
 winsup/cygwin/fhandler_serial.cc | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc
index b6d1e4f4c..1750a9f97 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:


                 reply	other threads:[~2020-03-26 11:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200326112656.DD2A7385E01A@sourceware.org \
    --to=corinna@sourceware.org \
    --cc=cygwin-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).