Date: Sat, 3 Mar 2012 11:14:26 +0200 From: Konstantin Belousov <kostikbel@gmail.com> To: Bruce Evans <brde@optusnet.com.au> Cc: svn-src-head@freebsd.org, Tijl Coosemans <tijl@freebsd.org>, src-committers@freebsd.org, svn-src-all@freebsd.org Subject: Re: svn commit: r232275 - in head/sys: amd64/include i386/include pc98/include x86/include Message-ID: <20120303091426.GS75778@deviant.kiev.zoral.com.ua> In-Reply-To: <20120303110551.Q1494@besplex.bde.org> References: <201202282217.q1SMHrIk094780@svn.freebsd.org> <201203012347.32984.tijl@freebsd.org> <20120302132403.P929@besplex.bde.org> <201203022231.43186.tijl@freebsd.org> <20120303110551.Q1494@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--8DtChEGCcMdSgkU2 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sat, Mar 03, 2012 at 12:02:23PM +1100, Bruce Evans wrote: > On Fri, 2 Mar 2012, Tijl Coosemans wrote: >=20 > >On Friday 02 March 2012 05:11:21 Bruce Evans wrote: > [... Lots about complications for longjmp() from a signal handler] >=20 > >Thanks, that was quite informative. C11 does say something about the > >FP env and signals now though: > > > >``When the processing of the abstract machine is interrupted by receipt > >of a signal, the values of objects that are neither lock-free atomic > >objects nor of type volatile sig_atomic_t are unspecified, as is the > >state of the floating-point environment. The value of any object > >modified by the handler that is neither a lock-free atomic object nor > >of type volatile sig_atomic_t becomes indeterminate when the handler > >exits, as does the state of the floating-point environment if it is > >modified by the handler and not restored to its original state.'' >=20 > Interesting. This is almost exactly the same as my justification for > not caring about old signal handlers getting a dirty FP state. Since > signal handlers can't do anything with static objects except write > to volatile sig_atomic_t ones, they can't do anything useful with FP. > But old standards seem to allow them to do silly things like calculate > pi to a billion decimal places and store the result encoded in an > array of about 1 billion sig_atomic_t's, or better yet, calculate > 2.0 + 2.0 and store the result in a smaller array of sig_atomic_t's. >=20 > Oops, the above doesn't clearly say of the unspecified state is for > the signal handler, or after the signal handler returns, or both. The > second sentence it only clearly says that certain objects and state > become indeterminate after bad behaviour by signal handlers. But we > want longjmp()s from signal handlers to be usually not bad behaviour. > The above at least allows them to work right. Maybe longjmp() can > determine if it is invoked in a signal handler and do the right thing > then. longjmp()s for machines that are too complicated for me have > to do sophisticated stack unwinding. This might require even more > sophisticated unwinding for signal handlers. This reminds me that > POSIX (?) weasels out of some of the complications by only requiring > a single level of nested signal handlers to work. >=20 > >This means a signal handler must not rely on the state of the FP env. > >It may install its own FP env if needed (e.g. FE_DFL_ENV), but then it > >must restore the original before returning. This allows for the > >rounding mode to be silently modified for integer conversions for > >instance. >=20 > Well, I think the kernel can't trust the signal handler to do that. It > also can't trust the compiler. The compiler can reasonably use FP for > anything it wants if this is (the compiler thinks) transparent to the > abstract machine, but the compiler can't know when the code is for a > signal handler without complicated directives. Then on x86, integer > operations may use the same SSE registers (although perhaps not mxcsr) > as FP uses, and again the compiler can't reasonably know when not to > do this. So the kernel must restore at least the shared registers, > and for SSE this means restoring using f*rstor which handles the whole > state at no extra cost. >=20 > So the interesting points for signal handlers move to: > - should signal handlers have to initialize their own state if they want > to use FP explicitly? I think they should. Might be, they should if talking about abstract C implementation, but any useful Unix (U*x, probably) implementation gives much more guarantees there. > - should signal handlers have to initialize their own state if they want > to use FP or shared registers implicitly (because the compiler wants to= )? > No. The kernel must handle this transparently, much like it does now, > and I think this makes the previous case work transparently too. The > kernel tries to do this lazily, but it doesn't do this very well (it > copies the state several times in sendsig() and sigreturn()). > - when the signal handler wants to modify the interrupted state, how does > it do this? There is minimal support for this. The easiest way to > modify it is to modify the current state and then longjmp() instead of > returning. I disagree. The most correct way is to modify ucontext_t supplied to the handler, and then return normally. There may be state grown in next generations of architecture which signal handler author is not aware. Also, on some architectures some parts of the ucontext/sigcontext can only be restored by kernel. This is true even for x86. > - how can signal handlers and debuggers even see the interrupted state? > gdb has less clue about this than it did 20 years ago. Users can > probably use debuggers to follow various pointers to the saved state > if they know more about this than signal handlers and debuggers. Signal handlers should examine ucontext_t. ptrace(2) interface on FreeBSD allows to fully examine and modify the thread CPU state. gdb indeed was not upgraded to be aware of recent FreeBSD features (and not very recent features, too). >=20 > >If longjmp is not supposed to change the FP env then, when called from > >a signal handler, either the signal handler must install a proper FP > >env before calling longjmp or a proper FP env must be installed after > >the target setjmp call. Otherwise the FP env is unspecified. >=20 > Better handle the usual case right like it used to be, without the > signal handler having to do anything, by always saving a minimal > environment in setjmp(), but now only restoring it for longjmp() in > signal handlers. The minimal environment doesn't include any normal > register on at least amd64 and i386 (except for i387 it includes the > stack and the tags -- these must be empty on return from any function > call). >=20 > Again there is a problem with transparent use of FP or SSE by the > compiler. An average SIGINT handler that doesn't want to do any > explicit FP and just wants to longjmp() back to the main loop can't > be expected to understand this stuff better than standards, kernels > and compilers and have the complications neccessary to fix up the FP > state after the compiler has transparently (it thinks) used FP or SSE. longjmp() from a signal handler has very high chance of providing wrong CPU state for anything except basic integer registers. --8DtChEGCcMdSgkU2 Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (FreeBSD) iEYEARECAAYFAk9R4PIACgkQC3+MBN1Mb4j0sQCgyUwcWmHxjoSCXcZZm4f8Z/nf pUAAoKYaNrCQmSv38bBzHDq0wwI/LGvi =T4an -----END PGP SIGNATURE----- --8DtChEGCcMdSgkU2--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120303091426.GS75778>