+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>
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 20.
{
myself->stopsig = 0;
myself->process_state &= ~PID_STOPPED;
- int state = 0;
/* Carefully tell sig_handle_tty_stop to wake up. */
- while (state < 2)
- {
- lock ();
- if (sig)
- yield (); /* state <= 1 */
- else if (state)
- state++; /* state == 2 */
- else
- {
- sig = SIGCONT;
- SetEvent (signal_arrived);
- state++; /* state == 1 */
- }
- unlock ();
- }
+ lock ();
+ sig = SIGCONT;
+ SetEvent (signal_arrived);
+ /* Make sure yield doesn't run under lock condition to avoid
+ starvation of sig_handle_tty_stop. */
+ unlock ();
+ /* Wait until sig_handle_tty_stop woke up. */
+ while (sig)
+ yield ();
/* Tell wait_sig to handle any queued signals now that we're alive
- again. */
+ again. */
sig_dispatch_pending (false);
}
/* Clear pending stop signals */
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
yield ()
{
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
for (int i = 0; i < 2; i++)
{
- /* 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);
+ /* MSDN implies that SleepEx 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.
+ Note: Don't use 0 timeout. This takes a lot of CPU if something
+ goes wrong. */
+ SleepEx (1L, false);
}
SetThreadPriority (GetCurrentThread (), prio);
}