* 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:
parent
5557a0dace
commit
9dbe3289ee
@ -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>
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user