[newlib-cygwin] Revert "Improve and simplify select()."

Corinna Vinschen corinna@sourceware.org
Sun Mar 20 21:00:00 GMT 2016


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

commit 66dc7d731aaefb79efda7181bffd81abdc7d5413
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Sun Mar 20 21:59:27 2016 +0100

    Revert "Improve and simplify select()."
    
    This reverts commit 472d0a228c56bd4783ebb0561667cda2de3cd168.
    
    Revert accidental push

Diff:
---
 winsup/cygwin/cygwait.h | 27 +++++++++++++++++++++
 winsup/cygwin/select.cc | 63 +++++++++++++++++++++++++++++++++++++------------
 winsup/cygwin/select.h  |  1 +
 3 files changed, 76 insertions(+), 15 deletions(-)

diff --git a/winsup/cygwin/cygwait.h b/winsup/cygwin/cygwait.h
index 1240f54..3e02cdd 100644
--- a/winsup/cygwin/cygwait.h
+++ b/winsup/cygwin/cygwait.h
@@ -59,3 +59,30 @@ cygwait (DWORD howlong)
 {
   return cygwait (NULL, howlong);
 }
+
+extern inline DWORD __attribute__ ((always_inline))
+cygwait_us (HANDLE h, LONGLONG howlong, unsigned mask)
+{
+  LARGE_INTEGER li_howlong;
+  PLARGE_INTEGER pli_howlong;
+  if (howlong < 0LL)
+    pli_howlong = NULL;
+  else
+    {
+      li_howlong.QuadPart = -(10LL * howlong);
+      pli_howlong = &li_howlong;
+    }
+  return cygwait (h, pli_howlong, mask);
+}
+
+static inline DWORD __attribute__ ((always_inline))
+cygwait_us (HANDLE h, LONGLONG howlong = -1)
+{
+  return cygwait_us (h, howlong, cw_cancel | cw_sig);
+}
+
+static inline DWORD __attribute__ ((always_inline))
+cygwait_us (LONGLONG howlong)
+{
+  return cygwait_us (NULL, howlong);
+}
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 556a79f..25b0c5a 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -32,6 +32,7 @@ details. */
 #include "pinfo.h"
 #include "sigproc.h"
 #include "cygtls.h"
+#include "cygwait.h"
 
 /*
  * All these defines below should be in sys/types.h
@@ -155,7 +156,7 @@ static int
 select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 	LONGLONG us)
 {
-  select_stuff::wait_states wait_state = select_stuff::select_set_zero;
+  select_stuff::wait_states wait_state = select_stuff::select_loop;
   int ret = 0;
 
   /* Record the current time for later use. */
@@ -181,7 +182,30 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 	  }
       select_printf ("sel.always_ready %d", sel.always_ready);
 
-      if (sel.always_ready || us == 0)
+      /* Degenerate case.  No fds to wait for.  Just wait for time to run out
+	 or signal to arrive. */
+      if (sel.start.next == NULL)
+	switch (cygwait_us (us))
+	  {
+	  case WAIT_SIGNALED:
+	    select_printf ("signal received");
+	    /* select() is always interrupted by a signal so set EINTR,
+	       unconditionally, ignoring any SA_RESTART detection by
+	       call_signal_handler().  */
+	    _my_tls.call_signal_handler ();
+	    set_sig_errno (EINTR);
+	    wait_state = select_stuff::select_signalled;
+	    break;
+	  case WAIT_CANCELED:
+	    sel.destroy ();
+	    pthread::static_cancel_self ();
+	    /*NOTREACHED*/
+	  default:
+	    /* Set wait_state to zero below. */
+	    wait_state = select_stuff::select_set_zero;
+	    break;
+	  }
+      else if (sel.always_ready || us == 0)
 	/* Catch any active fds via sel.poll() below */
 	wait_state = select_stuff::select_ok;
       else
@@ -190,24 +214,29 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 
       select_printf ("sel.wait returns %d", wait_state);
 
-      if (wait_state == select_stuff::select_ok)
+      if (wait_state >= select_stuff::select_ok)
 	{
 	  UNIX_FD_ZERO (readfds, maxfds);
 	  UNIX_FD_ZERO (writefds, maxfds);
 	  UNIX_FD_ZERO (exceptfds, maxfds);
-	  /* Set bit mask from sel records.  This also sets ret to the
-	     right value >= 0, matching the number of bits set in the
-	     fds records.  if ret is 0, continue to loop. */
-	  ret = sel.poll (readfds, writefds, exceptfds);
-	  if (!ret)
-	    wait_state = select_stuff::select_set_zero;
+	  if (wait_state == select_stuff::select_set_zero)
+	    ret = 0;
+	  else
+	    {
+	      /* Set bit mask from sel records.  This also sets ret to the
+		 right value >= 0, matching the number of bits set in the
+		 fds records.  if ret is 0, continue to loop. */
+	      ret = sel.poll (readfds, writefds, exceptfds);
+	      if (!ret)
+		wait_state = select_stuff::select_loop;
+	    }
 	}
       /* Always clean up everything here.  If we're looping then build it
 	 all up again.  */
       sel.cleanup ();
       sel.destroy ();
-      /* Check and recalculate timeout. */
-      if (us != -1LL && wait_state == select_stuff::select_set_zero)
+      /* Recalculate time remaining to wait if we are going to be looping. */
+      if (wait_state == select_stuff::select_loop && us != -1)
 	{
 	  select_printf ("recalculating us");
 	  LONGLONG now = gtod.usecs ();
@@ -229,7 +258,7 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 	    }
 	}
     }
-  while (wait_state == select_stuff::select_set_zero);
+  while (wait_state == select_stuff::select_loop);
 
   if (wait_state < select_stuff::select_ok)
     ret = -1;
@@ -465,7 +494,7 @@ next_while:;
 	 to wait for.  */
     default:
       s = &start;
-      res = select_set_zero;
+      bool gotone = false;
       /* Some types of objects (e.g., consoles) wake up on "inappropriate"
 	 events like mouse movements.  The verify function will detect these
 	 situations.  If it returns false, then this wakeup was a false alarm
@@ -479,9 +508,13 @@ next_while:;
 	  }
 	else if ((((wait_ret >= m && s->windows_handle) || s->h == w4[wait_ret]))
 		 && s->verify (s, readfds, writefds, exceptfds))
-	  res = select_ok;
+	  gotone = true;
 
-      select_printf ("res after verify %d", res);
+      if (!gotone)
+	res = select_loop;
+      else
+	res = select_ok;
+      select_printf ("gotone %d", gotone);
       break;
     }
 out:
diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h
index 3c749ad..581ee4e 100644
--- a/winsup/cygwin/select.h
+++ b/winsup/cygwin/select.h
@@ -78,6 +78,7 @@ public:
   enum wait_states
   {
     select_signalled = -3,
+    select_loop = -2,
     select_error = -1,
     select_ok = 0,
     select_set_zero = 1



More information about the Cygwin-cvs mailing list