Rename _threadinfo to _cygtls, throughout.

* cygtls.h (_cygtls::call_signal_handler): Rename from call_signal_handler_now.
(_cygtls::push): Make second argument mandatory.
(_cygtls::fixup_after_fork): Declare new function.
(_cygtls::lock): Ditto.
* cygtls.cc (_cygtls::fixup_after_fork): Define new function.
* dcrt0.cc (cygwin_finished_initializing): Define as bool.
(alloc_stack): Use _tlstop rather than arbitrary variable in probably vain
attempt to avoid strange fork problem on CTRL-C.
(dll_crt0_0): Remove obsolete winpids::init call.
* dll_init.cc (dll_dllcrt0): Detect forkee condition as equivalent to
initializing.
* winsup.h (cygwin_finished_initializing): Declare as bool.
* exceptions.cc (handle_exceptions): Rely on cygwin_finished_initializing to
determine how to handle exception during process startup.
(_cygtls::call_signal_handler): Rename from call_signal_handler_now.
(_cygtls::interrupt_now): Fill in second argument to push.
(signal_fixup_after_fork): Eliminate.
(setup_handler): Initialize locked to avoid potential inappropriate unlock.
Resume thread if it has acquired the stack lock.
(ctrl_c_handler): Just exit if ctrl-c is hit before cygiwn has finished
initializing.
* fork.cc (sync_with_child): Don't call abort since it can cause exit
deadlocks.
(sync_with_child): Change debugging output slightly.
(fork_child): Set cygwin_finished_initializing here.  Call _cygtls fork fixup
and explicitly call sigproc_init.
(fork_parent): Release malloc lock on fork failure.
(vfork): Call signal handler via _my_tls.
* sigproc.cc (sig_send): Ditto.
* syscalls.cc (readv): Ditto.
* termios.cc (tcsetattr): Ditto.
* wait.cc (wait4): Ditto.
* signal.cc (nanosleep): Ditto.
(abort): Ditto.
(kill_pgrp): Avoid killing self if exiting.
* sync.cc (muto::acquire): Remove (temporarily?) ill-advised exiting_thread
check.
* gendef (_sigfe): Be more agressive in protecting stack pointer from other
access by signal thread.
(_cygtls::locked): Define new function.
(_sigbe): Ditto.
(_cygtls::pop): Protect edx.
(_cygtls::lock): Use guaranteed method to set eax to 1.
(longjmp): Aggressively protect signal stack.
* miscfuncs.cc (low_priority_sleep): Reduce "sleep time" for secs == 0.
* pinfo.cc (winpids::set): Counterintuitively use malloc's lock to protect
simultaneous access to the pids list since there are pathological conditions
which can cause malloc to call winpid.
(winpids::init): Eliminate.
* pinfo.h (winpids::cs): Eliminate declaration.
* pinfo.h (winpids::init): Eliminate definition.
This commit is contained in:
Christopher Faylor 2004-02-12 03:01:58 +00:00
parent 2bc01fb1f5
commit e431827c7c
23 changed files with 287 additions and 209 deletions

View File

@ -1,3 +1,60 @@
2004-02-11 Christopher Faylor <cgf@redhat.com>
Rename _threadinfo to _cygtls, throughout.
* cygtls.h (_cygtls::call_signal_handler): Rename from
call_signal_handler_now.
(_cygtls::push): Make second argument mandatory.
(_cygtls::fixup_after_fork): Declare new function.
(_cygtls::lock): Ditto.
* cygtls.cc (_cygtls::fixup_after_fork): Define new function.
* dcrt0.cc (cygwin_finished_initializing): Define as bool.
(alloc_stack): Use _tlstop rather than arbitrary variable in probably
vain attempt to avoid strange fork problem on CTRL-C.
(dll_crt0_0): Remove obsolete winpids::init call.
* dll_init.cc (dll_dllcrt0): Detect forkee condition as equivalent to
initializing.
* winsup.h (cygwin_finished_initializing): Declare as bool.
* exceptions.cc (handle_exceptions): Rely on
cygwin_finished_initializing to determine how to handle exception
during process startup.
(_cygtls::call_signal_handler): Rename from call_signal_handler_now.
(_cygtls::interrupt_now): Fill in second argument to push.
(signal_fixup_after_fork): Eliminate.
(setup_handler): Initialize locked to avoid potential inappropriate
unlock. Resume thread if it has acquired the stack lock.
(ctrl_c_handler): Just exit if ctrl-c is hit before cygiwn has finished
initializing.
* fork.cc (sync_with_child): Don't call abort since it can cause exit
deadlocks.
(sync_with_child): Change debugging output slightly.
(fork_child): Set cygwin_finished_initializing here. Call _cygtls fork
fixup and explicitly call sigproc_init.
(fork_parent): Release malloc lock on fork failure.
(vfork): Call signal handler via _my_tls.
* sigproc.cc (sig_send): Ditto.
* syscalls.cc (readv): Ditto.
* termios.cc (tcsetattr): Ditto.
* wait.cc (wait4): Ditto.
* signal.cc (nanosleep): Ditto.
(abort): Ditto.
(kill_pgrp): Avoid killing self if exiting.
* sync.cc (muto::acquire): Remove (temporarily?) ill-advised
exiting_thread check.
* gendef (_sigfe): Be more agressive in protecting stack pointer from
other access by signal thread.
(_cygtls::locked): Define new function.
(_sigbe): Ditto.
(_cygtls::pop): Protect edx.
(_cygtls::lock): Use guaranteed method to set eax to 1.
(longjmp): Aggressively protect signal stack.
* miscfuncs.cc (low_priority_sleep): Reduce "sleep time" for secs == 0.
* pinfo.cc (winpids::set): Counterintuitively use malloc's lock to
protect simultaneous access to the pids list since there are
pathological conditions which can cause malloc to call winpid.
(winpids::init): Eliminate.
* pinfo.h (winpids::cs): Eliminate declaration.
* pinfo.h (winpids::init): Eliminate definition.
2004-02-11 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_nt_object_attribute): Fix error handling.

View File

@ -266,7 +266,7 @@ struct init_cygheap
#ifdef NEWVFORK
fhandler_tty_slave *ctty_on_hold;
#endif
struct _threadinfo **threadlist;
struct _cygtls **threadlist;
size_t sthreads;
int open_fhs;
void close_ctty ();

View File

@ -20,6 +20,7 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "cygthread.h"
#include "pinfo.h"
#include "sigproc.h"
class sentry
@ -32,7 +33,7 @@ public:
sentry () {destroy = 0;}
sentry (DWORD wait) {destroy = lock->acquire (wait);}
~sentry () {if (destroy) lock->release ();}
friend void _threadinfo::init ();
friend void _cygtls::init ();
};
muto NO_COPY *sentry::lock;
@ -42,27 +43,27 @@ static size_t NO_COPY nthreads;
#define THREADLIST_CHUNK 256
void
_threadinfo::init ()
_cygtls::init ()
{
if (cygheap->threadlist)
memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0]));
else
{
cygheap->sthreads = THREADLIST_CHUNK;
cygheap->threadlist = (_threadinfo **) ccalloc (HEAP_TLS, cygheap->sthreads,
cygheap->threadlist = (_cygtls **) ccalloc (HEAP_TLS, cygheap->sthreads,
sizeof (cygheap->threadlist[0]));
}
new_muto1 (sentry::lock, sentry_lock);
}
void
_threadinfo::set_state (bool is_exception)
_cygtls::set_state (bool is_exception)
{
initialized = CYGTLS_INITIALIZED + is_exception;
}
void
_threadinfo::reset_exception ()
_cygtls::reset_exception ()
{
if (initialized == CYGTLS_EXCEPTION)
{
@ -75,14 +76,14 @@ _threadinfo::reset_exception ()
/* Two calls to get the stack right... */
void
_threadinfo::call (DWORD (*func) (void *, void *), void *arg)
_cygtls::call (DWORD (*func) (void *, void *), void *arg)
{
char buf[CYGTLS_PADSIZE];
call2 (func, arg, buf);
}
void
_threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
_cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
{
exception_list except_entry;
/* Initialize this thread's ability to respond to things like
@ -95,7 +96,7 @@ _threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
}
void
_threadinfo::init_thread (void *x, DWORD (*func) (void *, void *))
_cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
{
if (x)
{
@ -125,7 +126,7 @@ _threadinfo::init_thread (void *x, DWORD (*func) (void *, void *))
sentry here (INFINITE);
if (nthreads >= cygheap->sthreads)
{
cygheap->threadlist = (_threadinfo **)
cygheap->threadlist = (_cygtls **)
crealloc (cygheap->threadlist, (cygheap->sthreads += THREADLIST_CHUNK)
* sizeof (cygheap->threadlist[0]));
memset (cygheap->threadlist + nthreads, 0, THREADLIST_CHUNK * sizeof (cygheap->threadlist[0]));
@ -135,7 +136,22 @@ _threadinfo::init_thread (void *x, DWORD (*func) (void *, void *))
}
void
_threadinfo::remove (DWORD wait)
_cygtls::fixup_after_fork ()
{
if (sig)
{
set_signal_mask (oldmask);
sig = 0;
}
stacklock = 0;
stackptr = stack + 1; // FIXME?
#ifdef DEBUGGING
memset (stackptr, 0, sizeof (stack) - sizeof (stack[0]));
#endif
}
void
_cygtls::remove (DWORD wait)
{
debug_printf ("wait %p\n", wait);
sentry here (wait);
@ -153,7 +169,7 @@ _threadinfo::remove (DWORD wait)
}
void
_threadinfo::push (__stack_t addr, bool exception)
_cygtls::push (__stack_t addr, bool exception)
{
if (exception)
lock ();
@ -166,13 +182,13 @@ _threadinfo::push (__stack_t addr, bool exception)
#define BAD_IX ((size_t) -1)
static size_t NO_COPY threadlist_ix = BAD_IX;
_threadinfo *
_threadinfo::find_tls (int sig)
_cygtls *
_cygtls::find_tls (int sig)
{
debug_printf ("sig %d\n", sig);
sentry here (INFINITE);
__asm__ volatile (".equ _threadlist_exception_return,.");
_threadinfo *res = NULL;
_cygtls *res = NULL;
for (threadlist_ix = 0; threadlist_ix < nthreads; threadlist_ix++)
if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig))
{
@ -184,7 +200,7 @@ _threadinfo::find_tls (int sig)
}
void
_threadinfo::set_siginfo (sigpacket *pack)
_cygtls::set_siginfo (sigpacket *pack)
{
infodata = pack->si;
}
@ -222,7 +238,7 @@ handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *, void *
}
void
_threadinfo::init_threadlist_exceptions (exception_list *el)
_cygtls::init_threadlist_exceptions (exception_list *el)
{
extern void init_exception_handler (exception_list *, exception_handler *);
init_exception_handler (el, handle_threadlist_exception);

View File

@ -90,7 +90,7 @@ struct _local_storage
'gentls_offsets' (<<-- start parsing here). */
typedef __uint32_t __stack_t;
struct _threadinfo
struct _cygtls
{
void (*func) /*gentls_offsets*/(int)/*gentls_offsets*/;
int saved_errno;
@ -108,7 +108,7 @@ struct _threadinfo
struct pthread *tid;
struct _reent local_clib;
struct _local_storage locals;
struct _threadinfo *prev, *next;
struct _cygtls *prev, *next;
__stack_t *stackptr;
int sig;
unsigned stacklock;
@ -121,9 +121,9 @@ struct _threadinfo
void init_thread (void *, DWORD (*) (void *, void *));
static void call (DWORD (*) (void *, void *), void *);
static void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3)));
static struct _threadinfo *find_tls (int sig);
static struct _cygtls *find_tls (int sig);
void remove (DWORD);
void push (__stack_t, bool = false) __attribute__ ((regparm (3)));
void push (__stack_t, bool) __attribute__ ((regparm (3)));
__stack_t pop () __attribute__ ((regparm (1)));
bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;}
void set_state (bool);
@ -138,16 +138,19 @@ struct _threadinfo
void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3)));
void set_threadkill () {threadkill = true;}
void reset_threadkill () {threadkill = false;}
int lock () __attribute__ ((regparm (1)));
int call_signal_handler () __attribute__ ((regparm (1)));
void fixup_after_fork () __attribute__ ((regparm (1)));
void lock () __attribute__ ((regparm (1)));
void unlock () __attribute__ ((regparm (1)));
bool locked () __attribute__ ((regparm (1)));
/*gentls_offsets*/
};
#pragma pack(pop)
extern char *_tlsbase __asm__ ("%fs:4");
extern char *_tlstop __asm__ ("%fs:8");
#define _my_tls (((_threadinfo *) _tlsbase)[-1])
extern _threadinfo *_main_tls;
#define _my_tls (((_cygtls *) _tlsbase)[-1])
extern _cygtls *_main_tls;
#define __getreent() (&_my_tls.local_clib)

View File

@ -72,9 +72,9 @@ char NO_COPY **envp;
extern "C" void __sinit (_reent *);
_threadinfo NO_COPY *_main_tls;
_cygtls NO_COPY *_main_tls;
int cygwin_finished_initializing;
bool NO_COPY cygwin_finished_initializing;
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
This is subtracted from the signal number prior to shifting the bit.
@ -513,18 +513,16 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
static void
alloc_stack (child_info_fork *ci)
{
/* FIXME: adding 16384 seems to avoid a stack copy problem during
fork on Win95, but I don't know exactly why yet. DJ */
volatile char b[ci->stacksize + 16384];
if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
if (!VirtualQuery ((LPCVOID) _tlstop, &sm, sizeof sm))
api_fatal ("fork: couldn't get stack info, %E");
if (sm.AllocationBase == ci->stacktop)
ci->stacksize = 0;
else
alloc_stack_hard_way (ci, b + sizeof (b) - 1);
{
ci->stacksize = 0;
return;
}
alloc_stack_hard_way (ci, b + sizeof (b) - 1);
return;
}
@ -662,7 +660,6 @@ dll_crt0_0 ()
}
device::init ();
winpids::init ();
do_global_ctors (&__CTOR_LIST__, 1);
cygthread::init ();
@ -718,7 +715,7 @@ dll_crt0_0 ()
CloseHandle (child_proc_info->pppid_handle);
}
_threadinfo::init ();
_cygtls::init ();
/* Initialize events */
events_init ();
@ -873,7 +870,7 @@ dll_crt0_1 (char *)
set_console_title (cp);
}
cygwin_finished_initializing = 1;
cygwin_finished_initializing = true;
/* Call init of loaded dlls. */
dlls.init ();

View File

@ -371,7 +371,7 @@ dll_dllcrt0 (HMODULE h, per_process *p)
initializing, then the DLL must be a cygwin-aware DLL
that was explicitly linked into the program rather than
a dlopened DLL. */
if (!cygwin_finished_initializing)
if (!in_forkee && !cygwin_finished_initializing)
type = DLL_LINK;
else
{
@ -387,7 +387,7 @@ dll_dllcrt0 (HMODULE h, per_process *p)
initialize the DLL. If we haven't finished initializing,
it may not be safe to call the dll's "main" since not
all of cygwin's internal structures may have been set up. */
if (!d || (cygwin_finished_initializing && !d->init ()))
if (!d || ((in_forkee || cygwin_finished_initializing) && !d->init ()))
return -1;
return (DWORD) d;

View File

@ -519,7 +519,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
break;
}
if (!myself->progname[0]
if (!cygwin_finished_initializing
|| GetCurrentThreadId () == sigtid
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
@ -692,10 +692,10 @@ interruptible (DWORD pc)
return res;
}
void __stdcall
_threadinfo::interrupt_setup (int sig, void *handler,
_cygtls::interrupt_setup (int sig, void *handler,
struct sigaction& siga)
{
push ((__stack_t) sigdelayed);
push ((__stack_t) sigdelayed, false);
oldmask = myself->getsigmask ();
newmask = oldmask | siga.sa_mask | SIGTOMASK (sig);
sa_flags = siga.sa_flags;
@ -717,28 +717,16 @@ _threadinfo::interrupt_setup (int sig, void *handler,
}
bool
_threadinfo::interrupt_now (CONTEXT *ctx, int sig, void *handler,
_cygtls::interrupt_now (CONTEXT *ctx, int sig, void *handler,
struct sigaction& siga)
{
push ((__stack_t) ctx->Eip);
push ((__stack_t) ctx->Eip, false);
interrupt_setup (sig, handler, siga);
ctx->Eip = pop ();
SetThreadContext (*this, ctx); /* Restart the thread in a new location */
return 1;
}
void __stdcall
signal_fixup_after_fork ()
{
if (_my_tls.sig)
{
_my_tls.sig = 0;
_my_tls.stackptr = _my_tls.stack + 1; // FIXME?
set_signal_mask (_my_tls.oldmask);
}
sigproc_init ();
}
extern "C" void __stdcall
set_sig_errno (int e)
{
@ -747,13 +735,14 @@ set_sig_errno (int e)
// sigproc_printf ("errno %d", e);
}
static int setup_handler (int, void *, struct sigaction&, _threadinfo *tls)
static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
__attribute__((regparm(3)));
static int
setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
{
CONTEXT cx;
bool interrupted = false;
bool locked = false;
if (tls->sig)
{
@ -762,12 +751,11 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
goto out;
}
int locked;
for (int i = 0; i < CALL_HANDLER_RETRY; i++)
{
locked = tls->lock ();
__stack_t *retaddr_on_stack = tls->stackptr - 1;
if (retaddr_on_stack >= tls->stack)
tls->lock ();
locked = true;
if (tls->stackptr > tls->stack)
{
tls->reset_exception ();
tls->interrupt_setup (sig, handler, siga);
@ -776,14 +764,14 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
break;
}
tls->unlock ();
locked = false;
DWORD res;
HANDLE hth = (HANDLE) *tls;
/* Suspend the thread which will receive the signal. But first ensure that
this thread doesn't have any mutos. (FIXME: Someday we should just grab
all of the mutos rather than checking for them)
For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
are valid.
/* Suspend the thread which will receive the signal.
For Windows 95, we also have to ensure that the addresses returned by
GetThreadContext are valid.
If one of these conditions is not true we loop for a fixed number of times
since we don't want to stall the signal handler. FIXME: Will this result in
noticeable delays?
@ -799,31 +787,25 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
sigproc_printf ("suspending mainthread PC %p", cx.Eip);
#endif
res = SuspendThread (hth);
/* Just release the lock now since we hav suspended the main thread and it
definitely can't be grabbing it now. This will have to change, of course,
if/when we can send signals to other than the main thread. */
/* Just set pending if thread is already suspended */
if (res)
{
(void) ResumeThread (hth);
break;
}
// FIXME - add check for reentering of DLL here
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
system_printf ("couldn't get context of main thread, %E");
else if (interruptible (cx.Eip))
interrupted = tls->interrupt_now (&cx, sig, handler, siga);
if (!tls->locked ())
{
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
system_printf ("couldn't get context of main thread, %E");
else if (interruptible (cx.Eip))
interrupted = tls->interrupt_now (&cx, sig, handler, siga);
}
res = ResumeThread (hth);
if (interrupted)
break;
tls->unlock ();
locked = false;
sigproc_printf ("couldn't interrupt. trying again.");
low_priority_sleep (0);
}
@ -845,6 +827,10 @@ static BOOL WINAPI
ctrl_c_handler (DWORD type)
{
static bool saw_close;
if (!cygwin_finished_initializing)
ExitProcess (STATUS_CONTROL_C_EXIT);
_my_tls.remove (INFINITE);
/* Return FALSE to prevent an "End task" dialog box from appearing
@ -977,7 +963,7 @@ sigpacket::process ()
/* nothing to do */;
else if (tls && sigismember (&tls->sigwait_mask, si.si_signo))
insigwait_mask = true;
else if (!tls && (tls = _threadinfo::find_tls (si.si_signo)))
else if (!tls && (tls = _cygtls::find_tls (si.si_signo)))
insigwait_mask = true;
else if (!(masked = sigismember (mask, si.si_signo)) && tls)
masked = sigismember (&tls->sigmask, si.si_signo);
@ -1153,36 +1139,36 @@ events_terminate (void)
exit_already = 1;
}
extern "C" {
int __stdcall
call_signal_handler_now ()
int
_cygtls::call_signal_handler ()
{
int sa_flags = 0;
while (_my_tls.sig && _my_tls.stackptr > _my_tls.stack)
int this_sa_flags = 0;
/* Call signal handler. No need to set stacklock since sig effectively
implies that. */
while (sig)
{
sa_flags = _my_tls.sa_flags;
int sig = _my_tls.sig;
void (*sigfunc) (int) = _my_tls.func;
this_sa_flags = sa_flags;
int thissig = sig;
void (*sigfunc) (int) = func;
(void) _my_tls.pop ();
(void) pop ();
reset_signal_arrived ();
sigset_t oldmask = _my_tls.oldmask;
int this_errno = _my_tls.saved_errno;
set_process_mask (_my_tls.newmask);
_my_tls.sig = 0;
sigfunc (sig);
sigset_t oldmask = oldmask;
int this_errno = saved_errno;
set_process_mask (newmask);
sig = 0;
sigfunc (thissig);
set_process_mask (oldmask);
if (this_errno >= 0)
set_errno (this_errno);
}
return sa_flags & SA_RESTART;
return this_sa_flags & SA_RESTART;
}
void __stdcall
extern "C" void __stdcall
reset_signal_arrived ()
{
(void) ResetEvent (signal_arrived);
sigproc_printf ("reset signal_arrived");
}
}

View File

@ -167,11 +167,11 @@ sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
*/
if (errcode != STATUS_CONTROL_C_EXIT)
{
system_printf ("child %u(%p) died before initialization with status code %p",
cygwin_pid (pi.dwProcessId), pi.hProcess, errcode);
system_printf ("*** child state %s", s);
system_printf ("child %u(%p) died before initialization with status code %p",
cygwin_pid (pi.dwProcessId), pi.hProcess, errcode);
system_printf ("*** child state %s", s);
#ifdef DEBUGGING
abort ();
try_to_debug ();
#endif
}
set_errno (EAGAIN);
@ -212,13 +212,13 @@ sync_with_parent (const char *s, bool hang_self)
switch (psync_rc)
{
case WAIT_TIMEOUT:
api_fatal ("WFSO timed out for %s", s);
api_fatal ("WFSO timed out %s", s);
break;
case WAIT_FAILED:
if (GetLastError () == ERROR_INVALID_HANDLE &&
WaitForSingleObject (fork_info->forker_finished, 1) != WAIT_FAILED)
break;
api_fatal ("WFSO failed for %s, fork_finished %p, %E", s,
api_fatal ("WFSO failed %s, fork_finished %p, %E", s,
fork_info->forker_finished);
break;
default:
@ -243,6 +243,17 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
first_dll, load_dlls);
/* If we've played with the stack, stacksize != 0. That means that
fork() was invoked from other than the main thread. Make sure that
the threadinfo information is properly set up. */
if (!fork_info->stacksize)
{
_main_tls = &_my_tls;
_main_tls->init_thread (NULL, NULL);
_main_tls->local_clib = *_impure_ptr;
_impure_ptr = &_main_tls->local_clib;
}
#ifdef DEBUGGING
char c;
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
@ -257,18 +268,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
}
#endif
/* If we've played with the stack, stacksize != 0. That means that
fork() was invoked from other than the main thread. Make sure that
when the "main" thread exits it calls do_exit, like a normal process.
Exit with a status code of 0. */
if (fork_info->stacksize)
{
_main_tls = &_my_tls;
_main_tls->init_thread (NULL, NULL);
_main_tls->local_clib = *_impure_ptr;
_impure_ptr = &_main_tls->local_clib;
}
set_file_api_mode (current_codepage);
MALLOC_CHECK;
@ -307,7 +306,8 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
#endif
pinfo_fixup_after_fork ();
signal_fixup_after_fork ();
_my_tls.fixup_after_fork ();
sigproc_init ();
/* Set thread local stuff to zero. Under Windows 95/98 this is sometimes
non-zero, for some reason.
@ -320,6 +320,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
fixup_timers_after_fork ();
wait_for_sigthread ();
cygbench ("fork-child");
cygwin_finished_initializing = true;
return 0;
}
@ -458,7 +459,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
myself->progname, myself->progname, c_flags, &si, &pi);
__malloc_lock ();
bool locked = __malloc_lock ();
void *newheap;
newheap = cygheap_setup_for_child (&ch, cygheap->fdtab.need_fixup_before ());
rc = CreateProcess (myself->progname, /* image to run */
@ -483,6 +484,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
/* Restore impersonation */
cygheap->user.reimpersonate ();
cygheap_setup_for_child_cleanup (newheap, &ch, 0);
__malloc_unlock ();
return -1;
}
@ -573,6 +575,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
dll_bss_start, dll_bss_end, impure_beg, impure_end, NULL);
__malloc_unlock ();
locked = false;
MALLOC_CHECK;
if (!rc)
goto cleanup;
@ -622,6 +625,9 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
/* Common cleanup code for failure cases */
cleanup:
if (locked)
__malloc_unlock ();
/* Remember to de-allocate the fd table. */
if (pi.hProcess)
ForceCloseHandle1 (pi.hProcess, childhProc);
@ -725,7 +731,7 @@ vfork ()
debug_printf ("cygheap->ctty_on_hold %p, cygheap->open_fhs %d", cygheap->ctty_on_hold, cygheap->open_fhs);
int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
debug_printf ("%d = vfork()", res);
call_signal_handler_now (); // FIXME: racy
_my_tls.call_signal_handler (); // FIXME: racy
vf->tls = _my_tls;
return res;
}
@ -757,7 +763,7 @@ vfork ()
debug_printf ("exiting vfork, pid %d", pid);
sig_dispatch_pending ();
call_signal_handler_now (); // FIXME: racy
_my_tls.call_signal_handler (); // FIXME: racy
_my_tls = vf->tls;
return pid;
#endif

View File

@ -91,86 +91,99 @@ EOF
.stabs "_sigfe:F(0,1)",36,0,0,__sigbe
__sigfe:
pushl %ebx
pushl %edx
movl %fs:4,%edx
1: movl \$1,%eax
lock xchgl %eax,$tls::stacklock(%edx)
cmpl %eax,%eax
jz 2f
xorl %eax,%eax
call _low_priority_sleep
jmp 1b
2: movl \$4,%eax
xadd %eax,$tls::stackptr(%edx)
decl $tls::stacklock(%edx)
leal __sigbe,%edx
xchgl %edx,8(%esp)
movl %edx,(%eax)
popl %edx
1: movl %fs:4,%edx # location of bottom of stack
movl \$1,%eax # potential lock value
lock xchgl %eax,$tls::stacklock(%edx) # see if we can grab it
orl %eax,%eax # it will be zero
jz 2f # if so
xorl %eax,%eax # nope. It was not zero
call _low_priority_sleep # should be a short-time thing, so
jmp 1b # sleep and loop
2: movl \$4,%eax # have the lock, now increment the
xadd %eax,$tls::stackptr(%edx) # stack pointer and get pointer
leal __sigbe,%ebx # new place to return to
xchgl %ebx,12(%esp) # exchange with real return value
movl %ebx,(%eax) # store real return value on alt stack
decl $tls::stacklock(%edx) # remove lock
popl %edx # restore saved value
popl %ebx
ret
.global __sigbe
.stabs "_sigbe:F(0,1)",36,0,0,__sigbe
__sigbe:
pushl %edx
pushl %eax
movl %fs:4,%edx
1: movl \$1,%eax
lock xchgl %eax,$tls::stacklock(%edx)
cmpl %eax,%eax
jz 2f
xorl %eax,%eax
call _low_priority_sleep
jmp 1b
2: movl \$-4,%eax
xadd %eax,$tls::stackptr(%edx)
decl $tls::stacklock(%edx)
xchgl %edx,-4(%eax)
xchgl %edx,4(%esp)
pushl %ebx
pushl %edx # return here after cygwin syscall
pushl %eax # don't clobber
1: movl %fs:4,%edx # address of bottom of tls
movl \$1,%eax # potential lock value
lock xchgl %eax,$tls::stacklock(%edx) # see if we can grab it
orl %eax,%eax # it will be zero
jz 2f # if so
xorl %eax,%eax # nope. not zero
call _low_priority_sleep # sleep
jmp 1b # and loop
2: movl \$-4,%eax # now decrement aux stack
xadd %eax,$tls::stackptr(%edx) # and get pointer
# xorl %ebx,%ebx
movl \$0x41774177,%ebx
xchgl %ebx,-4(%eax) #
xchgl %ebx,8(%esp)
decl $tls::stacklock(%edx) # release lock
popl %eax
popl %edx
ret
.global __ZN11_threadinfo3popEv
__ZN11_threadinfo3popEv:
.global __ZN7_cygtls3popEv
__ZN7_cygtls3popEv:
1: pushl %ebx
pushl %edx # FIXME: needed?
movl %eax,%edx
movl \$-4,%ebx
xadd %ebx,$tls::pstackptr(%edx)
xorl %eax,%eax
# xorl %eax,%eax
movl 8(%esp),%eax
xchgl %eax,-4(%ebx)
popl %edx # FIXME: needed?
popl %ebx
ret
.global __ZN11_threadinfo4lockEv
__ZN11_threadinfo4lockEv:
pushl %ebx
movl %eax,%ebx
.global __ZN7_cygtls4lockEv
__ZN7_cygtls4lockEv:
pushl %edi
movl %eax,%edi
1: movl \$1,%eax
lock xchgl %eax,$tls::pstacklock(%ebx)
cmpl %eax,%eax
lock xchgl %eax,$tls::pstacklock(%edi)
orl %eax,%eax
jz 2f
xorl %eax,%eax
call _low_priority_sleep
jmp 1b
2: xorl \$1,%eax
popl %ebx
2: popl %edi
ret
.global __ZN11_threadinfo6unlockEv
__ZN11_threadinfo6unlockEv:
.global __ZN7_cygtls6unlockEv
__ZN7_cygtls6unlockEv:
decl $tls::pstacklock(%eax)
ret
.global __ZN7_cygtls6lockedEv
__ZN7_cygtls6lockedEv:
movl $tls::pstacklock(%eax),%eax
ret
.global _sigreturn
.stabs "sigreturn:F(0,1)",36,0,0,_sigreturn
_sigreturn:
addl \$4,%esp # Remove argument
addl \$4,%esp # Remove argument
call _set_process_mask\@4
movl %fs:4,%ebx
cmpl \$0,$tls::sig(%ebx) # Did a signal come in?
jnz 3f # Yes, if non-zero
# cmpl \$0,$tls::sig(%ebx) # Did a signal come in?
# jnz 3f # Yes, if non-zero
1: popl %edx # saved errno
testl %edx,%edx # Is it < 0
@ -215,8 +228,7 @@ _sigdelayed:
movl \$0,$tls::sig(%ebx) # zero the signal number as a
# flag to the signal handler thread
# that it is ok to set up sigsave
4: popl %ebx
jmp *%ebx
4: ret
EOF
}
@ -229,15 +241,26 @@ sub longjmp {
.globl _longjmp
_longjmp:
1: movl %fs:4,%edx
movl \$1,%eax
lock xchgl %eax,$tls::stacklock(%edx)
orl %eax,%eax
jz 2f
xorl %eax,%eax
call _low_priority_sleep
jmp 1b
2: leal ($tls::stack)(%edx),%eax
movl %eax,($tls::stackptr)(%edx)
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%edi
movl 12(%ebp),%eax
testl %eax,%eax
jne 0f
jne 3f
incl %eax
0:
movl %eax,0(%edi)
3: movl %eax,0(%edi)
movl 24(%edi),%ebp
pushfl
popl %ebx
@ -250,14 +273,12 @@ _longjmp:
movw %ax,%es
movw 40(%edi),%ax
movw %ax,%gs
movl %fs:4,%eax
leal ($tls::stack)(%eax),%edx
movl %edx,($tls::stackptr)(%eax)
movl 0(%edi),%eax
movl 4(%edi),%ebx
movl 8(%edi),%ecx
movl 12(%edi),%edx
movl 16(%edi),%esi
decl $tls::stacklock(%edx)
movl 12(%edi),%edx
movl 20(%edi),%edi
popfl
ret

View File

@ -27,7 +27,7 @@ HANDLE sync_startup;
static void WINAPI
threadfunc_fe (VOID *arg)
{
_threadinfo::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg);
_cygtls::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg);
}
static DWORD WINAPI

View File

@ -318,7 +318,7 @@ low_priority_sleep (DWORD secs)
if (!secs && wincap.has_switch_to_thread ())
{
for (int i = 0; i < 10; i++)
for (int i = 0; i < 3; i++)
SwitchToThread ();
}
else

View File

@ -58,7 +58,7 @@ class vfork_save
public:
int pid;
DWORD frame[100];
_threadinfo tls;
_cygtls tls;
char **vfork_ebp;
char **vfork_esp;
int ctty;

View File

@ -30,6 +30,7 @@ details. */
#include "shared_info.h"
#include "cygheap.h"
#include "fhandler.h"
#include "cygmalloc.h"
static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0};
@ -755,22 +756,14 @@ winpids::enum9x (bool winpid)
return nelem;
}
NO_COPY CRITICAL_SECTION winpids::cs;
void
winpids::set (bool winpid)
{
EnterCriticalSection (&cs);
__malloc_lock ();
npids = (this->*enum_processes) (winpid);
if (pidlist)
pidlist[npids] = 0;
LeaveCriticalSection (&cs);
}
void
winpids::init ()
{
InitializeCriticalSection (&cs);
__malloc_unlock ();
}
DWORD

View File

@ -179,7 +179,6 @@ class winpids
DWORD enumNT (bool winpid);
DWORD enum9x (bool winpid);
void add (DWORD& nelem, bool, DWORD pid);
static CRITICAL_SECTION cs;
public:
DWORD npids;
inline void reset () { npids = 0; release (); }
@ -196,7 +195,6 @@ public:
inline _pinfo *operator [] (int i) const {return (_pinfo *) pinfolist[i];}
~winpids ();
void release ();
static void init ();
};
extern __inline pid_t

View File

@ -93,7 +93,7 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
rem = 0;
if (rc == WAIT_OBJECT_0)
{
(void) call_signal_handler_now ();
(void) _my_tls.call_signal_handler ();
set_errno (EINTR);
res = -1;
}
@ -302,7 +302,7 @@ kill_pgrp (pid_t pid, siginfo_t& si)
found++;
}
if (killself && kill_worker (myself->pid, si))
if (killself && !exit_state && kill_worker (myself->pid, si))
res = -1;
if (!found)
@ -341,7 +341,7 @@ abort (void)
set_signal_mask (sig_mask);
raise (SIGABRT);
(void) call_signal_handler_now (); /* Call any signal handler */
(void) _my_tls.call_signal_handler (); /* Call any signal handler */
do_exit (1); /* signal handler didn't exit. Goodbye. */
}

View File

@ -668,7 +668,7 @@ sig_send (_pinfo *p, int sig)
If sending to this process, wait for notification that a signal has
completed before returning. */
int __stdcall
sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls)
sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
{
int rc = 1;
bool its_me;
@ -747,7 +747,7 @@ sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls)
if (!pack.si.si_uid)
pack.si.si_uid = myself->uid;
pack.pid = myself->pid;
pack.tls = (_threadinfo *) tls;
pack.tls = (_cygtls *) tls;
if (wait_for_completion)
{
pack.wakeup = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
@ -816,7 +816,7 @@ sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls)
}
if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
call_signal_handler_now ();
_my_tls.call_signal_handler ();
out:
if (pack.wakeup)

View File

@ -54,7 +54,7 @@ struct sigpacket
{
siginfo_t si;
pid_t pid;
class _threadinfo *tls;
class _cygtls *tls;
sigset_t *mask;
union
{
@ -91,9 +91,8 @@ void __stdcall subproc_init ();
void __stdcall sigproc_terminate ();
bool __stdcall proc_exists (_pinfo *) __attribute__ ((regparm(1)));
bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1)));
int __stdcall sig_send (_pinfo *, siginfo_t&, class _threadinfo *tls = NULL) __attribute__ ((regparm (3)));
int __stdcall sig_send (_pinfo *, siginfo_t&, class _cygtls *tls = NULL) __attribute__ ((regparm (3)));
int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2)));
void __stdcall signal_fixup_after_fork ();
void __stdcall signal_fixup_after_exec ();
void __stdcall wait_for_sigthread ();
void __stdcall sigalloc ();

View File

@ -69,8 +69,10 @@ int
muto::acquire (DWORD ms)
{
DWORD this_tid = GetCurrentThreadId ();
#if 0
if (exiting_thread)
return this_tid == exiting_thread;
#endif
if (tid != this_tid)
{
@ -113,8 +115,6 @@ int
muto::release ()
{
DWORD this_tid = GetCurrentThreadId ();
if (exiting_thread)
return this_tid == exiting_thread;
if (tid != this_tid || !visits)
{

View File

@ -461,7 +461,7 @@ readv (int fd, const struct iovec *const iov, const int iovcnt)
}
out:
if (res >= 0 || get_errno () != EINTR || !call_signal_handler_now ())
if (res >= 0 || get_errno () != EINTR || !_my_tls.call_signal_handler ())
break;
set_errno (e);
}

View File

@ -23,6 +23,7 @@ details. */
#include "cygwin/version.h"
#include "perprocess.h"
#include "sigproc.h"
#include "cygtls.h"
#include <sys/termios.h>
/* tcsendbreak: POSIX 7.2.2.1 */
@ -146,7 +147,7 @@ tcsetattr (int fd, int a, const struct termios *t)
e = get_errno ();
break;
case bg_signalled:
if (call_signal_handler_now ())
if (_my_tls.call_signal_handler ())
continue;
res = -1;
/* fall through intentionally */

View File

@ -348,7 +348,7 @@ private:
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
class _threadinfo;
class _cygtls;
class pthread: public verifyable_object
{
public:
@ -360,7 +360,7 @@ public:
bool valid;
bool suspended;
int cancelstate, canceltype;
_threadinfo *cygtls;
_cygtls *cygtls;
HANDLE cancel_event;
pthread_t joiner;

View File

@ -15,6 +15,7 @@ details. */
#include "sigproc.h"
#include "perthread.h"
#include "thread.h"
#include "cygtls.h"
/* This is called _wait and not wait because the real wait is defined
in libc/syscalls/syswait.c. It calls us. */
@ -99,7 +100,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
if (w->status == -1)
{
set_sig_errno (EINTR);
call_signal_handler_now ();
_my_tls.call_signal_handler ();
sawsig = true;
res = -1;
}
@ -114,7 +115,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
*status = w->status;
done:
if (!sawsig || !call_signal_handler_now ())
if (!sawsig || !_my_tls.call_signal_handler ())
break;
}

View File

@ -239,7 +239,7 @@ extern "C" int try_to_debug (bool waitloop = 1);
void set_file_api_mode (codepage_type);
extern int cygwin_finished_initializing;
extern bool cygwin_finished_initializing;
/**************************** Miscellaneous ******************************/