* 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:
		| @@ -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. | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user