4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-21 16:26:12 +08:00

* 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.
This commit is contained in:
Christopher Faylor 2002-10-22 20:16:31 +00:00
parent 329b9ead3e
commit d525130f04
5 changed files with 64 additions and 104 deletions

View File

@ -1,3 +1,24 @@
2002-10-22 Christopher Faylor <cgf@redhat.com>
* 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.
2002-10-22 Pierre Humblet <pierre.humblet@ieee.org> 2002-10-22 Pierre Humblet <pierre.humblet@ieee.org>
* sec_helper.cc (cygsid::get_id): If the sid matches a sid stored in * sec_helper.cc (cygsid::get_id): If the sid matches a sid stored in

View File

@ -12,6 +12,7 @@ details. */
#include "exceptions.h" #include "exceptions.h"
#include "security.h" #include "security.h"
#include "cygthread.h" #include "cygthread.h"
#include "sync.h"
#undef CloseHandle #undef CloseHandle
@ -19,7 +20,7 @@ static cygthread NO_COPY threads[9];
#define NTHREADS (sizeof (threads) / sizeof (threads[0])) #define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id; 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 /* Initial stub called by cygthread constructor. Performs initial
per-thread initialization and loops waiting for new thread functions per-thread initialization and loops waiting for new thread functions
@ -48,7 +49,7 @@ cygthread::stub (VOID *arg)
system_printf ("erroneous thread activation"); system_printf ("erroneous thread activation");
else else
{ {
if (!info->func || initialized < 0) if (!info->func || exiting)
ExitThread (0); ExitThread (0);
/* Cygwin threads should not call ExitThread directly */ /* Cygwin threads should not call ExitThread directly */
@ -89,33 +90,12 @@ cygthread::simplestub (VOID *arg)
ExitThread (0); ExitThread (0);
} }
/* This function runs in a secondary thread and starts up a bunch of static NO_COPY muto *cygthread_protect;
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;
/* Start things going. Called from dll_crt0_1. */ /* Start things going. Called from dll_crt0_1. */
void void
cygthread::init () cygthread::init ()
{ {
runner_handle = CreateThread (&sec_none_nih, 0, cygthread::runner, NULL, 0, new_muto (cygthread_protect);
&runner_tid);
if (!runner_handle)
api_fatal ("can't start thread_runner, %E");
main_thread_id = GetCurrentThreadId (); main_thread_id = GetCurrentThreadId ();
} }
@ -131,7 +111,7 @@ cygthread::is ()
return 0; return 0;
} }
void * cygthread *
cygthread::freerange () cygthread::freerange ()
{ {
cygthread *self = (cygthread *) calloc (1, sizeof (*self)); cygthread *self = (cygthread *) calloc (1, sizeof (*self));
@ -148,39 +128,36 @@ new (size_t)
DWORD id; DWORD id;
cygthread *info; cygthread *info;
for (;;) cygthread_protect->acquire ();
{
int was_initialized = initialized;
if (was_initialized < 0)
ExitThread (0);
/* Search the threads array for an empty slot to use */ /* Search the threads array for an empty slot to use */
for (info = threads + NTHREADS - 1; info >= threads; info--) for (info = threads; info < threads + NTHREADS; info++)
if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0))) if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0)))
{ {
info->id = id;
#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", id, info - threads);
#endif #endif
return info; 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 < 0)
ExitThread (0);
if (!was_initialized)
Sleep (0); /* thread_runner is not finished yet. */
else
{
#ifdef DEBUGGING #ifdef DEBUGGING
char buf[1024]; char buf[1024];
if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf))) if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf)))
api_fatal ("Overflowed cygwin thread pool"); api_fatal ("Overflowed cygwin thread pool");
#endif #endif
return freerange ();
} info = freerange (); /* exhausted thread pool */
}
out:
cygthread_protect->release ();
return info;
} }
cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param,
@ -200,9 +177,7 @@ cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param,
Sleep (0); Sleep (0);
} }
#endif #endif
__name = name; /* Need to set after thread has woken up to __name = name;
ensure that it won't be cleared by exiting
thread. */
if (!thread_sync) if (!thread_sync)
ResumeThread (h); ResumeThread (h);
else else
@ -278,7 +253,6 @@ cygthread::detach ()
} }
else else
{ {
id = 0;
ResetEvent (*this); ResetEvent (*this);
/* Mark the thread as available by setting avail to non-zero */ /* Mark the thread as available by setting avail to non-zero */
(void) InterlockedExchange ((LPLONG) &this->avail, avail); (void) InterlockedExchange ((LPLONG) &this->avail, avail);
@ -289,37 +263,5 @@ cygthread::detach ()
void void
cygthread::terminate () cygthread::terminate ()
{ {
/* Wow. All of this seems to be necessary or (on Windows 9x at least) the exiting = 1;
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]);
}
}
} }

View File

@ -18,9 +18,7 @@ class cygthread
VOID *arg; VOID *arg;
bool is_freerange; bool is_freerange;
static DWORD main_thread_id; static DWORD main_thread_id;
static int initialized; static bool exiting;
static DWORD WINAPI runner (VOID *);
static DWORD WINAPI free_runner (VOID *);
static DWORD WINAPI stub (VOID *); static DWORD WINAPI stub (VOID *);
static DWORD WINAPI simplestub (VOID *); static DWORD WINAPI simplestub (VOID *);
public: public:
@ -32,7 +30,7 @@ class cygthread
operator HANDLE (); operator HANDLE ();
static bool is (); static bool is ();
void * operator new (size_t); void * operator new (size_t);
static void * freerange (); static cygthread *freerange ();
void exit_thread (); void exit_thread ();
static void terminate (); static void terminate ();
bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);} bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);}

View File

@ -573,10 +573,7 @@ dll_crt0_1 ()
char **envp = NULL; char **envp = NULL;
if (!child_proc_info) if (!child_proc_info)
{ memory_init ();
cygthread::init ();
memory_init ();
}
else else
{ {
bool close_ppid_handle = false; bool close_ppid_handle = false;
@ -587,7 +584,6 @@ dll_crt0_1 ()
alloc_stack (fork_info); alloc_stack (fork_info);
cygheap_fixup_in_child (0); cygheap_fixup_in_child (0);
memory_init (); memory_init ();
cygthread::init ();
set_myself (mypid); set_myself (mypid);
close_ppid_handle = !!child_proc_info->pppid_handle; close_ppid_handle = !!child_proc_info->pppid_handle;
break; break;
@ -600,7 +596,6 @@ dll_crt0_1 ()
hexec_proc = spawn_info->hexec_proc; hexec_proc = spawn_info->hexec_proc;
around: around:
HANDLE h; HANDLE h;
cygthread::init ();
cygheap_fixup_in_child (1); cygheap_fixup_in_child (1);
memory_init (); memory_init ();
if (!spawn_info->moreinfo->myself_pinfo || if (!spawn_info->moreinfo->myself_pinfo ||
@ -621,7 +616,6 @@ dll_crt0_1 ()
old_title = strcpy (title_buf, spawn_info->moreinfo->old_title); old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
cfree (spawn_info->moreinfo->old_title); cfree (spawn_info->moreinfo->old_title);
} }
// cygthread::init ();
break; break;
} }
if (close_hexec_proc) if (close_hexec_proc)
@ -632,6 +626,7 @@ dll_crt0_1 ()
ProtectHandle (hMainProc); ProtectHandle (hMainProc);
ProtectHandle (hMainThread); ProtectHandle (hMainThread);
cygthread::init ();
/* Initialize debug muto, if DLL is built with --enable-debugging. /* Initialize debug muto, if DLL is built with --enable-debugging.
Need to do this before any helper threads start. */ Need to do this before any helper threads start. */

View File

@ -281,8 +281,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
if (fixup_mmaps_after_fork (hParent)) if (fixup_mmaps_after_fork (hParent))
api_fatal ("recreate_mmaps_after_fork_failed"); api_fatal ("recreate_mmaps_after_fork_failed");
cygheap->fdtab.fixup_after_fork (hParent);
ProtectHandleINH (hParent);
MALLOC_CHECK; MALLOC_CHECK;
@ -291,10 +289,16 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
that we're done, and wait for the parent to fill in the. that we're done, and wait for the parent to fill in the.
loaded dlls' data/bss. */ loaded dlls' data/bss. */
if (!load_dlls) if (!load_dlls)
sync_with_parent ("performed fork fixup.", FALSE); {
cygheap->fdtab.fixup_after_fork (hParent);
ProtectHandleINH (hParent);
sync_with_parent ("performed fork fixup.", FALSE);
}
else else
{ {
dlls.load_after_fork (hParent, first_dll); dlls.load_after_fork (hParent, first_dll);
cygheap->fdtab.fixup_after_fork (hParent);
ProtectHandleINH (hParent);
sync_with_parent ("loaded dlls", TRUE); sync_with_parent ("loaded dlls", TRUE);
} }