* 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>
* 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
will hang. */
while (InterlockedExchange (&winapi_lock, 1))
low_priority_sleep (1);
low_priority_sleep (0);
return 1;
}
@ -782,26 +782,33 @@ static int
setup_handler (int sig, void *handler, struct sigaction& siga)
{
CONTEXT cx;
bool interrupted = 0;
HANDLE hth = NULL;
int res;
bool interrupted = false;
sigthread *th = NULL; // Initialization needed to shut up gcc
int prio = INFINITE;
if (sigsave.sig)
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);
if (mainthread.frame)
th = &mainthread;
{
hth = NULL;
th = &mainthread;
}
else
{
LeaveCriticalSection (&mainthread.lock);
th = NULL;
if (!mainthread.get_winapi_lock (1))
continue;
hth = myself->getthread2signal ();
th = NULL;
/* 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
@ -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
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 is stopped) then
just queue the signal. */
If the thread is already suspended (which can occur when a program has called
SuspendThread on itself then just queue the signal. */
if (!mainthread.get_winapi_lock (1))
continue;
EnterCriticalSection (&mainthread.lock);
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
mainthread.release_winapi_lock ();
if (mainthread.frame)
goto resume_thread; /* In case the main thread *just* set the frame */
/* Just release the lock now since we hav suspended the main thread and it
definitely can't be grabbing it now. This will have to change, of course,
if/when we can send signals to other than the main thread. */
LeaveCriticalSection (&mainthread.lock);
/* Just set pending if thread is already suspended */
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;
/* FIXME: Make multi-thread aware */
@ -835,71 +851,63 @@ setup_handler (int sig, void *handler, struct sigaction& siga)
goto resume_thread;
}
EnterCriticalSection (&mainthread.lock);
if (mainthread.frame)
{
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);
th = &mainthread;
else
goto try_to_interrupt;
resume_thread:
ResumeThread (hth);
low_priority_sleep (0);
continue;
{
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
{
system_printf ("couldn't get context of main thread, %E");
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)
{
interrupted = interrupt_on_return (th, sig, handler, siga);
LeaveCriticalSection (&th->lock);
}
else if (interruptible (cx.Eip))
{
interrupted = interrupt_now (&cx, sig, handler, siga);
#ifdef DEBUGGING
if (!interrupted)
sigproc_printf ("couldn't deliver signal %d via %p", sig, cx.Eip);
#endif
}
else
interrupted = interrupt_now (&cx, sig, handler, siga);
resume_thread:
if (hth)
res = ResumeThread (hth);
if (interrupted)
break;
if ((DWORD) prio != INFINITE && !mainthread.frame)
prio = low_priority_sleep (SLEEP_0_STAY_LOW);
sigproc_printf ("couldn't interrupt. trying again.");
}
set_pending:
if (interrupted)
res = 1;
{
if ((DWORD) prio != INFINITE)
SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY);
sigproc_printf ("signal successfully delivered");
}
else
{
pending_signals = 1; /* FIXME: Probably need to be more tricky here */
sig_set_pending (sig);
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);
}
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);
if (pending_signals)
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
return interrupted;
}
#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);
}
void __stdcall
int __stdcall
low_priority_sleep (DWORD secs)
{
HANDLE thisthread = GetCurrentThread ();
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);
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_mask = 0;
/* 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;
set_sigcatchers (prev, func);

View File

@ -41,8 +41,6 @@ details. */
#define WSPX 20000 // Wait for wait_sig to terminate
#define WWSP 20000 // Wait for wait_subproc to terminate
#define WAIT_SIG_PRIORITY THREAD_PRIORITY_TIME_CRITICAL
#define TOTSIGS (NSIG + __SIGOFFSET)
#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_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_nonmain ((_pinfo *)myself_nowait_nonmain_dummy)

View File

@ -242,7 +242,8 @@ extern void multiple_cygwin_problem (const char *, unsigned, unsigned);
class path_conv;
int __stdcall stat_worker (const char *name, struct __stat64 *buf, int nofollow,
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 ******************************/