* cygtls.h (CYGTLS_INITIALIZED): Change to a little more unlikely value.

(CYGTLSMAGIC): Delete.
* dcrt0.cc (dll_crt0_0): Call sigproc_init during init startup.
(_dll_crt0): Don't worry about sync_startup.  Just wait for sigthread here.
* dll_init.cc (cygwin_detach_dll): Only pick up tls version of retaddr if we
have a valid tls.
* fork.cc (frok::child): Remove sigproc_init initialization since it happens
much earlier now.
* gendef: Recognize SIGFE_MAYBE.
(fefunc): Generate calls to _sigfe_maybe, if appropriate.
(_sigfe_maybe): New function.
* init.cc (search_for): Always initialize search_for, even on fork.
(calibration_thread): Delete.
(calibration_id): Delete.
(prime_threads): Delete.
(munge_threadfunc): Remove calibration_thread special case.  Avoid calling
thread function if we haven't yet hit the "search_for" thread.
(dll_entry): Remove prime_threads call.  Only call munge_threadfunc when
hwait_sig is active.  Ditto.  for _my_tls.remove ();
* sigproc.cc (hwait_sig): Make global.
(sigproc_init): Don't bother with sync_startup.
(sig_send): Treat flush as a no-op when signals are held.
(wait_sig): Cause signals to be held after fork.
This commit is contained in:
Christopher Faylor 2006-03-12 23:57:05 +00:00
parent 0b9632d1fa
commit 51f90b2f01
9 changed files with 80 additions and 70 deletions

View File

@ -1,3 +1,29 @@
2006-03-12 Christopher Faylor <cgf@timesys.com>
* cygtls.h (CYGTLS_INITIALIZED): Change to a little more unlikely value.
(CYGTLSMAGIC): Delete.
* dcrt0.cc (dll_crt0_0): Call sigproc_init during init startup.
(_dll_crt0): Don't worry about sync_startup. Just wait for sigthread here.
* dll_init.cc (cygwin_detach_dll): Only pick up tls version of retaddr
if we have a valid tls.
* fork.cc (frok::child): Remove sigproc_init initialization since it
happens much earlier now.
* gendef: Recognize SIGFE_MAYBE.
(fefunc): Generate calls to _sigfe_maybe, if appropriate.
(_sigfe_maybe): New function.
* init.cc (search_for): Always initialize search_for, even on fork.
(calibration_thread): Delete.
(calibration_id): Delete.
(prime_threads): Delete.
(munge_threadfunc): Remove calibration_thread special case. Avoid
calling thread function if we haven't yet hit the "search_for" thread.
(dll_entry): Remove prime_threads call. Only call munge_threadfunc
when hwait_sig is active. Ditto. for _my_tls.remove ();
* sigproc.cc (hwait_sig): Make global.
(sigproc_init): Don't bother with sync_startup.
(sig_send): Treat flush as a no-op when signals are held.
(wait_sig): Cause signals to be held after fork.
2006-03-09 Corinna Vinschen <corinna@vinschen.de> 2006-03-09 Corinna Vinschen <corinna@vinschen.de>
* syscalls.cc (rename): Move existance check for oldpath further up * syscalls.cc (rename): Move existance check for oldpath further up

View File

@ -23,8 +23,7 @@ details. */
typedef unsigned int SOCKET; typedef unsigned int SOCKET;
#endif #endif
#define CYGTLS_INITIALIZED 0x43227 #define CYGTLS_INITIALIZED 0xc763173f
#define CYGTLSMAGIC "D0Ub313v31nm&G1c?";
#ifndef CYG_MAX_PATH #ifndef CYG_MAX_PATH
# define CYG_MAX_PATH 260 # define CYG_MAX_PATH 260

View File

@ -301,8 +301,8 @@ cygwin_conv_to_posix_path SIGFE
cygwin32_conv_to_posix_path = cygwin_conv_to_posix_path SIGFE cygwin32_conv_to_posix_path = cygwin_conv_to_posix_path SIGFE
cygwin_conv_to_win32_path SIGFE cygwin_conv_to_win32_path SIGFE
cygwin32_conv_to_win32_path = cygwin_conv_to_win32_path SIGFE cygwin32_conv_to_win32_path = cygwin_conv_to_win32_path SIGFE
cygwin_detach_dll SIGFE cygwin_detach_dll SIGFE_MAYBE
cygwin32_detach_dll = cygwin_detach_dll SIGFE cygwin32_detach_dll = cygwin_detach_dll SIGFE_MAYBE
cygwin_dll_init NOSIGFE cygwin_dll_init NOSIGFE
endprotoent = cygwin_endprotoent SIGFE endprotoent = cygwin_endprotoent SIGFE
endservent = cygwin_endservent SIGFE endservent = cygwin_endservent SIGFE

View File

@ -750,6 +750,8 @@ dll_crt0_0 ()
DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL, DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation, TokenImpersonation, SecurityImpersonation, TokenImpersonation,
&hProcImpToken); &hProcImpToken);
/* Initialize signal/subprocess handling. */
sigproc_init ();
debug_printf ("finished dll_crt0_0 initialization"); debug_printf ("finished dll_crt0_0 initialization");
} }
@ -835,9 +837,6 @@ dll_crt0_1 (char *)
/* Initialize user info. */ /* Initialize user info. */
uinfo_init (); uinfo_init ();
/* Initialize signal/subprocess handling. */
sigproc_init ();
/* Connect to tty. */ /* Connect to tty. */
tty_init (); tty_init ();
@ -924,7 +923,6 @@ dll_crt0_1 (char *)
/* Flush signals and ensure that signal thread is up and running. Can't /* Flush signals and ensure that signal thread is up and running. Can't
do this for noncygwin case since the signal thread is blocked due to do this for noncygwin case since the signal thread is blocked due to
LoadLibrary serialization. */ LoadLibrary serialization. */
wait_for_sigthread ();
ld_preload (); ld_preload ();
if (user_data->main) if (user_data->main)
cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr)); cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
@ -950,14 +948,8 @@ initialize_main_tls (char *padding)
extern "C" void __stdcall extern "C" void __stdcall
_dll_crt0 () _dll_crt0 ()
{ {
extern HANDLE sync_startup;
extern DWORD threadfunc_ix; extern DWORD threadfunc_ix;
if (sync_startup != INVALID_HANDLE_VALUE) wait_for_sigthread ();
{
WaitForSingleObject (sync_startup, INFINITE);
CloseHandle (sync_startup);
}
if (!threadfunc_ix) if (!threadfunc_ix)
system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems."); system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");

View File

@ -404,7 +404,12 @@ dll_noncygwin_dllcrt0 (HMODULE h, per_process *p)
extern "C" void extern "C" void
cygwin_detach_dll (dll *) cygwin_detach_dll (dll *)
{ {
dlls.detach ((HANDLE) _my_tls.retaddr ()); HANDLE retaddr;
if (_my_tls.isinitialized ())
retaddr = (HANDLE) _my_tls.retaddr ();
else
retaddr = __builtin_return_address (0);
dlls.detach (retaddr);
} }
extern "C" void extern "C" void

View File

@ -171,8 +171,6 @@ frok::child (void *)
ForceCloseHandle1 (fork_info->forker_finished, forker_finished); ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
sigproc_init ();
pthread::atforkchild (); pthread::atforkchild ();
fixup_timers_after_fork (); fixup_timers_after_fork ();
cygbench ("fork-child"); cygbench ("fork-child");

View File

@ -1,5 +1,5 @@
#!/usr/bin/perl #!/usr/bin/perl
# Copyright 2003, 2004, 2005 Red Hat, Inc. # Copyright 2003, 2004, 2005, 2006 Red Hat, Inc.
# #
# This file is part of Cygwin. # This file is part of Cygwin.
# #
@ -43,12 +43,14 @@ for (@in) {
chomp; chomp;
if (/=/o) { if (/=/o) {
if (s/\s+NOSIGFE\s*$//) { if (s/\s+NOSIGFE\s*$//) {
} elsif (s/ SIGFE$//) { # nothing
my $func = (split(' '))[2]; } elsif (s/ SIGFE(_MAYBE)?$//) {
$sigfe{$func} = '_sigfe_' . $func; my $func = (split(' '))[2];
my $maybe = lc $1 . '_';
$sigfe{$func} = '_sigfe' . $maybe . $func;
} }
} else { } else {
my ($func, $sigfe) = m%^\s*(\S+)(?:\s+((?:NO)?SIGR?FE))?$%o; my ($func, $sigfe) = m%^\s*(\S+)(?:\s+((?:NO)?SIGFE(?:_MAYBE)?))?$%o;
if (defined($sigfe) && $sigfe =~ /^NO/o) { if (defined($sigfe) && $sigfe =~ /^NO/o) {
$_ = $func; $_ = $func;
} else { } else {
@ -83,13 +85,14 @@ close SIGFE;
sub fefunc { sub fefunc {
my $func = '_' . shift; my $func = '_' . shift;
my $fe = '_' . shift; my $fe = '_' . shift;
my $sigfe_func = ($fe =~ /^(.*)$func/)[0];
my $extra; my $extra;
my $res = <<EOF; my $res = <<EOF;
.extern $func .extern $func
.global $fe .global $fe
$fe: $fe:
pushl \$$func pushl \$$func
jmp __sigfe jmp $sigfe_func
EOF EOF
if (!$main::first++) { if (!$main::first++) {
@ -97,6 +100,18 @@ EOF
.text .text
.stabs "_sigfe:F(0,1)",36,0,0,__sigfe .stabs "_sigfe:F(0,1)",36,0,0,__sigfe
__sigfe_maybe:
pushl %ebx
pushl %edx
movl %fs:4,%ebx # location of bottom of stack
movl $tls::initialized(%ebx),%eax
cmpl \$0xc763173f,%eax # initialized?
je 1f
popl %edx
popl %ebx
popl %eax
jmp *%eax
__sigfe: __sigfe:
pushl %ebx pushl %ebx
pushl %edx pushl %edx

View File

@ -19,11 +19,9 @@ details. */
#include "ntdll.h" #include "ntdll.h"
int NO_COPY dynamically_loaded; int NO_COPY dynamically_loaded;
static char *search_for = (char *) cygthread::stub; static char NO_COPY *search_for = (char *) cygthread::stub;
unsigned threadfunc_ix[8] __attribute__((section (".cygwin_dll_common"), shared)); unsigned threadfunc_ix[8] __attribute__((section (".cygwin_dll_common"), shared));
DWORD tls_func; extern cygthread *hwait_sig;
HANDLE sync_startup;
#define OLDFUNC_OFFSET -1 #define OLDFUNC_OFFSET -1
@ -35,32 +33,6 @@ threadfunc_fe (VOID *arg)
_cygtls::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg); _cygtls::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg);
} }
static DWORD WINAPI
calibration_thread (VOID *arg)
{
ExitThread (0);
}
static DWORD calibration_id;
/* We need to know where the OS stores the address of the thread function
on the stack so that we can intercept the call and insert some tls
stuff on the stack. This function starts a known calibration thread.
When it starts, a call will be made to dll_entry which will call munge_threadfunc
looking for the calibration thread offset on the stack. This offset will
be stored and used by all executing cygwin processes. */
static void
prime_threads ()
{
if (threadfunc_ix[0])
sync_startup = INVALID_HANDLE_VALUE;
else
{
search_for = (char *) calibration_thread;
sync_startup = CreateThread (NULL, 0, calibration_thread, 0, 0, &calibration_id);
}
}
/* If possible, redirect the thread entry point to a cygwin routine which /* If possible, redirect the thread entry point to a cygwin routine which
adds tls stuff to the stack. */ adds tls stuff to the stack. */
static void static void
@ -82,14 +54,16 @@ munge_threadfunc ()
} }
} }
char *threadfunc = ebp[threadfunc_ix[0]]; if (threadfunc_ix[0])
if (threadfunc == (char *) calibration_thread)
/* no need for the overhead */;
else if (threadfunc_ix[0])
{ {
for (i = 0; threadfunc_ix[i]; i++) char *threadfunc = ebp[threadfunc_ix[0]];
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe; if (!search_for || threadfunc == search_for)
((char **) _tlsbase)[OLDFUNC_OFFSET] = threadfunc; {
search_for = NULL;
for (i = 0; threadfunc_ix[i]; i++)
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
((char **) _tlsbase)[OLDFUNC_OFFSET] = threadfunc;
}
} }
} }
@ -170,16 +144,15 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
respawn_wow64_process (); respawn_wow64_process ();
dll_crt0_0 (); dll_crt0_0 ();
prime_threads (); // this should be the last thing to happen
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
if (!sync_startup || GetCurrentThreadId () == calibration_id) if (hwait_sig)
munge_threadfunc (); munge_threadfunc ();
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
if (!sync_startup) if (hwait_sig)
_my_tls.remove (0); _my_tls.remove (0);
break; break;
} }

View File

@ -61,10 +61,10 @@ HANDLE NO_COPY signal_arrived; // Event signaled when a signal has
HANDLE NO_COPY sigCONT; // Used to "STOP" a process HANDLE NO_COPY sigCONT; // Used to "STOP" a process
Static cygthread *hwait_sig; cygthread *hwait_sig;
Static HANDLE wait_sig_inited; // Control synchronization of Static HANDLE wait_sig_inited; // Control synchronization of
// message queue startup // message queue startup
Static bool sigheld; // True if holding signals static bool sigheld; // True if holding signals
Static int nprocs; // Number of deceased children Static int nprocs; // Number of deceased children
Static char cprocs[(NPROCS + 1) * sizeof (pinfo)];// All my children info Static char cprocs[(NPROCS + 1) * sizeof (pinfo)];// All my children info
@ -475,7 +475,6 @@ create_signal_arrived ()
void __stdcall void __stdcall
sigproc_init () sigproc_init ()
{ {
extern HANDLE sync_startup;
wait_sig_inited = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); wait_sig_inited = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
ProtectHandle (wait_sig_inited); ProtectHandle (wait_sig_inited);
@ -484,7 +483,6 @@ sigproc_init ()
*/ */
sync_proc_subproc.init ("sync_proc_subproc"); sync_proc_subproc.init ("sync_proc_subproc");
sync_startup = NULL;
hwait_sig = new cygthread (wait_sig, 0, cygself, "sig"); hwait_sig = new cygthread (wait_sig, 0, cygself, "sig");
hwait_sig->zap_h (); hwait_sig->zap_h ();
@ -523,6 +521,8 @@ sig_send (_pinfo *p, int sig)
#endif #endif
return -1; return -1;
} }
else if (sig == __SIGFLUSH || sig == __SIGFLUSHFAST)
return 0;
else else
{ {
SetEvent (sigCONT); SetEvent (sigCONT);
@ -1091,8 +1091,12 @@ wait_sig (VOID *)
readsig, myself->sendsig); readsig, myself->sendsig);
sigpacket pack; sigpacket pack;
if (in_forkee)
pack.si.si_signo = __SIGHOLD;
for (;;) for (;;)
{ {
if (pack.si.si_signo == __SIGHOLD)
WaitForSingleObject (sigCONT, INFINITE);
DWORD nb; DWORD nb;
pack.tls = NULL; pack.tls = NULL;
if (!ReadFile (readsig, &pack, sizeof (pack), &nb, NULL)) if (!ReadFile (readsig, &pack, sizeof (pack), &nb, NULL))
@ -1194,8 +1198,6 @@ wait_sig (VOID *)
sigproc_printf ("signalling pack.wakeup %p", pack.wakeup); sigproc_printf ("signalling pack.wakeup %p", pack.wakeup);
SetEvent (pack.wakeup); SetEvent (pack.wakeup);
} }
if (pack.si.si_signo == __SIGHOLD)
WaitForSingleObject (sigCONT, INFINITE);
if (pack.si.si_signo == __SIGEXIT) if (pack.si.si_signo == __SIGEXIT)
break; break;
} }