diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b66434600..880dab278 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2012-07-29 Christopher Faylor + + * cygtls.cc (_cygtls::reset_signal_arrived): New function. + (set_signal_arrived::~set_signal_arrived): Use reset_signal_arrived to + reset state. + * exceptions.cc (sig_handle_tty_stop): Use WAIT_SIGNALED rather than + assume we know the return from cancelable_wait. + (_cygtls::interrupt_setup): Modify to allow calling when executing in + non-cygwin code via sigdelayed. Always reset signal_arrived. + * gendef: Throughout use start_offset rather than the completely wrong + sizeof__cygtls. + (_sigdelayed): Rewrite to avoid duplication when calling the signal + handler. + (sigreturn): Delete. + * gentls_offsets: Define start_offset rather than sizeof__cygtls. + * tlsoffsets.h: Regenerate. + 2012-07-29 Christopher Faylor * fhandler_termios.cc (fhandler_termios::line_edit): Use special case diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 91517fd58..6c4740059 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -748,7 +748,7 @@ sig_handle_tty_stop (int sig) switch (cancelable_wait (sigCONT, cw_infinite, cw_sig_eintr)) { case WAIT_OBJECT_0: - case WAIT_OBJECT_0 + 1: + case WAIT_SIGNALED: myself->stopsig = SIGCONT; myself->alert_parent (SIGCONT); break; @@ -801,7 +801,7 @@ _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga) this->sig = sig; // Should always be last thing set to avoid a race - if (signal_arrived) + if (incyg && signal_arrived) SetEvent (signal_arrived); proc_subproc (PROC_CLEARWAIT, 1); @@ -1259,10 +1259,14 @@ _cygtls::call_signal_handler () while (1) { lock (); - if (sig) + if (!sig) + { + unlock (); + break; + } + + if (incyg) pop (); - else - break; debug_only_printf ("dealing with signal %d", sig); this_sa_flags = sa_flags; @@ -1272,12 +1276,12 @@ _cygtls::call_signal_handler () sigset_t this_oldmask = set_process_mask_delta (); int this_errno = saved_errno; sig = 0; + reset_signal_arrived (); unlock (); // make sure synchronized if (!(this_sa_flags & SA_SIGINFO)) { - void (*sigfunc) (int) = thisfunc; incyg = false; - sigfunc (thissig); + thisfunc (thissig); } else { @@ -1293,7 +1297,6 @@ _cygtls::call_signal_handler () set_errno (this_errno); } - unlock (); return this_sa_flags & SA_RESTART || (this != _main_tls); } diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef index 3dcea174a..5cc06f76c 100755 --- a/winsup/cygwin/gendef +++ b/winsup/cygwin/gendef @@ -162,60 +162,23 @@ __sigbe: # return here after cygwin syscall .global _sigdelayed _sigdelayed: - pushl %ebp - movl %esp,%ebp + pushl %ebp + movl %esp,%ebp pushf - pushl %esi - pushl %edi - pushl %edx - pushl %ecx - pushl %ebx - pushl %eax - movl %fs:4,%ebx -1: movl \$1,%eax - xchgl %eax,$tls::stacklock(%ebx) - movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock - # If %eax is 1 then someone else has - # the lock but we want to flag that - # we're waiting for it. If %eax is 0 - # then we're not spinning and 0 will - # reflect that. - testl %eax,%eax - jz 2f - call _yield - jmp 1b -2: incl $tls::incyg(%ebx) - movl $tls::sig(%ebx),%eax - testl %eax,%eax - jz leave # call_signal_handler may have beat us - # to it - pushl $tls::saved_errno(%ebx) # saved errno - call _set_process_mask_delta - pushl %eax + pushl %esi + pushl %edi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl %fs:4,%ebx # get tls + pushl $tls::saved_errno(%ebx) # saved errno - # fill out handler arguments - xorl %eax,%eax # ucontext_t (currently not set) - pushl %eax - leal $tls::infodata(%ebx),%eax - pushl %eax # siginfo - pushl $tls::sig(%ebx) # signal number - - pushl \$_sigreturn # where to return - pushl $tls::func(%ebx) # user-supplied signal func - 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: decl $tls::incyg(%ebx) - decl $tls::stacklock(%ebx) - ret # return via signal handler - - .global _sigreturn -_sigreturn: - movl %fs:4,%ebx - incl $tls::incyg(%ebx) - addl \$12,%esp # remove arguments - call _set_process_mask\@4 + movl \$$tls::start_offset,%eax # point to beginning + addl %ebx,%eax # of tls block + call __ZN7_cygtls19call_signal_handlerEv # call handler + movl %fs:4,%ebx # reget tls 1: movl \$1,%eax # potential lock value xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock @@ -292,7 +255,7 @@ stabilize_sig_stack: cmpl \$0,$tls::sig(%ebx) jz 3f decl $tls::stacklock(%ebx) # unlock - movl \$-$tls::sizeof__cygtls,%eax # point to beginning + movl \$$tls::start_offset,%eax # point to beginning addl %ebx,%eax # of tls block call __ZN7_cygtls19call_signal_handlerEv jmp 1b diff --git a/winsup/cygwin/gentls_offsets b/winsup/cygwin/gentls_offsets index 17deb41fd..de9f1b993 100755 --- a/winsup/cygwin/gentls_offsets +++ b/winsup/cygwin/gentls_offsets @@ -60,7 +60,7 @@ main(int argc, char **argv) # define poffset(f) (((char *) &(foo->f)) - ((char *) foo)) EOF print TMP 'puts ("//;# autogenerated: Do not edit.\n");', "\n\n"; - print TMP "printf (\"//; \$tls::sizeof_$struct = %d;\\n\", sizeof($struct\));\n"; + print TMP "printf (\"//; \$tls::start_offset = -%d;\\n\", CYGTLS_PADSIZE);\n"; for my $f (@fields) { print TMP ' printf ("//; $tls::', $f, ' = %d;\n", ', "offset($f));\n"; print TMP ' printf ("//; $tls::p', $f, ' = %d;\n", ', "poffset($f));\n"; diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index 3acd27a19..1ab4559b9 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -1,6 +1,6 @@ //;# autogenerated: Do not edit. -//; $tls::sizeof__cygtls = 4048; +//; $tls::start_offset = -12700; //; $tls::locals = -12700; //; $tls::plocals = 0; //; $tls::local_clib = -11236;