diff options
author | Christopher Faylor <me@cgf.cx> | 2002-10-22 20:16:31 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2002-10-22 20:16:31 +0000 |
commit | d525130f0403aff59eca72693d9a15648741e88e (patch) | |
tree | 16549d8075aa4ee8df6f5f6c64717b4218072640 /winsup/cygwin/cygthread.cc | |
parent | 329b9ead3ea5a48d452ce48538a4584835c70555 (diff) | |
download | newlib-d525130f0403aff59eca72693d9a15648741e88e.zip newlib-d525130f0403aff59eca72693d9a15648741e88e.tar.gz newlib-d525130f0403aff59eca72693d9a15648741e88e.tar.bz2 |
* cygthread.cc (cygthread::exiting): New variable.
(cygthread::initialized): Delete.
(cygthread::stub): Use exiting variable to determine when to exit.
(cygthread::runner): Delete.
(cygthread_protect): New variable.
(cygthread::init): Don't start runner thread. Initialize muto for list
protection.
(cygthread::freerange): Return pointer to cygthread.
(cygthread::operator new): Change logic to start threads on an as-needed basis.
(cygthread::detach): Don't zero id.
(cygthread::terminate): Don't kill any executing threads. Just set exiting
flag.
* cygthread.h (cygthread): Reflect above changes.
* dcrt0.cc (dll_crt0_1): Move cygthread initialization later.
* fork.cc (fork_child): Do fdtab fixup after dll fixup or (apparently) winsock
may allocate memory in dll load address.
Diffstat (limited to 'winsup/cygwin/cygthread.cc')
-rw-r--r-- | winsup/cygwin/cygthread.cc | 124 |
1 files changed, 33 insertions, 91 deletions
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 7143d70..70225f0 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -12,6 +12,7 @@ details. */ #include "exceptions.h" #include "security.h" #include "cygthread.h" +#include "sync.h" #undef CloseHandle @@ -19,7 +20,7 @@ static cygthread NO_COPY threads[9]; #define NTHREADS (sizeof (threads) / sizeof (threads[0])) DWORD NO_COPY cygthread::main_thread_id; -int NO_COPY cygthread::initialized; +bool NO_COPY cygthread::exiting; /* Initial stub called by cygthread constructor. Performs initial per-thread initialization and loops waiting for new thread functions @@ -48,7 +49,7 @@ cygthread::stub (VOID *arg) system_printf ("erroneous thread activation"); else { - if (!info->func || initialized < 0) + if (!info->func || exiting) ExitThread (0); /* Cygwin threads should not call ExitThread directly */ @@ -89,33 +90,12 @@ cygthread::simplestub (VOID *arg) ExitThread (0); } -/* This function runs in a secondary thread and starts up a bunch of - other suspended threads for use in the cygthread pool. */ -DWORD WINAPI -cygthread::runner (VOID *arg) -{ - for (unsigned i = 0; i < NTHREADS; i++) - if (!initialized) - threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub, - &threads[i], CREATE_SUSPENDED, - &threads[i].avail); - else - ExitThread (0); - - initialized ^= 1; - ExitThread (0); -} - -HANDLE NO_COPY runner_handle; -DWORD NO_COPY runner_tid; +static NO_COPY muto *cygthread_protect; /* Start things going. Called from dll_crt0_1. */ void cygthread::init () { - runner_handle = CreateThread (&sec_none_nih, 0, cygthread::runner, NULL, 0, - &runner_tid); - if (!runner_handle) - api_fatal ("can't start thread_runner, %E"); + new_muto (cygthread_protect); main_thread_id = GetCurrentThreadId (); } @@ -131,7 +111,7 @@ cygthread::is () return 0; } -void * +cygthread * cygthread::freerange () { cygthread *self = (cygthread *) calloc (1, sizeof (*self)); @@ -148,39 +128,36 @@ new (size_t) DWORD id; cygthread *info; - for (;;) - { - 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))) - { - info->id = id; + cygthread_protect->acquire (); + + /* Search the threads array for an empty slot to use */ + for (info = threads; info < threads + NTHREADS; info++) + if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0))) + { #ifdef DEBUGGING - if (info->__name) - api_fatal ("name not NULL? id %p, i %d", id, info - threads); + if (info->__name) + api_fatal ("name not NULL? id %p, i %d", id, info - threads); #endif - return info; - } - - if (was_initialized < 0) - ExitThread (0); + goto out; + } + else if (!info->id) + { + info->h = CreateThread (&sec_none_nih, 0, cygthread::stub, info, + CREATE_SUSPENDED, &info->id); + goto out; + } - if (!was_initialized) - Sleep (0); /* thread_runner is not finished yet. */ - else - { #ifdef DEBUGGING - char buf[1024]; - if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf))) - api_fatal ("Overflowed cygwin thread pool"); + char buf[1024]; + if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf))) + api_fatal ("Overflowed cygwin thread pool"); #endif - return freerange (); - } - } + + info = freerange (); /* exhausted thread pool */ + +out: + cygthread_protect->release (); + return info; } cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, @@ -200,9 +177,7 @@ cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, Sleep (0); } #endif - __name = name; /* Need to set after thread has woken up to - ensure that it won't be cleared by exiting - thread. */ + __name = name; if (!thread_sync) ResumeThread (h); else @@ -278,7 +253,6 @@ cygthread::detach () } else { - id = 0; ResetEvent (*this); /* Mark the thread as available by setting avail to non-zero */ (void) InterlockedExchange ((LPLONG) &this->avail, avail); @@ -289,37 +263,5 @@ cygthread::detach () void cygthread::terminate () { - /* Wow. All of this seems to be necessary or (on Windows 9x at least) the - process will sometimes deadlock if there are suspended threads. I assume - that something funky is happening like a suspended thread being created - while the process is exiting or something. In particular, it seems like - the WaitForSingleObjects are necessary since it appears that the - TerminateThread call may happen asynchronously, i.e., when TerminateThread - returns, the thread may not yet have terminated. */ - if (runner_handle && initialized >= 0) - { - /* Don't care about detaching (or attaching) threads now */ - if (cygwin_hmodule && !DisableThreadLibraryCalls (cygwin_hmodule)) - system_printf ("DisableThreadLibraryCalls (%p) failed, %E", - cygwin_hmodule); - initialized = -1; - (void) TerminateThread (runner_handle, 0); - (void) WaitForSingleObject (runner_handle, INFINITE); - (void) CloseHandle (runner_handle); - HANDLE hthreads[NTHREADS]; - int n = 0; - for (unsigned i = 0; i < NTHREADS; i++) - if (threads[i].h) - { - hthreads[n] = threads[i].h; - threads[i].h = NULL; - TerminateThread (hthreads[n++], 0); - } - if (n) - { - (void) WaitForMultipleObjects (n, hthreads, TRUE, INFINITE); - while (--n >= 0) - CloseHandle (hthreads[n]); - } - } + exiting = 1; } |