* 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>
|
||||
|
||||
Respond to more g++ warnings relating to initializing structures.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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.
|
||||
|
||||
|
|
|
@ -31,12 +31,15 @@ extern DWORD __sigfirst, __siglast;
|
|||
|
||||
static BOOL WINAPI ctrl_c_handler (DWORD);
|
||||
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. */
|
||||
|
||||
static NO_COPY int exit_already = 0;
|
||||
static NO_COPY muto *mask_sync = NULL;
|
||||
|
||||
HMODULE cygwin_hmodule;
|
||||
HANDLE NO_COPY console_handler_thread_waiter = NULL;
|
||||
|
||||
static const struct
|
||||
|
@ -611,12 +614,31 @@ handle_sigsuspend (sigset_t tempmask)
|
|||
extern DWORD exec_exit; // Possible exit value for exec
|
||||
extern int pending_signals;
|
||||
|
||||
extern __inline int
|
||||
int
|
||||
interruptible (DWORD pc)
|
||||
{
|
||||
#if 0
|
||||
DWORD pchigh = pc & 0xf0000000;
|
||||
return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) ||
|
||||
!(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
|
||||
|
@ -689,7 +711,9 @@ static int
|
|||
call_handler (int sig, struct sigaction& siga, void *handler)
|
||||
{
|
||||
CONTEXT *cx, orig;
|
||||
int interrupted = 1;
|
||||
int res;
|
||||
extern muto *sync_proc_subproc;
|
||||
|
||||
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());
|
||||
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);
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
else if (!interrupt_on_return (cx, sig, siga, handler))
|
||||
{
|
||||
set_pending:
|
||||
pending_signals = 1; /* FIXME: Probably need to be more tricky here */
|
||||
sig_set_pending (sig);
|
||||
interrupted = 0;
|
||||
}
|
||||
|
||||
(void) ResumeThread (hth);
|
||||
if (interrupted)
|
||||
(void) SetEvent (signal_arrived); // For an EINTR case
|
||||
sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
|
||||
|
||||
out:
|
||||
sigproc_printf ("returning");
|
||||
return 1;
|
||||
return interrupted;
|
||||
}
|
||||
#endif /* i386 */
|
||||
|
||||
|
@ -983,6 +1027,17 @@ events_init (void)
|
|||
|
||||
ProtectHandle (title_mutex);
|
||||
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
|
||||
|
@ -1035,12 +1090,7 @@ _sigreturn:
|
|||
ret
|
||||
|
||||
_sigdelayed:
|
||||
# addl 4,%%esp
|
||||
cmpl $0,_pending_signals
|
||||
je 2f
|
||||
pushl $0
|
||||
call _sig_dispatch_pending@4
|
||||
2: pushl %2 # original return address
|
||||
pushl %2 # original return address
|
||||
pushf
|
||||
pushl %%esi
|
||||
pushl %%edi
|
||||
|
@ -1053,9 +1103,16 @@ _sigdelayed:
|
|||
pushl %4 # signal argument
|
||||
pushl $_sigreturn
|
||||
movl $0,%0
|
||||
pushl $_signal_arrived
|
||||
call _ResetEvent@4
|
||||
jmp *%5
|
||||
|
||||
pushl _signal_arrived # Everybody waiting for this should
|
||||
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:
|
||||
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* fhandler_floppy.cc. See fhandler.h for a description of the
|
||||
fhandler classes.
|
||||
|
||||
Copyright 1999 Cygnus Solutions.
|
||||
Copyright 1999, 2000 Cygnus Solutions.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* fork.cc
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999 Cygnus Solutions.
|
||||
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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.
|
||||
|
||||
|
@ -12,26 +12,17 @@ details. */
|
|||
#include <ctype.h>
|
||||
#include "winsup.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
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);
|
||||
extern HMODULE cygwin_hmodule;
|
||||
|
||||
int NO_COPY dynamically_loaded;
|
||||
|
||||
int
|
||||
WINAPI dll_entry (HANDLE, DWORD reason, void *static_load)
|
||||
extern "C" int
|
||||
WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
cygwin_hmodule = (HMODULE) h;
|
||||
dynamically_loaded = (static_load == NULL);
|
||||
break;
|
||||
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.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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.
|
||||
|
||||
|
|
|
@ -85,8 +85,6 @@ Static HANDLE hwait_subproc = NULL; // Handle of sig_subproc thread
|
|||
|
||||
Static HANDLE wait_sig_inited = NULL; // Control synchronization of
|
||||
// message queue startup
|
||||
Static muto *sync_proc_subproc = NULL; // Control access to
|
||||
// subproc stuff
|
||||
|
||||
/* 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_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
|
||||
Static DWORD sigtid = 0; // ID of the signal thread
|
||||
|
||||
|
@ -244,7 +245,7 @@ proc_subproc (DWORD what, DWORD val)
|
|||
int potential_match;
|
||||
DWORD exitcode;
|
||||
pinfo *child;
|
||||
int send_sigchld = 0;
|
||||
int clearing = 0;
|
||||
waitq *w;
|
||||
|
||||
#define wval ((waitq *) val)
|
||||
|
@ -284,14 +285,6 @@ proc_subproc (DWORD what, DWORD val)
|
|||
wake_wait_subproc ();
|
||||
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.
|
||||
* Possibly this is just due to an exec(). Cygwin implements an exec()
|
||||
* 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);
|
||||
hchildren[val] = child->hProcess; /* Filled out by child */
|
||||
ProtectHandle1 (child->hProcess, childhProc);
|
||||
wake_wait_subproc ();
|
||||
break; // This was an exec()
|
||||
}
|
||||
|
||||
|
@ -318,46 +310,21 @@ proc_subproc (DWORD what, DWORD val)
|
|||
child->pid, val, hchildren[val], nchildren, nzombies);
|
||||
remove_child (val); // Remove from children arrays
|
||||
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
|
||||
if (!proc_loop_wait) // Don't bother if wait_subproc is
|
||||
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. */
|
||||
sync_proc_subproc->release (); // Avoid a potential deadlock
|
||||
rc = sig_send (NULL, SIGCHLD); // Send a SIGCHLD
|
||||
goto out1; // Don't try to unlock. We don't have a lock.
|
||||
rc = sig_send (myself_nowait, SIGCHLD); // Send a SIGCHLD
|
||||
break; // 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
|
||||
* the main thread's dispatch to a signal handler function.
|
||||
|
@ -366,15 +333,41 @@ proc_subproc (DWORD what, DWORD val)
|
|||
case PROC_CLEARWAIT:
|
||||
/* Clear all "wait"ing 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)
|
||||
{
|
||||
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 */
|
||||
if (!SetEvent (w->next->ev))
|
||||
system_printf ("Couldn't wake up wait event, %E");
|
||||
if (!SetEvent (oldw))
|
||||
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;
|
||||
sip_printf ("finished clearing");
|
||||
}
|
||||
break;
|
||||
|
||||
/* Handle a wait4() operation. Allocates an event for the calling
|
||||
|
@ -1252,6 +1245,10 @@ wait_sig (VOID *)
|
|||
/* A normal UNIX signal */
|
||||
default:
|
||||
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);
|
||||
goto nextsig;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ enum procstuff
|
|||
PROC_CHILDSTOPPED = 2, // a child stopped
|
||||
PROC_CHILDTERMINATED = 3, // a child died
|
||||
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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
which is intended to operate similarly to a mutex but attempts to
|
||||
avoid making expensive calls to the kernel.
|
||||
|
||||
Copyright 1999 Cygnus Solutions.
|
||||
Copyright 2000 Cygnus Solutions.
|
||||
|
||||
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
|
||||
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
|
||||
muto::acquire (DWORD ms)
|
||||
{
|
||||
|
@ -59,7 +63,7 @@ muto::acquire (DWORD ms)
|
|||
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
|
||||
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
|
||||
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. */
|
||||
if (!--visits)
|
||||
{
|
||||
tid = 0; /* We were the last unlocker. */
|
||||
InterlockedExchange (&sync, 0); /* Reset trigger. */
|
||||
/* This thread had incremented waiters but had never decremented it.
|
||||
Decrement it now. If it is >= 0 then there are possibly other
|
||||
threads waiting for the lock, so trigger bruteforce. */
|
||||
tid = 0; /* We were the last unlocker. */
|
||||
if (InterlockedDecrement (&waiters) >= 0)
|
||||
(void) SetEvent (bruteforce); /* Wake up one of the waiting threads */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* sync.h: Header file for cygwin synchronization primitives.
|
||||
|
||||
Copyright 1999 Cygnus Solutions.
|
||||
Copyright 1999, 2000 Cygnus Solutions.
|
||||
|
||||
Written by Christopher Faylor <cgf@cygnus.com>
|
||||
|
||||
|
@ -36,6 +36,7 @@ public:
|
|||
|
||||
/* Return true if caller thread owns the lock. */
|
||||
int ismine () {return tid == GetCurrentThreadId ();}
|
||||
DWORD owner () {return tid;}
|
||||
};
|
||||
|
||||
/* Use a statically allocated buffer as the storage for a muto */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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.
|
||||
|
||||
|
|
Loading…
Reference in New Issue