4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-18 20:39:33 +08:00

* exceptions.cc (_cygtls::handle_SIGCONT): Simplify loop waiting for

sig_handle_tty_stop to wake up.  Make sure to unlock before calling
	yield to avoid starvation of sig_handle_tty_stop.  Add comments.
	* miscfuncs.cc (yield): Explain why yield should never be called under
	_cygtls::lock conditions.  Call SleepEx with 1ms timeout.  Explain why.
This commit is contained in:
Corinna Vinschen 2013-06-06 15:29:41 +00:00
parent 925e1c8157
commit b3f0fb6baa
3 changed files with 30 additions and 23 deletions

View File

@ -1,3 +1,11 @@
2013-06-06 Corinna Vinschen <corinna@vinschen.de>
* exceptions.cc (_cygtls::handle_SIGCONT): Simplify loop waiting for
sig_handle_tty_stop to wake up. Make sure to unlock before calling
yield to avoid starvation of sig_handle_tty_stop. Add comments.
* miscfuncs.cc (yield): Explain why yield should never be called under
_cygtls::lock conditions. Call SleepEx with 1ms timeout. Explain why.
2013-06-05 Corinna Vinschen <corinna@vinschen.de> 2013-06-05 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 20. * include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 20.

View File

@ -1253,25 +1253,18 @@ _cygtls::handle_SIGCONT ()
{ {
myself->stopsig = 0; myself->stopsig = 0;
myself->process_state &= ~PID_STOPPED; myself->process_state &= ~PID_STOPPED;
int state = 0;
/* Carefully tell sig_handle_tty_stop to wake up. */ /* Carefully tell sig_handle_tty_stop to wake up. */
while (state < 2) lock ();
{ sig = SIGCONT;
lock (); SetEvent (signal_arrived);
if (sig) /* Make sure yield doesn't run under lock condition to avoid
yield (); /* state <= 1 */ starvation of sig_handle_tty_stop. */
else if (state) unlock ();
state++; /* state == 2 */ /* Wait until sig_handle_tty_stop woke up. */
else while (sig)
{ yield ();
sig = SIGCONT;
SetEvent (signal_arrived);
state++; /* state == 1 */
}
unlock ();
}
/* Tell wait_sig to handle any queued signals now that we're alive /* Tell wait_sig to handle any queued signals now that we're alive
again. */ again. */
sig_dispatch_pending (false); sig_dispatch_pending (false);
} }
/* Clear pending stop signals */ /* Clear pending stop signals */

View File

@ -236,7 +236,11 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
return (ssize_t) tot; return (ssize_t) tot;
} }
/* Try hard to schedule another thread. */ /* Try hard to schedule another thread.
Note: Don't call yield under _cygtls::lock conditions. It results in
potential starvation, especially on a single-CPU system, because
_cygtls::lock also calls yield when waiting for the lock. */
void void
yield () yield ()
{ {
@ -244,11 +248,13 @@ yield ()
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE); SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
/* MSDN implies that SleepEx(0,...) will force scheduling of other /* MSDN implies that SleepEx will force scheduling of other threads.
threads. Unlike SwitchToThread() the documentation does not mention Unlike SwitchToThread() the documentation does not mention other
other cpus so, presumably (hah!), this + using a lower priority will cpus so, presumably (hah!), this + using a lower priority will
stall this thread temporarily and cause another to run. */ stall this thread temporarily and cause another to run.
SleepEx (0, false); Note: Don't use 0 timeout. This takes a lot of CPU if something
goes wrong. */
SleepEx (1L, false);
} }
SetThreadPriority (GetCurrentThread (), prio); SetThreadPriority (GetCurrentThread (), prio);
} }