summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2003-04-04 18:56:46 +0000
committerChristopher Faylor <cgf@redhat.com>2003-04-04 18:56:46 +0000
commitda9b2172d3404083be67d8a7862d1cc0b1a3befd (patch)
treee3e3758c8e08bc1da5fe65ada085e631b3867780
parenta61b224d3977401fbcc0bf963f8a2ad870ad6ef1 (diff)
downloadgdb-da9b2172d3404083be67d8a7862d1cc0b1a3befd.tar.gz
merge from trunk
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/cygthread.cc43
-rw-r--r--winsup/cygwin/cygthread.h47
3 files changed, 78 insertions, 26 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 474767ebccb..b839897bb9e 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,6 +1,18 @@
2003-04-04 Christopher Faylor <cgf@redhat.com>
- * cygthread.cc (operator new): Be more defensive when messing with
+ * cygthread.h (cygthread::avail): Make LONG for easier use with
+ Interlocked* functions.
+ * cygthread.cc (cygthread::init): Eliminate unneeded muto.
+ (cygthread::operator new): Don't lock. Instead change use of avail
+ variable into tri-state: available (1), not available (-1),
+ uninitialized (0).
+ (cygthread::terminate_thread): Set avail to uninitialized.
+ (cygthread::detach): Eliminate local 'avail'. Always set avail to 1
+ unless signalled.
+
+2003-04-04 Christopher Faylor <cgf@redhat.com>
+
+ * cygthread.cc (cygthread::operator new): Be more defensive when messing with
threads that are marked "unavailable".
2003-04-03 Christopher Faylor <cgf@redhat.com>
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index fd946e4ad7d..bc6c8bc9eaf 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -94,12 +94,10 @@ cygthread::simplestub (VOID *arg)
ExitThread (0);
}
-static NO_COPY muto *cygthread_protect;
/* Start things going. Called from dll_crt0_1. */
void
cygthread::init ()
{
- new_muto (cygthread_protect);
main_thread_id = GetCurrentThreadId ();
}
@@ -129,29 +127,27 @@ cygthread::freerange ()
void * cygthread::operator
new (size_t)
{
- DWORD id;
+ LONG is_avail;
cygthread *info;
- cygthread_protect->acquire ();
-
/* Search the threads array for an empty slot to use */
for (info = threads; info < threads + NTHREADS; info++)
- if ((LONG) (id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, -1)) < 0)
- /* being considered */;
- else if (id > 0)
+ if ((is_avail = InterlockedExchange (&info->avail, -1)) < 0)
+ /* in use */;
+ else if (is_avail > 0)
{
+ /* available */
#ifdef DEBUGGING
if (info->__name)
- api_fatal ("name not NULL? id %p, i %d", id, info - threads);
+ api_fatal ("name not NULL? id %p, i %d", info->id, info - threads);
if (!info->h)
- api_fatal ("h not set? id %p, i %d", id, info - threads);
+ api_fatal ("h not set? id %p, i %d", info->id, info - threads);
#endif
goto out;
}
- else if (info->id)
- InterlockedExchange ((LPLONG) &info->avail, 0);
else
{
+ /* Uninitialized. Available as soon as thread is created */
info->h = CreateThread (&sec_none_nih, 0, cygthread::stub, info,
CREATE_SUSPENDED, &info->id);
goto out;
@@ -159,15 +155,13 @@ new (size_t)
#ifdef DEBUGGING
char buf[1024];
- if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf)))
+ if (!GetEnvironmentVariable ("CYGWIN_FREERANGE_NOCHECK", buf, sizeof (buf)))
api_fatal ("Overflowed cygwin thread pool");
#endif
info = freerange (); /* exhausted thread pool */
out:
- InterlockedExchange ((LPLONG) &info->avail, 0);
- cygthread_protect->release ();
return info;
}
@@ -269,21 +263,21 @@ cygthread::terminate_thread ()
thread_sync = ev = h = NULL;
__name = NULL;
id = 0;
+ (void) InterlockedExchange (&avail, 0); /* No longer initialized */
}
/* Detach the cygthread from the current thread. Note that the
theory is that cygthreads are only associated with one thread.
- So, there should be no problems with multiple threads doing waits
- on the one cygthread. */
+ So, there should be never be multiple threads doing waits
+ on the same cygthread. */
bool
cygthread::detach (HANDLE sigwait)
{
bool signalled = false;
- if (avail)
- system_printf ("called detach on available thread %d?", avail);
+ if (avail >= 0)
+ system_printf ("called detach but avail %d, thread %d?", avail, id);
else
{
- DWORD newavail = id;
DWORD res;
if (!sigwait)
@@ -303,18 +297,17 @@ cygthread::detach (HANDLE sigwait)
res = WaitForSingleObject (*this, INFINITE);
else
{
+ signalled = true;
terminate_thread ();
set_sig_errno (EINTR); /* caller should be dealing with return
values. */
- newavail = 0;
- signalled = true;
}
}
thread_printf ("%s returns %d, id %p", sigwait ? "WFMO" : "WFSO",
res, id);
- if (!newavail)
+ if (signalled)
/* already handled */;
else if (is_freerange)
{
@@ -324,8 +317,8 @@ cygthread::detach (HANDLE sigwait)
else
{
ResetEvent (*this);
- /* Mark the thread as available by setting avail to non-zero */
- (void) InterlockedExchange ((LPLONG) &avail, newavail);
+ /* Mark the thread as available by setting avail to positive value */
+ (void) InterlockedExchange (&avail, 1);
}
}
return signalled;
diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h
new file mode 100644
index 00000000000..3226f2a02e7
--- /dev/null
+++ b/winsup/cygwin/cygthread.h
@@ -0,0 +1,47 @@
+/* cygthread.h
+
+ Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+class cygthread
+{
+ LONG avail; /* 1: available, 0: ininitialized, -1: not available */
+ DWORD id;
+ HANDLE h;
+ HANDLE ev;
+ HANDLE thread_sync;
+ void *stack_ptr;
+ const char *__name;
+ LPTHREAD_START_ROUTINE func;
+ VOID *arg;
+ bool is_freerange;
+ static DWORD main_thread_id;
+ static bool exiting;
+ static DWORD WINAPI stub (VOID *);
+ static DWORD WINAPI simplestub (VOID *);
+ public:
+ static const char * name (DWORD = 0);
+ cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *);
+ cygthread () {};
+ static void init ();
+ bool detach (HANDLE = NULL);
+ operator HANDLE ();
+ static bool is ();
+ void * operator new (size_t);
+ static cygthread *freerange ();
+ void exit_thread ();
+ void terminate_thread ();
+ static void terminate ();
+ bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);}
+ void zap_h ()
+ {
+ (void) CloseHandle (h);
+ h = NULL;
+ }
+
+};
+
+#define cygself NULL