* exceptions.cc (sigthread::get_winapi_lock): Just do standard 'give up

timeslice' wait.
(setup_handler): Revamp YA to attempt to deliver signal multiple times on
failure rather than punting to wait_sig.
* miscfuncs.cc (low_priority_sleep): Accept INFINITE sleep to mean "don't reset
the priority after setting it to idle".  Return previous priority.
* winsup.h (SLEEP_0_STAY_LOW): Define.
(low_priority_sleep): Return an int.
* sigproc.h: Define WAIT_SIG_PRIORITY here.
* sigproc.cc: Remove WAIT_SIG_PRIORITY definition.
This commit is contained in:
Christopher Faylor 2002-11-22 04:43:47 +00:00
parent 505746ad22
commit 13af9a149d
7 changed files with 99 additions and 63 deletions

View File

@ -1,3 +1,17 @@
2002-11-21 Christopher Faylor <cgf@redhat.com>
* exceptions.cc (sigthread::get_winapi_lock): Just do standard 'give up
timeslice' wait.
(setup_handler): Revamp YA to attempt to deliver signal multiple times
on failure rather than punting to wait_sig.
* miscfuncs.cc (low_priority_sleep): Accept INFINITE sleep to mean
"don't reset the priority after setting it to idle". Return previous
priority.
* winsup.h (SLEEP_0_STAY_LOW): Define.
(low_priority_sleep): Return an int.
* sigproc.h: Define WAIT_SIG_PRIORITY here.
* sigproc.cc: Remove WAIT_SIG_PRIORITY definition.
2002-11-20 Pierre Humblet <pierre.humblet@ieee.org> 2002-11-20 Pierre Humblet <pierre.humblet@ieee.org>
* security.h: Declare internal_getpwsid and internal_getgrsid. * security.h: Declare internal_getpwsid and internal_getgrsid.

View File

@ -666,7 +666,7 @@ sigthread::get_winapi_lock (int test)
/* Need to do a busy loop because we can't block or a potential SuspendThread /* Need to do a busy loop because we can't block or a potential SuspendThread
will hang. */ will hang. */
while (InterlockedExchange (&winapi_lock, 1)) while (InterlockedExchange (&winapi_lock, 1))
low_priority_sleep (1); low_priority_sleep (0);
return 1; return 1;
} }
@ -782,26 +782,33 @@ static int
setup_handler (int sig, void *handler, struct sigaction& siga) setup_handler (int sig, void *handler, struct sigaction& siga)
{ {
CONTEXT cx; CONTEXT cx;
bool interrupted = 0; bool interrupted = false;
HANDLE hth = NULL;
int res;
sigthread *th = NULL; // Initialization needed to shut up gcc sigthread *th = NULL; // Initialization needed to shut up gcc
int prio = INFINITE;
if (sigsave.sig) if (sigsave.sig)
goto set_pending; goto set_pending;
for (int i = 0; !interrupted && i < CALL_HANDLER_RETRY; i++) for (int i = 0; i < CALL_HANDLER_RETRY; i++)
{ {
DWORD res;
HANDLE hth;
EnterCriticalSection (&mainthread.lock); EnterCriticalSection (&mainthread.lock);
if (mainthread.frame) if (mainthread.frame)
th = &mainthread; {
hth = NULL;
th = &mainthread;
}
else else
{ {
LeaveCriticalSection (&mainthread.lock); LeaveCriticalSection (&mainthread.lock);
th = NULL; if (!mainthread.get_winapi_lock (1))
continue;
hth = myself->getthread2signal (); hth = myself->getthread2signal ();
th = NULL;
/* Suspend the thread which will receive the signal. But first ensure that /* Suspend the thread which will receive the signal. But first ensure that
this thread doesn't have any mutos. (FIXME: Someday we should just grab this thread doesn't have any mutos. (FIXME: Someday we should just grab
@ -811,20 +818,29 @@ setup_handler (int sig, void *handler, struct sigaction& siga)
If one of these conditions is not true we loop for a fixed number of times 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 since we don't want to stall the signal handler. FIXME: Will this result in
noticeable delays? noticeable delays?
If the thread is already suspended (which can occur when a program is stopped) then If the thread is already suspended (which can occur when a program has called
just queue the signal. */ SuspendThread on itself then just queue the signal. */
if (!mainthread.get_winapi_lock (1)) EnterCriticalSection (&mainthread.lock);
continue;
sigproc_printf ("suspending mainthread"); sigproc_printf ("suspending mainthread");
res = SuspendThread (hth); res = SuspendThread (hth);
mainthread.release_winapi_lock (); /* Just release the lock now since we hav suspended the main thread and it
if (mainthread.frame) definitely can't be grabbing it now. This will have to change, of course,
goto resume_thread; /* In case the main thread *just* set the frame */ if/when we can send signals to other than the main thread. */
LeaveCriticalSection (&mainthread.lock);
/* Just set pending if thread is already suspended */ /* Just set pending if thread is already suspended */
if (res) if (res)
goto set_pending; {
(void) ResumeThread (hth);
break;
}
mainthread.release_winapi_lock ();
if (mainthread.frame)
goto resume_thread; /* We just got the frame. What are the odds?
Just loop and we'll hopefully pick it up on
the next pass through. */
muto *m; muto *m;
/* FIXME: Make multi-thread aware */ /* FIXME: Make multi-thread aware */
@ -835,71 +851,63 @@ setup_handler (int sig, void *handler, struct sigaction& siga)
goto resume_thread; goto resume_thread;
} }
EnterCriticalSection (&mainthread.lock);
if (mainthread.frame) if (mainthread.frame)
{ th = &mainthread;
th = &mainthread;
goto try_to_interrupt;
}
LeaveCriticalSection (&mainthread.lock);
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
system_printf ("couldn't get context of main thread, %E");
else if (!interruptible (cx.Eip, 1))
sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
cx.Eip, cx.Esp);
else else
goto try_to_interrupt; {
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
resume_thread: if (!GetThreadContext (hth, &cx))
ResumeThread (hth); {
low_priority_sleep (0); system_printf ("couldn't get context of main thread, %E");
continue; goto resume_thread;
}
}
}
if ((DWORD) prio != INFINITE)
{
/* Reset the priority so we can finish this off quickly. */
SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY);
prio = INFINITE;
} }
try_to_interrupt:
if (th) if (th)
{ {
interrupted = interrupt_on_return (th, sig, handler, siga); interrupted = interrupt_on_return (th, sig, handler, siga);
LeaveCriticalSection (&th->lock); LeaveCriticalSection (&th->lock);
} }
else if (interruptible (cx.Eip)) else if (interruptible (cx.Eip))
{ interrupted = interrupt_now (&cx, sig, handler, siga);
interrupted = interrupt_now (&cx, sig, handler, siga);
#ifdef DEBUGGING resume_thread:
if (!interrupted) if (hth)
sigproc_printf ("couldn't deliver signal %d via %p", sig, cx.Eip); res = ResumeThread (hth);
#endif
} if (interrupted)
else
break; break;
if ((DWORD) prio != INFINITE && !mainthread.frame)
prio = low_priority_sleep (SLEEP_0_STAY_LOW);
sigproc_printf ("couldn't interrupt. trying again.");
} }
set_pending: set_pending:
if (interrupted) if (interrupted)
res = 1; {
if ((DWORD) prio != INFINITE)
SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY);
sigproc_printf ("signal successfully delivered");
}
else else
{ {
pending_signals = 1; /* FIXME: Probably need to be more tricky here */ pending_signals = 1; /* FIXME: Probably need to be more tricky here */
sig_set_pending (sig); sig_set_pending (sig);
sig_dispatch_pending (1); sig_dispatch_pending (1);
low_priority_sleep (0); /* Hopefully, other process will be waking up soon. */ low_priority_sleep (SLEEP_0_STAY_LOW); /* Hopefully, other process will be waking up soon. */
sigproc_printf ("couldn't send signal %d", sig); sigproc_printf ("couldn't send signal %d", sig);
} }
if (!hth)
sigproc_printf ("good. Didn't suspend main thread, th %p", th);
else
{
res = ResumeThread (hth);
sigproc_printf ("ResumeThread returned %d", res);
}
sigproc_printf ("returning %d", interrupted); sigproc_printf ("returning %d", interrupted);
if (pending_signals)
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
return interrupted; return interrupted;
} }
#endif /* i386 */ #endif /* i386 */

View File

@ -292,12 +292,27 @@ sys_mbstowcs (WCHAR *tgt, const char *src, int len)
return MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len); return MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len);
} }
void __stdcall int __stdcall
low_priority_sleep (DWORD secs) low_priority_sleep (DWORD secs)
{ {
HANDLE thisthread = GetCurrentThread (); HANDLE thisthread = GetCurrentThread ();
int curr_prio = GetThreadPriority (thisthread); int curr_prio = GetThreadPriority (thisthread);
bool staylow;
if (secs != INFINITE)
staylow = false;
else
{
secs = 0;
staylow = true;
}
/* Force any threads in normal priority to be scheduled */
SetThreadPriority (thisthread, THREAD_PRIORITY_NORMAL);
Sleep (0);
SetThreadPriority (thisthread, THREAD_PRIORITY_IDLE); SetThreadPriority (thisthread, THREAD_PRIORITY_IDLE);
Sleep (secs); Sleep (secs);
SetThreadPriority (thisthread, curr_prio); if (!staylow)
SetThreadPriority (thisthread, curr_prio);
return curr_prio;
} }

View File

@ -57,7 +57,7 @@ signal (int sig, _sig_func_ptr func)
myself->getsig (sig).sa_handler = func; myself->getsig (sig).sa_handler = func;
myself->getsig (sig).sa_mask = 0; myself->getsig (sig).sa_mask = 0;
/* SA_RESTART is set to maintain BSD compatible signal behaviour by default. /* SA_RESTART is set to maintain BSD compatible signal behaviour by default.
This is also compatible to the behaviour of signal(2) in Linux. */ This is also compatible with the behaviour of signal(2) in Linux. */
myself->getsig (sig).sa_flags |= SA_RESTART; myself->getsig (sig).sa_flags |= SA_RESTART;
set_sigcatchers (prev, func); set_sigcatchers (prev, func);

View File

@ -41,8 +41,6 @@ details. */
#define WSPX 20000 // Wait for wait_sig to terminate #define WSPX 20000 // Wait for wait_sig to terminate
#define WWSP 20000 // Wait for wait_subproc to terminate #define WWSP 20000 // Wait for wait_subproc to terminate
#define WAIT_SIG_PRIORITY THREAD_PRIORITY_TIME_CRITICAL
#define TOTSIGS (NSIG + __SIGOFFSET) #define TOTSIGS (NSIG + __SIGOFFSET)
#define wake_wait_subproc() SetEvent (events[0]) #define wake_wait_subproc() SetEvent (events[0])

View File

@ -124,7 +124,7 @@ void __stdcall wait_for_sigthread ();
extern char myself_nowait_dummy[]; extern char myself_nowait_dummy[];
extern char myself_nowait_nonmain_dummy[]; extern char myself_nowait_nonmain_dummy[];
#define WAIT_SIG_EXITING (WAIT_OBJECT_0 + 1) #define WAIT_SIG_PRIORITY THREAD_PRIORITY_TIME_CRITICAL
#define myself_nowait ((_pinfo *)myself_nowait_dummy) #define myself_nowait ((_pinfo *)myself_nowait_dummy)
#define myself_nowait_nonmain ((_pinfo *)myself_nowait_nonmain_dummy) #define myself_nowait_nonmain ((_pinfo *)myself_nowait_nonmain_dummy)

View File

@ -242,7 +242,8 @@ extern void multiple_cygwin_problem (const char *, unsigned, unsigned);
class path_conv; class path_conv;
int __stdcall stat_worker (const char *name, struct __stat64 *buf, int nofollow, int __stdcall stat_worker (const char *name, struct __stat64 *buf, int nofollow,
path_conv *pc = NULL) __attribute__ ((regparm (3))); path_conv *pc = NULL) __attribute__ ((regparm (3)));
void __stdcall low_priority_sleep (DWORD) __attribute__ ((regparm (1))); int __stdcall low_priority_sleep (DWORD) __attribute__ ((regparm (1)));
#define SLEEP_0_STAY_LOW INFINITE
/**************************** Exports ******************************/ /**************************** Exports ******************************/