Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/fhandler_fifo.cc66
1 files 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,11 +1373,48 @@ 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)
{
NTSTATUS status;
@@ -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 ();