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:
parent
329b9ead3e
commit
d525130f04
@ -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
|
||||||
|
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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);}
|
||||||
|
@ -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. */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user