Date: Sat, 3 Mar 2012 15:12:46 +0100 From: Tijl Coosemans <tijl@freebsd.org> To: Konstantin Belousov <kostikbel@gmail.com> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, Bruce Evans <brde@optusnet.com.au> Subject: Re: svn commit: r232275 - in head/sys: amd64/include i386/include pc98/include x86/include Message-ID: <201203031512.52057.tijl@freebsd.org> In-Reply-To: <20120303091426.GS75778@deviant.kiev.zoral.com.ua> References: <201202282217.q1SMHrIk094780@svn.freebsd.org> <20120303110551.Q1494@besplex.bde.org> <20120303091426.GS75778@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart2479442.GBbydegazq Content-Type: Text/Plain; charset="iso-8859-15" Content-Transfer-Encoding: quoted-printable On Saturday 03 March 2012 10:14:26 Konstantin Belousov wrote: > 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. Yes, being unspecified allows for the kernel to handle the saving and restoring and to install a default FP env for the handler. The compiler can also assume a default environment (unless FENV_ACCESS pragma is on) so it's probably necessary for the kernel to do so. >>> 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. >=20 > longjmp() from a signal handler has very high chance of providing > wrong CPU state for anything except basic integer registers. And the signal might have interrupted a function that isn't reentrant, so you can still only call async-signal-safe functions after the longjmp. It doesn't really leave the signal handler context. --nextPart2479442.GBbydegazq Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (FreeBSD) iF4EABEIAAYFAk9SJuMACgkQfoCS2CCgtivTsQD/V6fAtBiEJvXWDYWCDBQNmxIL eMjiHhQZlKZ7vxCcgsoA+gIAyKbKg+aNWTgHjl9AJ+vsU3np2SLYnVX3Yi+ckkk6 =dC4W -----END PGP SIGNATURE----- --nextPart2479442.GBbydegazq--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203031512.52057.tijl>