* 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().
This commit is contained in:
Christopher Faylor 2011-07-06 16:33:30 +00:00
parent fa0b926af9
commit d1204b6378
3 changed files with 68 additions and 45 deletions

View File

@ -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.

View File

@ -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->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.
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 ("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 ();
break;
res = ResumeThread (hth);
if (interrupted)
goto out;
sigproc_printf ("couldn't interrupt. trying again.");
yield ();
}
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);
tls->unlock ();
res = ResumeThread (hth);
if (interrupted)
break;
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:

View File

@ -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,