aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/exceptions.cc116
-rw-r--r--winsup/cygwin/miscfuncs.cc19
-rw-r--r--winsup/cygwin/signal.cc2
-rw-r--r--winsup/cygwin/sigproc.cc2
-rw-r--r--winsup/cygwin/sigproc.h2
-rw-r--r--winsup/cygwin/winsup.h3
7 files changed, 97 insertions, 61 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index e87d8c9..b0672ee 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index ae868cc..b18c61f 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -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;
+ else
{
- th = &mainthread;
- goto try_to_interrupt;
+ cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+ if (!GetThreadContext (hth, &cx))
+ {
+ system_printf ("couldn't get context of main thread, %E");
+ goto resume_thread;
+ }
}
+ }
- 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
- goto try_to_interrupt;
-
- resume_thread:
- ResumeThread (hth);
- low_priority_sleep (0);
- continue;
+ 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 */
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 9c7ab54..e585659 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -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;
}
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 9c807f4..010df9b 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -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);
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 5f4d4c0..aeb51f2 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -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])
diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h
index a461efd..c8c208e 100644
--- a/winsup/cygwin/sigproc.h
+++ b/winsup/cygwin/sigproc.h
@@ -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)
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 9b7e040..e46c072 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -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 ******************************/