Skip site navigation (1)Skip section navigation (2)
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>