diff options
author | Christopher Faylor <cgf@redhat.com> | 2003-04-04 18:56:46 +0000 |
---|---|---|
committer | Christopher Faylor <cgf@redhat.com> | 2003-04-04 18:56:46 +0000 |
commit | da9b2172d3404083be67d8a7862d1cc0b1a3befd (patch) | |
tree | e3e3758c8e08bc1da5fe65ada085e631b3867780 | |
parent | a61b224d3977401fbcc0bf963f8a2ad870ad6ef1 (diff) | |
download | gdb-da9b2172d3404083be67d8a7862d1cc0b1a3befd.tar.gz |
merge from trunk
-rw-r--r-- | winsup/cygwin/ChangeLog | 14 | ||||
-rw-r--r-- | winsup/cygwin/cygthread.cc | 43 | ||||
-rw-r--r-- | winsup/cygwin/cygthread.h | 47 |
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 |