From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2210) id DA40F385041D; Tue, 4 Aug 2020 15:29:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA40F385041D Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Ken Brown To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: FIFO: add a third pass to raw_read X-Act-Checkin: newlib-cygwin X-Git-Author: Ken Brown X-Git-Refname: refs/heads/master X-Git-Oldrev: 55b93b27d67f068e435f48ea5442627b32577526 X-Git-Newrev: 4f5b52ffe7e91866fea18072b69c912385397648 Message-Id: <20200804152951.DA40F385041D@sourceware.org> Date: Tue, 4 Aug 2020 15:29:51 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Aug 2020 15:29:52 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=4f5b52ffe7e91866fea18072b69c912385397648 commit 4f5b52ffe7e91866fea18072b69c912385397648 Author: Ken Brown Date: Mon Aug 3 09:44:31 2020 -0400 Cygwin: FIFO: add a third pass to raw_read 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. Diff: --- 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 ();