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:
authorCorinna Vinschen <corinna@vinschen.de>2016-03-20 23:59:27 +0300
committerCorinna Vinschen <corinna@vinschen.de>2016-03-20 23:59:27 +0300
commit66dc7d731aaefb79efda7181bffd81abdc7d5413 (patch)
treefc32a3017f485638ddbdc38be0a1f732c2df0ca9
parent1cca343e4714d11c53e23c8a3a17deba3e5531db (diff)
Revert "Improve and simplify select()."
This reverts commit 472d0a228c56bd4783ebb0561667cda2de3cd168. Revert accidental push
-rw-r--r--winsup/cygwin/cygwait.h27
-rw-r--r--winsup/cygwin/select.cc63
-rw-r--r--winsup/cygwin/select.h1
3 files changed, 76 insertions, 15 deletions
diff --git a/winsup/cygwin/cygwait.h b/winsup/cygwin/cygwait.h
index 1240f5404..3e02cdd66 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 556a79f21..25b0c5a98 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 3c749ad6e..581ee4e73 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