mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-28 03:27:46 +08:00
* exceptions.cc (interruptible): Change method for determining if something is
interruptible. (call_handler): Avoid suspending a thread if it owns a mutex. Only set signal_arrived if the thread was actually interrupted. (events_init): Initialize module information needed by interruptible(). (sigdelayed): Don't call sig_dispatch_pending since it could screw up * init.cc (dll_entry): Record module handle of main for use by interruptible(). (proc_subproc): Reorganize handling of terminated child so that the bulk of the processing comes from the signal thread. (wait_sig): Force processing of waiting threads if SIGCHLD is not processed. * sync.cc (muto::release): Set tid == 0 after lock is released or signal processor will be confused.
This commit is contained in:
parent
58dabf5040
commit
f02f1f1444
@ -1,3 +1,20 @@
|
|||||||
|
Wed Feb 23 21:34:58 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* exceptions.cc (interruptible): Change method for determining if
|
||||||
|
something is interruptible.
|
||||||
|
(call_handler): Avoid suspending a thread if it owns a mutex. Only set
|
||||||
|
signal_arrived if the thread was actually interrupted.
|
||||||
|
(events_init): Initialize module information needed by interruptible().
|
||||||
|
(sigdelayed): Don't call sig_dispatch_pending since it could screw up
|
||||||
|
* init.cc (dll_entry): Record module handle of main for use by
|
||||||
|
interruptible().
|
||||||
|
(proc_subproc): Reorganize handling of terminated child so that the
|
||||||
|
bulk of the processing comes from the signal thread.
|
||||||
|
(wait_sig): Force processing of waiting threads if SIGCHLD is not
|
||||||
|
processed.
|
||||||
|
* sync.cc (muto::release): Set tid == 0 after lock is released or
|
||||||
|
signal processor will be confused.
|
||||||
|
|
||||||
Tue Feb 22 23:06:01 2000 Christopher Faylor <cgf@cygnus.com>
|
Tue Feb 22 23:06:01 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
Respond to more g++ warnings relating to initializing structures.
|
Respond to more g++ warnings relating to initializing structures.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* autoload.h: Define functions for auto-loading symbols from a DLL.
|
/* autoload.h: Define functions for auto-loading symbols from a DLL.
|
||||||
|
|
||||||
Copyright 1999 Cygnus Solutions.
|
Copyright 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
Written by Christopher Faylor <cgf@cygnus.com>
|
Written by Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* errno.cc: errno-related functions
|
/* errno.cc: errno-related functions
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -31,12 +31,15 @@ extern DWORD __sigfirst, __siglast;
|
|||||||
|
|
||||||
static BOOL WINAPI ctrl_c_handler (DWORD);
|
static BOOL WINAPI ctrl_c_handler (DWORD);
|
||||||
static void really_exit (int);
|
static void really_exit (int);
|
||||||
|
static char windows_system_directory[1024];
|
||||||
|
static size_t windows_system_directory_length;
|
||||||
|
|
||||||
/* This is set to indicate that we have already exited. */
|
/* This is set to indicate that we have already exited. */
|
||||||
|
|
||||||
static NO_COPY int exit_already = 0;
|
static NO_COPY int exit_already = 0;
|
||||||
static NO_COPY muto *mask_sync = NULL;
|
static NO_COPY muto *mask_sync = NULL;
|
||||||
|
|
||||||
|
HMODULE cygwin_hmodule;
|
||||||
HANDLE NO_COPY console_handler_thread_waiter = NULL;
|
HANDLE NO_COPY console_handler_thread_waiter = NULL;
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
@ -611,12 +614,31 @@ handle_sigsuspend (sigset_t tempmask)
|
|||||||
extern DWORD exec_exit; // Possible exit value for exec
|
extern DWORD exec_exit; // Possible exit value for exec
|
||||||
extern int pending_signals;
|
extern int pending_signals;
|
||||||
|
|
||||||
extern __inline int
|
int
|
||||||
interruptible (DWORD pc)
|
interruptible (DWORD pc)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
DWORD pchigh = pc & 0xf0000000;
|
DWORD pchigh = pc & 0xf0000000;
|
||||||
return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) ||
|
return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) ||
|
||||||
!(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000);
|
!(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000);
|
||||||
|
#else
|
||||||
|
if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
MEMORY_BASIC_INFORMATION m;
|
||||||
|
memset (&m, 0, sizeof m);
|
||||||
|
if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
|
||||||
|
sigproc_printf ("couldn't get memory info, %E");
|
||||||
|
|
||||||
|
# define h ((HMODULE) m.AllocationBase)
|
||||||
|
if (h == cygwin_hmodule)
|
||||||
|
return 0;
|
||||||
|
char *checkdir = (char *) alloca (windows_system_directory_length);
|
||||||
|
if (!GetModuleFileName (h, checkdir, windows_system_directory_length))
|
||||||
|
return 0;
|
||||||
|
return !strncasematch (windows_system_directory, checkdir, windows_system_directory_length);
|
||||||
|
# undef h
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -689,7 +711,9 @@ static int
|
|||||||
call_handler (int sig, struct sigaction& siga, void *handler)
|
call_handler (int sig, struct sigaction& siga, void *handler)
|
||||||
{
|
{
|
||||||
CONTEXT *cx, orig;
|
CONTEXT *cx, orig;
|
||||||
|
int interrupted = 1;
|
||||||
int res;
|
int res;
|
||||||
|
extern muto *sync_proc_subproc;
|
||||||
|
|
||||||
if (hExeced != NULL && hExeced != INVALID_HANDLE_VALUE)
|
if (hExeced != NULL && hExeced != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@ -706,7 +730,24 @@ call_handler (int sig, struct sigaction& siga, void *handler)
|
|||||||
|
|
||||||
sigproc_printf ("Suspending %p (mainthread)", myself->getthread2signal());
|
sigproc_printf ("Suspending %p (mainthread)", myself->getthread2signal());
|
||||||
HANDLE hth = myself->getthread2signal ();
|
HANDLE hth = myself->getthread2signal ();
|
||||||
|
/* Suspend the thread which will receive the signal. But first ensure that
|
||||||
|
this thread doesn't have the sync_proc_subproc and mask_sync mutos, since
|
||||||
|
we need those (hack alert). If the thread-to-be-suspended has either of
|
||||||
|
these mutos, enter a busy loop until it is released. If the thread is
|
||||||
|
already suspended (which should never occur) then just queue the signal. */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
res = SuspendThread (hth);
|
res = SuspendThread (hth);
|
||||||
|
/* FIXME: Make multi-thread aware */
|
||||||
|
if (sync_proc_subproc->owner () != maintid && mask_sync->owner () != maintid)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
goto set_pending;
|
||||||
|
ResumeThread (hth);
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
|
||||||
sigproc_printf ("suspend said %d, %E", res);
|
sigproc_printf ("suspend said %d, %E", res);
|
||||||
|
|
||||||
/* Clear any waiting threads prior to dispatching to handler function */
|
/* Clear any waiting threads prior to dispatching to handler function */
|
||||||
@ -734,17 +775,20 @@ call_handler (int sig, struct sigaction& siga, void *handler)
|
|||||||
interrupt_now (cx, sig, siga, handler);
|
interrupt_now (cx, sig, siga, handler);
|
||||||
else if (!interrupt_on_return (cx, sig, siga, handler))
|
else if (!interrupt_on_return (cx, sig, siga, handler))
|
||||||
{
|
{
|
||||||
|
set_pending:
|
||||||
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);
|
||||||
|
interrupted = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) ResumeThread (hth);
|
(void) ResumeThread (hth);
|
||||||
|
if (interrupted)
|
||||||
(void) SetEvent (signal_arrived); // For an EINTR case
|
(void) SetEvent (signal_arrived); // For an EINTR case
|
||||||
sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
|
sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sigproc_printf ("returning");
|
sigproc_printf ("returning");
|
||||||
return 1;
|
return interrupted;
|
||||||
}
|
}
|
||||||
#endif /* i386 */
|
#endif /* i386 */
|
||||||
|
|
||||||
@ -983,6 +1027,17 @@ events_init (void)
|
|||||||
|
|
||||||
ProtectHandle (title_mutex);
|
ProtectHandle (title_mutex);
|
||||||
mask_sync = new_muto (FALSE, NULL);
|
mask_sync = new_muto (FALSE, NULL);
|
||||||
|
windows_system_directory[0] = '\0';
|
||||||
|
(void) GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
|
||||||
|
char *end = strchr (windows_system_directory, '\0');
|
||||||
|
if (end == windows_system_directory)
|
||||||
|
api_fatal ("can't find windows system directory");
|
||||||
|
if (end[-1] != '\\')
|
||||||
|
{
|
||||||
|
*end++ = '\\';
|
||||||
|
*end = '\0';
|
||||||
|
}
|
||||||
|
windows_system_directory_length = end - windows_system_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1035,12 +1090,7 @@ _sigreturn:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
_sigdelayed:
|
_sigdelayed:
|
||||||
# addl 4,%%esp
|
pushl %2 # original return address
|
||||||
cmpl $0,_pending_signals
|
|
||||||
je 2f
|
|
||||||
pushl $0
|
|
||||||
call _sig_dispatch_pending@4
|
|
||||||
2: pushl %2 # original return address
|
|
||||||
pushf
|
pushf
|
||||||
pushl %%esi
|
pushl %%esi
|
||||||
pushl %%edi
|
pushl %%edi
|
||||||
@ -1053,9 +1103,16 @@ _sigdelayed:
|
|||||||
pushl %4 # signal argument
|
pushl %4 # signal argument
|
||||||
pushl $_sigreturn
|
pushl $_sigreturn
|
||||||
movl $0,%0
|
movl $0,%0
|
||||||
pushl $_signal_arrived
|
|
||||||
call _ResetEvent@4
|
pushl _signal_arrived # Everybody waiting for this should
|
||||||
jmp *%5
|
call _ResetEvent@4 # have woken up by now.
|
||||||
|
|
||||||
|
cmpl $0,_pending_signals
|
||||||
|
je 2f
|
||||||
|
pushl $0
|
||||||
|
call _sig_dispatch_pending@4
|
||||||
|
|
||||||
|
2: jmp *%5
|
||||||
|
|
||||||
___siglast:
|
___siglast:
|
||||||
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
|
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* external.cc: Interface to Cygwin internals from external programs.
|
/* external.cc: Interface to Cygwin internals from external programs.
|
||||||
|
|
||||||
Copyright 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
Written by Christopher Faylor <cgf@cygnus.com>
|
Written by Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* fhandler_floppy.cc. See fhandler.h for a description of the
|
/* fhandler_floppy.cc. See fhandler.h for a description of the
|
||||||
fhandler classes.
|
fhandler classes.
|
||||||
|
|
||||||
Copyright 1999 Cygnus Solutions.
|
Copyright 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* fork.cc
|
/* fork.cc
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* heap.cc: Cygwin heap manager.
|
/* heap.cc: Cygwin heap manager.
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* init.cc for WIN32.
|
/* init.cc for WIN32.
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -12,26 +12,17 @@ details. */
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "winsup.h"
|
#include "winsup.h"
|
||||||
|
|
||||||
extern "C"
|
extern HMODULE cygwin_hmodule;
|
||||||
{
|
|
||||||
int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" void *export_malloc (unsigned int);
|
|
||||||
extern "C" void *export_realloc (void *,unsigned int);
|
|
||||||
extern "C" void *export_calloc (unsigned int,unsigned int);
|
|
||||||
extern "C" void export_free (void *);
|
|
||||||
|
|
||||||
extern void do_global_ctors (void (**in_pfunc)(), int force);
|
|
||||||
|
|
||||||
int NO_COPY dynamically_loaded;
|
int NO_COPY dynamically_loaded;
|
||||||
|
|
||||||
int
|
extern "C" int
|
||||||
WINAPI dll_entry (HANDLE, DWORD reason, void *static_load)
|
WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||||
{
|
{
|
||||||
switch (reason)
|
switch (reason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
cygwin_hmodule = (HMODULE) h;
|
||||||
dynamically_loaded = (static_load == NULL);
|
dynamically_loaded = (static_load == NULL);
|
||||||
break;
|
break;
|
||||||
case DLL_THREAD_ATTACH:
|
case DLL_THREAD_ATTACH:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* pipe.cc: pipe for WIN32.
|
/* pipe.cc: pipe for Cygwin.
|
||||||
|
|
||||||
Copyright 1996, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* registry.cc: registry interface
|
/* registry.cc: registry interface
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -85,8 +85,6 @@ Static HANDLE hwait_subproc = NULL; // Handle of sig_subproc thread
|
|||||||
|
|
||||||
Static HANDLE wait_sig_inited = NULL; // Control synchronization of
|
Static HANDLE wait_sig_inited = NULL; // Control synchronization of
|
||||||
// message queue startup
|
// message queue startup
|
||||||
Static muto *sync_proc_subproc = NULL; // Control access to
|
|
||||||
// subproc stuff
|
|
||||||
|
|
||||||
/* Used by WaitForMultipleObjects. These are handles to child processes.
|
/* Used by WaitForMultipleObjects. These are handles to child processes.
|
||||||
*/
|
*/
|
||||||
@ -100,6 +98,9 @@ Static int nzombies = 0; // Number of deceased children
|
|||||||
Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
|
Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
|
||||||
Static waitq waitq_main; // Storage for main thread
|
Static waitq waitq_main; // Storage for main thread
|
||||||
|
|
||||||
|
muto NO_COPY *sync_proc_subproc = NULL; // Control access to
|
||||||
|
// subproc stuff
|
||||||
|
|
||||||
DWORD NO_COPY maintid = 0; // ID of the main thread
|
DWORD NO_COPY maintid = 0; // ID of the main thread
|
||||||
Static DWORD sigtid = 0; // ID of the signal thread
|
Static DWORD sigtid = 0; // ID of the signal thread
|
||||||
|
|
||||||
@ -244,7 +245,7 @@ proc_subproc (DWORD what, DWORD val)
|
|||||||
int potential_match;
|
int potential_match;
|
||||||
DWORD exitcode;
|
DWORD exitcode;
|
||||||
pinfo *child;
|
pinfo *child;
|
||||||
int send_sigchld = 0;
|
int clearing = 0;
|
||||||
waitq *w;
|
waitq *w;
|
||||||
|
|
||||||
#define wval ((waitq *) val)
|
#define wval ((waitq *) val)
|
||||||
@ -284,14 +285,6 @@ proc_subproc (DWORD what, DWORD val)
|
|||||||
wake_wait_subproc ();
|
wake_wait_subproc ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* A child is in the stopped state. Scan wait() queue to see if anyone
|
|
||||||
* should be notified. (Called from wait_sig thread)
|
|
||||||
*/
|
|
||||||
case PROC_CHILDSTOPPED:
|
|
||||||
child = myself; // Just to avoid accidental NULL dereference
|
|
||||||
sip_printf ("Received stopped notification");
|
|
||||||
goto scan_wait;
|
|
||||||
|
|
||||||
/* A child process had terminated.
|
/* A child process had terminated.
|
||||||
* Possibly this is just due to an exec(). Cygwin implements an exec()
|
* Possibly this is just due to an exec(). Cygwin implements an exec()
|
||||||
* as a "handoff" from one windows process to another. If child->hProcess
|
* as a "handoff" from one windows process to another. If child->hProcess
|
||||||
@ -310,7 +303,6 @@ proc_subproc (DWORD what, DWORD val)
|
|||||||
ForceCloseHandle1 (hchildren[val], childhProc);
|
ForceCloseHandle1 (hchildren[val], childhProc);
|
||||||
hchildren[val] = child->hProcess; /* Filled out by child */
|
hchildren[val] = child->hProcess; /* Filled out by child */
|
||||||
ProtectHandle1 (child->hProcess, childhProc);
|
ProtectHandle1 (child->hProcess, childhProc);
|
||||||
wake_wait_subproc ();
|
|
||||||
break; // This was an exec()
|
break; // This was an exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,46 +310,21 @@ proc_subproc (DWORD what, DWORD val)
|
|||||||
child->pid, val, hchildren[val], nchildren, nzombies);
|
child->pid, val, hchildren[val], nchildren, nzombies);
|
||||||
remove_child (val); // Remove from children arrays
|
remove_child (val); // Remove from children arrays
|
||||||
zombies[nzombies++] = child; // Add to zombie array
|
zombies[nzombies++] = child; // Add to zombie array
|
||||||
wake_wait_subproc (); // Notify wait_subproc thread that
|
|
||||||
// nchildren has changed.
|
|
||||||
child->process_state = PID_ZOMBIE;// Walking dead
|
child->process_state = PID_ZOMBIE;// Walking dead
|
||||||
if (!proc_loop_wait) // Don't bother if wait_subproc is
|
if (!proc_loop_wait) // Don't bother if wait_subproc is
|
||||||
break; // exiting
|
break; // exiting
|
||||||
|
|
||||||
send_sigchld = 1;
|
|
||||||
|
|
||||||
scan_wait:
|
|
||||||
/* Scan the linked list of wait()ing threads. If a wait's parameters
|
|
||||||
* match this pid, then activate it.
|
|
||||||
*/
|
|
||||||
for (w = &waitq_head; w->next != NULL; w = w->next)
|
|
||||||
{
|
|
||||||
if ((potential_match = checkstate (w)) > 0)
|
|
||||||
sip_printf ("released waiting thread");
|
|
||||||
else if (potential_match < 0)
|
|
||||||
sip_printf ("only found non-terminated children");
|
|
||||||
else if (potential_match == 0) // nothing matched
|
|
||||||
{
|
|
||||||
sip_printf ("waiting thread found no children");
|
|
||||||
HANDLE oldw = w->next->ev;
|
|
||||||
w->next->ev = NULL;
|
|
||||||
if (!SetEvent (oldw))
|
|
||||||
system_printf ("couldn't wake up wait event %p, %E", oldw);
|
|
||||||
w->next = w->next->next;
|
|
||||||
}
|
|
||||||
if (w->next == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sip_printf ("finished processing terminated/stopped child");
|
|
||||||
if (!send_sigchld)
|
|
||||||
break; // No need to send a SIGCHLD
|
|
||||||
|
|
||||||
/* Send a SIGCHLD to myself. */
|
/* Send a SIGCHLD to myself. */
|
||||||
sync_proc_subproc->release (); // Avoid a potential deadlock
|
rc = sig_send (myself_nowait, SIGCHLD); // Send a SIGCHLD
|
||||||
rc = sig_send (NULL, SIGCHLD); // Send a SIGCHLD
|
break; // Don't try to unlock. We don't have a lock.
|
||||||
goto out1; // Don't try to unlock. We don't have a lock.
|
|
||||||
|
|
||||||
|
/* A child is in the stopped state. Scan wait() queue to see if anyone
|
||||||
|
* should be notified. (Called from wait_sig thread)
|
||||||
|
*/
|
||||||
|
case PROC_CHILDSTOPPED:
|
||||||
|
child = myself; // Just to avoid accidental NULL dereference
|
||||||
|
sip_printf ("Received stopped notification");
|
||||||
|
goto scan_wait;
|
||||||
|
|
||||||
/* Clear all waiting threads. Called from exceptions.cc prior to
|
/* Clear all waiting threads. Called from exceptions.cc prior to
|
||||||
* the main thread's dispatch to a signal handler function.
|
* the main thread's dispatch to a signal handler function.
|
||||||
@ -366,15 +333,41 @@ proc_subproc (DWORD what, DWORD val)
|
|||||||
case PROC_CLEARWAIT:
|
case PROC_CLEARWAIT:
|
||||||
/* Clear all "wait"ing threads. */
|
/* Clear all "wait"ing threads. */
|
||||||
sip_printf ("clear waiting threads");
|
sip_printf ("clear waiting threads");
|
||||||
|
clearing = 1;
|
||||||
|
|
||||||
|
case PROC_SIGCHLD:
|
||||||
|
scan_wait:
|
||||||
|
/* Scan the linked list of wait()ing threads. If a wait's parameters
|
||||||
|
* match this pid, then activate it.
|
||||||
|
*/
|
||||||
for (w = &waitq_head; w->next != NULL; w = w->next)
|
for (w = &waitq_head; w->next != NULL; w = w->next)
|
||||||
{
|
{
|
||||||
sip_printf ("clearing waiting thread, pid %d", w->next->pid);
|
if ((potential_match = checkstate (w)) > 0)
|
||||||
|
sip_printf ("released waiting thread");
|
||||||
|
else if (!clearing && potential_match < 0)
|
||||||
|
sip_printf ("only found non-terminated children");
|
||||||
|
else if (potential_match <= 0) // nothing matched
|
||||||
|
{
|
||||||
|
sip_printf ("waiting thread found no children");
|
||||||
|
HANDLE oldw = w->next->ev;
|
||||||
|
w->next->ev = NULL;
|
||||||
|
if (clearing)
|
||||||
w->next->status = -1; /* flag that a signal was received */
|
w->next->status = -1; /* flag that a signal was received */
|
||||||
if (!SetEvent (w->next->ev))
|
if (!SetEvent (oldw))
|
||||||
system_printf ("Couldn't wake up wait event, %E");
|
system_printf ("couldn't wake up wait event %p, %E", oldw);
|
||||||
|
w->next = w->next->next;
|
||||||
}
|
}
|
||||||
|
if (w->next == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clearing)
|
||||||
|
sip_printf ("finished processing terminated/stopped child");
|
||||||
|
else
|
||||||
|
{
|
||||||
waitq_head.next = NULL;
|
waitq_head.next = NULL;
|
||||||
sip_printf ("finished clearing");
|
sip_printf ("finished clearing");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Handle a wait4() operation. Allocates an event for the calling
|
/* Handle a wait4() operation. Allocates an event for the calling
|
||||||
@ -1252,6 +1245,10 @@ wait_sig (VOID *)
|
|||||||
/* A normal UNIX signal */
|
/* A normal UNIX signal */
|
||||||
default:
|
default:
|
||||||
sip_printf ("Got signal %d", sig);
|
sip_printf ("Got signal %d", sig);
|
||||||
|
int wasdispatched = sig_handle (sig);
|
||||||
|
dispatched |= wasdispatched;
|
||||||
|
if (sig == SIGCHLD && !wasdispatched)
|
||||||
|
proc_subproc (PROC_SIGCHLD, 0);
|
||||||
dispatched |= sig_handle (sig);
|
dispatched |= sig_handle (sig);
|
||||||
goto nextsig;
|
goto nextsig;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ enum procstuff
|
|||||||
PROC_CHILDSTOPPED = 2, // a child stopped
|
PROC_CHILDSTOPPED = 2, // a child stopped
|
||||||
PROC_CHILDTERMINATED = 3, // a child died
|
PROC_CHILDTERMINATED = 3, // a child died
|
||||||
PROC_CLEARWAIT = 4, // clear all waits - signal arrived
|
PROC_CLEARWAIT = 4, // clear all waits - signal arrived
|
||||||
PROC_WAIT = 5 // setup for wait() for subproc
|
PROC_WAIT = 5, // setup for wait() for subproc
|
||||||
|
PROC_SIGCHLD = 6 // saw a non-trapped SIGCHLD
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct struct_waitq
|
typedef struct struct_waitq
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
which is intended to operate similarly to a mutex but attempts to
|
which is intended to operate similarly to a mutex but attempts to
|
||||||
avoid making expensive calls to the kernel.
|
avoid making expensive calls to the kernel.
|
||||||
|
|
||||||
Copyright 1999 Cygnus Solutions.
|
Copyright 2000 Cygnus Solutions.
|
||||||
|
|
||||||
Written by Christopher Faylor <cgf@cygnus.com>
|
Written by Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
@ -43,7 +43,11 @@ muto::~muto ()
|
|||||||
|
|
||||||
/* Acquire the lock. Argument is the number of milliseconds to wait for
|
/* Acquire the lock. Argument is the number of milliseconds to wait for
|
||||||
the lock. Multiple visits from the same thread are allowed and should
|
the lock. Multiple visits from the same thread are allowed and should
|
||||||
be handled correctly. */
|
be handled correctly.
|
||||||
|
|
||||||
|
Note: The goal here is to minimize, as much as possible, calls to the
|
||||||
|
OS. Hence the use of InterlockedIncrement, etc., rather than (much) more
|
||||||
|
expensive OS mutexes. */
|
||||||
int
|
int
|
||||||
muto::acquire (DWORD ms)
|
muto::acquire (DWORD ms)
|
||||||
{
|
{
|
||||||
@ -59,7 +63,7 @@ muto::acquire (DWORD ms)
|
|||||||
lock the same muto to succeed without attempting to manipulate sync.
|
lock the same muto to succeed without attempting to manipulate sync.
|
||||||
If the muto is already locked then this thread will wait for ms until
|
If the muto is already locked then this thread will wait for ms until
|
||||||
it is signalled by muto::release. Then it will attempt to grab the
|
it is signalled by muto::release. Then it will attempt to grab the
|
||||||
sync field. If it succeeds, then this thread owns the mutex.
|
sync field. If it succeeds, then this thread owns the muto.
|
||||||
|
|
||||||
There is a pathological condition where a thread times out waiting for
|
There is a pathological condition where a thread times out waiting for
|
||||||
bruteforce but the release code triggers the bruteforce event. In this
|
bruteforce but the release code triggers the bruteforce event. In this
|
||||||
@ -99,11 +103,11 @@ muto::release ()
|
|||||||
/* FIXME: Need to check that other thread has not exited, too. */
|
/* FIXME: Need to check that other thread has not exited, too. */
|
||||||
if (!--visits)
|
if (!--visits)
|
||||||
{
|
{
|
||||||
tid = 0; /* We were the last unlocker. */
|
|
||||||
InterlockedExchange (&sync, 0); /* Reset trigger. */
|
InterlockedExchange (&sync, 0); /* Reset trigger. */
|
||||||
/* This thread had incremented waiters but had never decremented it.
|
/* This thread had incremented waiters but had never decremented it.
|
||||||
Decrement it now. If it is >= 0 then there are possibly other
|
Decrement it now. If it is >= 0 then there are possibly other
|
||||||
threads waiting for the lock, so trigger bruteforce. */
|
threads waiting for the lock, so trigger bruteforce. */
|
||||||
|
tid = 0; /* We were the last unlocker. */
|
||||||
if (InterlockedDecrement (&waiters) >= 0)
|
if (InterlockedDecrement (&waiters) >= 0)
|
||||||
(void) SetEvent (bruteforce); /* Wake up one of the waiting threads */
|
(void) SetEvent (bruteforce); /* Wake up one of the waiting threads */
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* sync.h: Header file for cygwin synchronization primitives.
|
/* sync.h: Header file for cygwin synchronization primitives.
|
||||||
|
|
||||||
Copyright 1999 Cygnus Solutions.
|
Copyright 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
Written by Christopher Faylor <cgf@cygnus.com>
|
Written by Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
@ -36,6 +36,7 @@ public:
|
|||||||
|
|
||||||
/* Return true if caller thread owns the lock. */
|
/* Return true if caller thread owns the lock. */
|
||||||
int ismine () {return tid == GetCurrentThreadId ();}
|
int ismine () {return tid == GetCurrentThreadId ();}
|
||||||
|
DWORD owner () {return tid;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Use a statically allocated buffer as the storage for a muto */
|
/* Use a statically allocated buffer as the storage for a muto */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* thread.h: Locking and threading module definitions
|
/* thread.h: Locking and threading module definitions
|
||||||
|
|
||||||
Copyright 1998, 1999 Cygnus Solutions.
|
Copyright 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
Written by Marco Fuykschot <marco@ddi.nl>
|
Written by Marco Fuykschot <marco@ddi.nl>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* wait.cc: Posix wait routines.
|
/* wait.cc: Posix wait routines.
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user