* 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.
* cygthread.cc (cygthread::operator new): Be more defensive when messing with
This commit is contained in:
Christopher Faylor 2003-04-04 18:52:11 +00:00
parent 5557a0dace
commit 9dbe3289ee
3 changed files with 32 additions and 28 deletions

View File

@ -1,6 +1,18 @@
2003-04-04 Christopher Faylor <cgf@redhat.com> 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". threads that are marked "unavailable".
2003-04-03 Christopher Faylor <cgf@redhat.com> 2003-04-03 Christopher Faylor <cgf@redhat.com>

View File

@ -94,12 +94,10 @@ cygthread::simplestub (VOID *arg)
ExitThread (0); ExitThread (0);
} }
static NO_COPY muto *cygthread_protect;
/* Start things going. Called from dll_crt0_1. */ /* Start things going. Called from dll_crt0_1. */
void void
cygthread::init () cygthread::init ()
{ {
new_muto (cygthread_protect);
main_thread_id = GetCurrentThreadId (); main_thread_id = GetCurrentThreadId ();
} }
@ -129,30 +127,27 @@ cygthread::freerange ()
void * cygthread::operator void * cygthread::operator
new (size_t) new (size_t)
{ {
DWORD id; LONG is_avail;
cygthread *info; cygthread *info;
cygthread_protect->acquire ();
/* Search the threads array for an empty slot to use */ /* Search the threads array for an empty slot to use */
for (info = threads; info < threads + NTHREADS; info++) for (info = threads; info < threads + NTHREADS; info++)
if ((LONG) (id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, -1)) < 0) if ((is_avail = InterlockedExchange (&info->avail, -1)) < 0)
/* being considered */; /* in use */;
else if (id > 0) else if (is_avail > 0)
{ {
/* available */
#ifdef DEBUGGING #ifdef DEBUGGING
if (info->__name) 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) 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 #endif
goto out; goto out;
} }
else if (info->id)
InterlockedExchange ((LPLONG) &info->avail, 0); /* Not available yet */
else else
{ {
/* Available as soon as thread is created */ /* Uninitialized. Available as soon as thread is created */
info->h = CreateThread (&sec_none_nih, 0, cygthread::stub, info, info->h = CreateThread (&sec_none_nih, 0, cygthread::stub, info,
CREATE_SUSPENDED, &info->id); CREATE_SUSPENDED, &info->id);
goto out; goto out;
@ -160,15 +155,13 @@ new (size_t)
#ifdef DEBUGGING #ifdef DEBUGGING
char buf[1024]; 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"); api_fatal ("Overflowed cygwin thread pool");
#endif #endif
info = freerange (); /* exhausted thread pool */ info = freerange (); /* exhausted thread pool */
out: out:
InterlockedExchange ((LPLONG) &info->avail, 0);
cygthread_protect->release ();
return info; return info;
} }
@ -270,21 +263,21 @@ cygthread::terminate_thread ()
thread_sync = ev = h = NULL; thread_sync = ev = h = NULL;
__name = NULL; __name = NULL;
id = 0; id = 0;
(void) InterlockedExchange (&avail, 0); /* No longer initialized */
} }
/* Detach the cygthread from the current thread. Note that the /* Detach the cygthread from the current thread. Note that the
theory is that cygthreads are only associated with one thread. theory is that cygthreads are only associated with one thread.
So, there should be no problems with multiple threads doing waits So, there should be never be multiple threads doing waits
on the one cygthread. */ on the same cygthread. */
bool bool
cygthread::detach (HANDLE sigwait) cygthread::detach (HANDLE sigwait)
{ {
bool signalled = false; bool signalled = false;
if (avail) if (avail >= 0)
system_printf ("called detach on available thread %d?", avail); system_printf ("called detach but avail %d, thread %d?", avail, id);
else else
{ {
DWORD avail = id;
DWORD res; DWORD res;
if (!sigwait) if (!sigwait)
@ -304,18 +297,17 @@ cygthread::detach (HANDLE sigwait)
res = WaitForSingleObject (*this, INFINITE); res = WaitForSingleObject (*this, INFINITE);
else else
{ {
signalled = true;
terminate_thread (); terminate_thread ();
set_sig_errno (EINTR); /* caller should be dealing with return set_sig_errno (EINTR); /* caller should be dealing with return
values. */ values. */
avail = 0;
signalled = true;
} }
} }
thread_printf ("%s returns %d, id %p", sigwait ? "WFMO" : "WFSO", thread_printf ("%s returns %d, id %p", sigwait ? "WFMO" : "WFSO",
res, id); res, id);
if (!avail) if (signalled)
/* already handled */; /* already handled */;
else if (is_freerange) else if (is_freerange)
{ {
@ -325,8 +317,8 @@ cygthread::detach (HANDLE sigwait)
else else
{ {
ResetEvent (*this); ResetEvent (*this);
/* Mark the thread as available by setting avail to non-zero */ /* Mark the thread as available by setting avail to positive value */
(void) InterlockedExchange ((LPLONG) &this->avail, avail); (void) InterlockedExchange (&avail, 1);
} }
} }
return signalled; return signalled;

View File

@ -8,7 +8,7 @@ details. */
class cygthread class cygthread
{ {
DWORD avail; LONG avail; /* 1: available, 0: ininitialized, -1: not available */
DWORD id; DWORD id;
HANDLE h; HANDLE h;
HANDLE ev; HANDLE ev;