summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog10
-rw-r--r--winsup/cygwin/exceptions.cc87
-rw-r--r--winsup/cygwin/miscfuncs.cc14
3 files changed, 67 insertions, 44 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index e822c1994..c1cfa4324 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,13 @@
+2011-07-06 Christopher Faylor <me.cygwin2011@cgf.cx>
+
+ * exceptions.cc (CALL_HANDLER_RETRY_INNER): Rename to reflect different
+ functionality.
+ (CALL_HANDLER_RETRY_OUTER): New define.
+ (setup_handler): Add outer loop to signal handler to try harder to
+ deliver the signal.
+ * miscfuncs.cc (yield): Drop priority and use SleepEx() to force thread
+ rescheduling rather than relying on SwitchToThread().
+
2011-07-06 Corinna Vinschen <corinna@vinschen.de>
* sigproc.cc (wait_sig): Fix debug output.
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 5d4acf033..638c6e3b8 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -32,7 +32,8 @@ details. */
#include "ntdll.h"
#include "exception.h"
-#define CALL_HANDLER_RETRY 20
+#define CALL_HANDLER_RETRY_OUTER 10
+#define CALL_HANDLER_RETRY_INNER 10
char debugger_command[2 * NT_MAX_PATH + 20];
@@ -848,52 +849,54 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
goto out;
}
- for (int i = 0; i < CALL_HANDLER_RETRY; i++)
+ for (int n = 0; n < CALL_HANDLER_RETRY_OUTER; n++)
{
- tls->lock ();
- if (tls->incyg)
+ for (int i = 0; i < CALL_HANDLER_RETRY_INNER; i++)
{
- sigproc_printf ("controlled interrupt. stackptr %p, stack %p, stackptr[-1] %p",
- tls->stackptr, tls->stack, tls->stackptr[-1]);
- tls->interrupt_setup (sig, handler, siga);
- interrupted = true;
- tls->unlock ();
- break;
- }
+ tls->lock ();
+ if (tls->incyg)
+ {
+ sigproc_printf ("controlled interrupt. stackptr %p, stack %p, stackptr[-1] %p",
+ tls->stackptr, tls->stack, tls->stackptr[-1]);
+ tls->interrupt_setup (sig, handler, siga);
+ interrupted = true;
+ tls->unlock ();
+ break;
+ }
- DWORD res;
- HANDLE hth = (HANDLE) *tls;
-
- /* Suspend the thread which will receive the signal.
- For Windows 95, we also have to ensure that the addresses returned by
- GetThreadContext are valid.
- If one of these conditions is not true we loop for a fixed number of times
- since we don't want to stall the signal handler. FIXME: Will this result in
- noticeable delays?
- If the thread is already suspended (which can occur when a program has called
- SuspendThread on itself) then just queue the signal. */
-
- sigproc_printf ("suspending thread");
- res = SuspendThread (hth);
- /* Just set pending if thread is already suspended */
- if (res)
- {
- ResumeThread (hth);
- break;
- }
- cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
- if (!GetThreadContext (hth, &cx))
- system_printf ("couldn't get context of thread, %E");
- else
- interrupted = tls->interrupt_now (&cx, sig, handler, siga);
+ DWORD res;
+ HANDLE hth = (HANDLE) *tls;
- tls->unlock ();
- res = ResumeThread (hth);
- if (interrupted)
- break;
+ /* Suspend the thread which will receive the signal.
+ If one of these conditions is not true we loop.
+ If the thread is already suspended (which can occur when a program
+ has called SuspendThread on itself) then just queue the signal. */
- sigproc_printf ("couldn't interrupt. trying again.");
- yield ();
+ sigproc_printf ("suspending thread");
+ res = SuspendThread (hth);
+ /* Just set pending if thread is already suspended */
+ if (res)
+ {
+ ResumeThread (hth);
+ goto out;
+ }
+ cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+ if (!GetThreadContext (hth, &cx))
+ system_printf ("couldn't get context of thread, %E");
+ else
+ interrupted = tls->interrupt_now (&cx, sig, handler, siga);
+
+ tls->unlock ();
+ res = ResumeThread (hth);
+ if (interrupted)
+ goto out;
+
+ sigproc_printf ("couldn't interrupt. trying again.");
+ yield ();
+ }
+ /* Hit here if we couldn't deliver the signal. Take a more drastic
+ action before trying again. */
+ Sleep (1);
}
out:
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 0ac25f4c3..d293edea9 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -235,11 +235,21 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
return (ssize_t) tot;
}
+/* Try hard to schedule another thread. */
void
yield ()
{
- for (int i = 0; i < 3; i++)
- SwitchToThread ();
+ for (int i = 0; i < 2; i++)
+ {
+ int prio = GetThreadPriority (GetCurrentThread ());
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
+ /* MSDN implies that SleepEx(0,...) will force scheduling of other
+ threads. Unlike SwitchToThread() the documentation does not mention
+ other cpus so, presumably (hah!), this + using a lower priority will
+ stall this thread temporarily and cause another to run. */
+ SleepEx (0, false);
+ SetThreadPriority (GetCurrentThread (), prio);
+ }
}
/* Get a default value for the nice factor. When changing these values,