public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Ken Brown <kbrown@cornell.edu>
To: cygwin-patches@cygwin.com
Subject: [PATCH 8/8] Cygwin: FIFO: add a third pass to raw_read
Date: Tue,  4 Aug 2020 08:55:07 -0400	[thread overview]
Message-ID: <20200804125507.8842-9-kbrown@cornell.edu> (raw)
In-Reply-To: <20200804125507.8842-1-kbrown@cornell.edu>

Currently raw_read makes two passes through the list of clients.  On
the first pass it tries to read from the client from which it last
read successfully.  On the second pass it tries to read from all
connected clients.

Add a new pass in between these two, in which raw_read tries to read
from all clients that are in the fc_input_avail case.  This should be
more efficient in case select was previously called and detected input
available.

Slightly tweak the first pass.  If a client is marked as having the
last successful read but reading from it now finds no input, don't
unmark it unless we successfully read from a different client on one
of the later passes.
---
 winsup/cygwin/fhandler_fifo.cc | 66 ++++++++++++++++++++++++++++++----
 1 file changed, 60 insertions(+), 6 deletions(-)

diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 017d44e54..a33c32b73 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -1318,17 +1318,30 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
       if (take_ownership (10) < 0)
 	goto maybe_retry;
 
-      /* Poll the connected clients for input.  Make two passes.  On
-	 the first pass, just try to read from the client from which
-	 we last read successfully.  This should minimize
-	 interleaving of writes from different clients. */
       fifo_client_lock ();
+      /* Poll the connected clients for input.  Make three passes.
+
+	 On the first pass, just try to read from the client from
+	 which we last read successfully.  This should minimize
+	 interleaving of writes from different clients.
+
+	 On the second pass, just try to read from the clients in the
+	 state fc_input_avail.  This should be more efficient if
+	 select has been called and detected input available.
+
+	 On the third pass, try to read from all connected clients. */
+
       /* First pass. */
       int j;
       for (j = 0; j < nhandlers; j++)
 	if (fc_handler[j].last_read)
 	  break;
-      if (j < nhandlers && fc_handler[j].get_state () >= fc_connected)
+      if (j < nhandlers && fc_handler[j].get_state () < fc_connected)
+	{
+	  fc_handler[j].last_read = false;
+	  j = nhandlers;
+	}
+      if (j < nhandlers)
 	{
 	  NTSTATUS status;
 	  IO_STATUS_BLOCK io;
@@ -1349,6 +1362,8 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
 		}
 	      break;
 	    case STATUS_PIPE_EMPTY:
+	      /* Update state in case it's fc_input_avail. */
+	      fc_handler[j].set_state (fc_connected);
 	      break;
 	    case STATUS_PIPE_BROKEN:
 	      fc_handler[j].set_state (fc_disconnected);
@@ -1358,10 +1373,47 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
 	      fc_handler[j].set_state (fc_error);
 	      break;
 	    }
-	  fc_handler[j].last_read = false;
 	}
 
       /* Second pass. */
+      for (int i = 0; i < nhandlers; i++)
+	if (fc_handler[i].get_state () == fc_input_avail)
+	  {
+	    NTSTATUS status;
+	    IO_STATUS_BLOCK io;
+
+	    status = NtReadFile (fc_handler[i].h, NULL, NULL, NULL,
+				 &io, in_ptr, len, NULL, NULL);
+	    switch (status)
+	      {
+	      case STATUS_SUCCESS:
+	      case STATUS_BUFFER_OVERFLOW:
+		if (io.Information > 0)
+		  {
+		    len = io.Information;
+		    if (j < nhandlers)
+		      fc_handler[j].last_read = false;
+		    fc_handler[i].last_read = true;
+		    fifo_client_unlock ();
+		    reading_unlock ();
+		    return;
+		  }
+		break;
+	      case STATUS_PIPE_EMPTY:
+		/* No input available after all. */
+		fc_handler[i].set_state (fc_connected);
+		break;
+	      case STATUS_PIPE_BROKEN:
+		fc_handler[i].set_state (fc_disconnected);
+		break;
+	      default:
+		debug_printf ("NtReadFile status %y", status);
+		fc_handler[i].set_state (fc_error);
+		break;
+	      }
+	  }
+
+      /* Third pass. */
       for (int i = 0; i < nhandlers; i++)
 	if (fc_handler[i].get_state () >= fc_connected)
 	  {
@@ -1378,6 +1430,8 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
 		if (io.Information > 0)
 		  {
 		    len = io.Information;
+		    if (j < nhandlers)
+		      fc_handler[j].last_read = false;
 		    fc_handler[i].last_read = true;
 		    fifo_client_unlock ();
 		    reading_unlock ();
-- 
2.28.0


  parent reply	other threads:[~2020-08-04 12:55 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-04 12:54 [PATCH 0/8] FIFO: bug fixes and small improvements Ken Brown
2020-08-04 12:55 ` [PATCH 1/8] Cygwin: FIFO: lock fixes Ken Brown
2020-08-04 12:55 ` [PATCH 2/8] Cygwin: FIFO: fix timing issue with owner change Ken Brown
2020-08-04 12:55 ` [PATCH 3/8] Cygwin: FIFO: add a timeout to take_ownership Ken Brown
2020-08-04 12:55 ` [PATCH 4/8] Cygwin: FIFO: reorganize some fifo_client_handler methods Ken Brown
2020-08-04 12:55 ` [PATCH 5/8] Cygwin: FIFO: don't read from pipes that are closing Ken Brown
2020-08-04 12:55 ` [PATCH 6/8] Cygwin: FIFO: synchronize the fifo_reader and fifosel threads Ken Brown
2020-08-04 12:55 ` [PATCH 7/8] Cygwin: FIFO: fix indentation Ken Brown
2020-08-04 12:55 ` Ken Brown [this message]
2020-08-04 15:04 ` [PATCH 0/8] FIFO: bug fixes and small improvements Corinna Vinschen

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=20200804125507.8842-9-kbrown@cornell.edu \
    --to=kbrown@cornell.edu \
    --cc=cygwin-patches@cygwin.com \
    /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).