* 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>
* 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>

View File

@ -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,30 +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); /* Not available yet */
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,
CREATE_SUSPENDED, &info->id);
goto out;
@ -160,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;
}
@ -270,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 avail = id;
DWORD res;
if (!sigwait)
@ -304,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. */
avail = 0;
signalled = true;
}
}
thread_printf ("%s returns %d, id %p", sigwait ? "WFMO" : "WFSO",
res, id);
if (!avail)
if (signalled)
/* already handled */;
else if (is_freerange)
{
@ -325,8 +317,8 @@ cygthread::detach (HANDLE sigwait)
else
{
ResetEvent (*this);
/* Mark the thread as available by setting avail to non-zero */
(void) InterlockedExchange ((LPLONG) &this->avail, avail);
/* Mark the thread as available by setting avail to positive value */
(void) InterlockedExchange (&avail, 1);
}
}
return signalled;

View File

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