* cygthread.h (cygthread::terminate): Declare new function.

(cygthread::initialized): Change to 'int'.
* cygthread.cc (cygthread::stub): Exit thread if initialized < 0.
(cygthread::new): Ditto.
(cygthread::runner): Ditto.  Set initialized using xor to preserve sign.
(cygthread::terminate): New function.
* dcrt0.cc (do_exit): Call cygthread::terminate.
This commit is contained in:
Christopher Faylor
2002-09-29 02:19:35 +00:00
parent fc5dae1cca
commit aea1f301fc
5 changed files with 123 additions and 87 deletions

View File

@ -19,7 +19,7 @@ static cygthread NO_COPY threads[6];
#define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id;
bool NO_COPY cygthread::initialized;
int NO_COPY cygthread::initialized;
/* Initial stub called by cygthread constructor. Performs initial
per-thread initialization and loops waiting for new thread functions
@ -68,7 +68,10 @@ cygthread::stub (VOID *arg)
#endif
SetEvent (info->ev);
info->__name = NULL;
SuspendThread (info->h);
if (initialized < 0)
ExitThread (0);
else
SuspendThread (info->h);
}
}
@ -78,9 +81,14 @@ DWORD WINAPI
cygthread::runner (VOID *arg)
{
for (unsigned i = 0; i < NTHREADS; i++)
threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub, &threads[i],
CREATE_SUSPENDED, &threads[i].avail);
cygthread::initialized = true;
if (!initialized)
threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub,
&threads[i], CREATE_SUSPENDED,
&threads[i].avail);
else
return 0;
initialized ^= 1;
return 0;
}
@ -127,7 +135,10 @@ new (size_t)
for (;;)
{
bool was_initialized = initialized;
int was_initialized = initialized;
if (was_initialized < 0)
ExitThread (0);
/* Search the threads array for an empty slot to use */
for (info = threads + NTHREADS - 1; info >= threads; info--)
if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0)))
@ -140,6 +151,9 @@ new (size_t)
return info;
}
if (was_initialized < 0)
ExitThread (0);
if (!was_initialized)
Sleep (0); /* thread_runner is not finished yet. */
else
@ -259,3 +273,12 @@ cygthread::detach ()
}
}
}
void
cygthread::terminate ()
{
initialized = -1;
for (cygthread *info = threads + NTHREADS - 1; info >= threads; info--)
if (!(DWORD) InterlockedExchange ((LPLONG) &info->avail, 0) && info->id)
SetEvent (info->ev);
}